multipart/mixed

Disclaimer: this summary is my understanding of how the team discovered this and thus if there are any inaccuracies, they are mine.

hx-multipart is an htmx extension that blends html streaming with htmx goodness.

What is html streaming?

It was observed about 10 years ago that html could be streamed to the browser to create a more dynamic feel to webpages.

Note:

  • php or another server side language can do html streaming, if buffering is turned off.

  • if there is a webserver involved, buffering may also need to be turned off.

  • the document will be appended to.

  • for example, output.php, results in 'Hello World!':

<?php

        echo "Hello ";

        ob_flush();
        flush();

        sleep(5);

        echo "World!";

What is multipart/mixed?

It is a content-type that allows streaming of various content.

  • supposedly created in 1992 to allow mixed content for email.

  • Christian Tanul from the htmx team discovered that it works over http as well.

ping-1.php doesn’t work. Compare with ping.php which works.

<?php

/*
*Purpose:* to test streaming html.

*Author:* Marlon A. Griffith
*Created:* Wed. 2026-09-09

*Modified:*
*/

header( 'HTTP/1.1 200 OK' );
header( 'Content-Type: multipart/mixed; boundary=...' );

echo <<<BODY

--...
Content-Type: text/html

P
--...
Content-Type: text/html

Po
--...
Content-Type: text/html

Pon
--...
Content-Type: text/html

Pong
--...--

BODY;

What is the htmx goodness?

Christian, Michael West and Carson Gross developed the htmx extension - hx-multipart, which provides the javascript shiv to read the stream and insert into the dom depending on the content type and target.

htmx principles reminder

Motivation:

    Why should only <a> & <form> be able to make HTTP requests?
    Why should only click & submit events trigger them?
    Why should only GET & POST methods be available?
    Why should you only be able to replace the entire screen?

By removing these constraints, htmx completes HTML as a hypertext.

The last principle emphasizes locality of behaviour. To me this means grouping simple behaviour and styling together to create light html components directly in your html page. From https://htmx.org an example:

<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.10/dist/htmx.min.js"
 integrity="sha384-H5SrcfygHmAuTDZphMHqBJLc3FhssKjG7w/CeCpFReSfwBWDTKpkzPP8c+cLsK+V"
          crossorigin="anonymous"></script>

<!-- Active Search -->
<input type="search" name="search"
       hx-post="/search"
       hx-trigger="input changed delay:200ms, keyup[key=='Enter'], load"
       hx-target="#results"
       hx-indicator=".htmx-indicator">

<tbody id="results"></tbody>

What is the result?

hx-multipart becomes a streaming process which allows an usable page, while images loaded, i.e. it is hydration using basic http. See the two sample files below:

htmx-multipart.html

<!DOCTYPE html>
<html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width">

     <title>HTMX Multipart/mixed Streaming Test</title>

     <!-- Include µCSS from CDN -->
     <link rel="stylesheet" href="https://unpkg.com/@digicreon/mucss/dist/mu.fuchsia.css">

     <!-- from filesystem
     <script src="htmx.min.js"></script>
     <script src="hx-multipart.min.js"></script> -->
     <script src="https://cdn.jsdelivr.net/npm/htmx.org@4.0.0/dist/htmx.min.js"></script>
     <script src="https://cdn.jsdelivr.net/gh/bigskysoftware/htmx@four/src/ext/hx-multipart.min.js"></script>

   </head>
   <body>

     <main>
       <p>Converted from four.htmx.org for php using the hx-multipart extension.</p>
       <button hx-get="ping.php">
        Ping
      </button>
      <p id="para1">Paragraph 1</p>
      <p id="para2">Paragraph 2</p>
      <p id="para3">Paragraph 3</p>
      <p id="para4">Paragraph 4</p>
      <p id="notes">no Notifications here... move on.</p>

      <p>Browser only call.</p>
      <p>This is sent but is not updated by hx-multipart</p>
      <button hx-get="ping-1.php">
       Ping browser
     </button>
     </main>

   </body>
</html>

ping.php

<?php

// from ai summary when I was researching Tues. 2026-09-15 night
// Works!
header('Content-Type: multipart/mixed; boundary="..."');

$boundary = "...";

$response = "--$boundary\r\n";
$response .= "Content-Type: text/html\r\n";
$response .= "HX-Target: #para1\r\n\r\n";
$response .= "P\r\n";
$response .= "--$boundary\r\n";
$response .= "Content-Type: text/html\r\n";
$response .= "HX-Target: #para2\r\n\r\n";
$response .= "o\r\n";
$response .= "--$boundary\r\n";
$response .= "Content-Type: text/html\r\n";
$response .= "HX-Target: #para3\r\n\r\n";
$response .= "n\r\n";
$response .= "--$boundary\r\n";
$response .= "Content-Type: text/html\r\n";
$response .= "HX-Target: #para4\r\n\r\n";
$response .= "g\r\n";
$response .= "--$boundary\r\n";
$response .= "Content-Type: text/html\r\n";
$response .= "HX-Target: #notes\r\n\r\n";
$response .= "Notification: all done.\r\n";
$response .= "--$boundary--"; // End the multipart response

echo $response;

Christian used it to build the prototype game hyperspace. It is sort of a 3D tetris built with hx-multipart, hx-live and a posgresql database.

Why wouldn’t you use server sent events (sse) for this?

sse can only send text, i.e. html, text or json.

why would you want to do that?

  • consider a webpage like Pinterest or any other photogallery.

    • it can take a long time to load the page depending on how many images there are.

    • streaming allows partial functionality while the page loads.

  • hx-multipart has synchronous and asynchronous loading options.

  • the html and php code is very simple

    • see htmx-multipart.html and ping.php, above, as a hello world example.

Caveat:

  • this is one way streaming - from the server to the browser.

  • the line endings must be '\r\n'

Conclusion

This is another tool in htmx’s belt for updating the dom, along with:

htmx Feature Communication Model Direction Updates Content Types

hx-target and hx-select

Single Request/Response

Server → Browser

Single id based

text, html, svg and json

out of band (oob) swaps

Single Request/Response

Server → Browser

Multiple simple id based

text, html, svg and json

hx-multipart

Single Request/Response

Server → Browser

Multiple complex

text, html, svg, json, image, audio, video, etc.

the <partial> template

Single Request/Response

Continuous Server → Browser

Multiple complex

text, html, svg and json

Server Sent Events

Continuous Events

One way Server → Browser

Multiple complex

text, html, svg and json

Web Sockets

Continuous Channel

Bidirectional Server → Browser

Multiple complex

text, html, svg and json?