Back to I AM A TEAPOT

November 16 2023

text/event-stream All the Way Down

SSE is a really great idea. With a single request you can create a server driven stream of events. Using this for driving Datastar’s HTMX like fragments plugin is a natural fit. The only problem is that SSE doesn’t support anything but the GET method. This means that you can’t use SSE to send data to the server. This is a problem for HTMX, because HTMX uses the POST method to send data to the server. So, what to do?

The Solution

text/event-stream MIME type is the underlying protocol for Server Sent Events. It is a simple protocol that is easy to implement. It is also a simple protocol to extend. So, we can extend it to support POST,PUT,PATCH,DELETE requests. The majority of the code is in how your read and buffer results from fetch API calls. The rest is just a matter of parsing the request and sending the appropriate response. The great part is the server side still just uses the same libraries or helpers that it would use for SSE.

This means every data fragment is an OOB in HTMX terms.

event: datastar-fragment id: 92680296792588350 data: merge morph_element data:
settle 0 data: fragment
<div id="lazy_tabs">
  <div class="tabs tabs-bordered">
    <button
      id="tab_0"
      class="tab tab-active"
      data-on-click="$$get('/examples/lazy_tabs/data?tabId=0')"
    >
      Tab 0</button
    ><button
      id="tab_1"
      class="tab"
      data-on-click="$$get('/examples/lazy_tabs/data?tabId=1')"
    >
      Tab 1</button
    ><button
      id="tab_2"
      class="tab"
      data-on-click="$$get('/examples/lazy_tabs/data?tabId=2')"
    >
      Tab 2</button
    ><button
      id="tab_3"
      class="tab"
      data-on-click="$$get('/examples/lazy_tabs/data?tabId=3')"
    >
      Tab 3</button
    ><button
      id="tab_4"
      class="tab"
      data-on-click="$$get('/examples/lazy_tabs/data?tabId=4')"
    >
      Tab 4</button
    ><button
      id="tab_5"
      class="tab"
      data-on-click="$$get('/examples/lazy_tabs/data?tabId=5')"
    >
      Tab 5</button
    ><button
      id="tab_6"
      class="tab"
      data-on-click="$$get('/examples/lazy_tabs/data?tabId=6')"
    >
      Tab 6</button
    ><button
      id="tab_7"
      class="tab"
      data-on-click="$$get('/examples/lazy_tabs/data?tabId=7')"
    >
      Tab 7
    </button>
  </div>
  <div id="tab_content" class="p-4 shadow-lg bg-base-200">
    <p>
      Voluptas minima totam qui est ut. Fuga accusantium sint voluptatem nihil
      asperiores. Saepe illo eveniet consequatur voluptatibus maxime. Voluptates
      aut illo est recusandae omnis. Sit iure sunt et provident ut. Velit
      quibusdam repellendus sed fugiat et.
    </p>
    <p>Possimus molestiae quaerat incidunt sapiente ipsam.</p>
    <p>
      Autem quis quia libero expedita accusantium. Tempora quia qui voluptatem
      inventore repellendus. Sit officia aliquam laudantium similique delectus.
      Non eos rerum quisquam voluptas ullam. Placeat dolores facere laborum non
      fugit. Est neque earum eum aut non. Quia voluptas rerum quia perspiciatis
      harum. Voluptatem et mollitia repellendus sed dicta.
    </p>
    <p>
      Eos rerum harum hic sunt omnis. Est veniam est aut ex consequuntur. Est
      qui inventore assumenda enim perferendis. Libero tenetur nisi quasi
      recusandae rerum. Consectetur iste distinctio id accusamus quo. Enim
      voluptatum rerum voluptas rem harum.
    </p>
    <p>
      Consectetur eveniet ex quaerat velit et. Sint nesciunt temporibus minus
      deserunt perferendis. Molestiae modi nulla ratione ea sapiente. Laboriosam
      sed voluptatibus quo tenetur repudiandae. Accusamus culpa ipsa ab nihil
      suscipit. Mollitia veritatis id consequatur dolorem rerum. Ratione atque
      quia illum sunt repudiandae. Voluptate qui temporibus laborum nobis
      officia. Voluptate unde sed culpa dolorem minus.
    </p>
  </div>
</div>

This is easy to debug, easy to create, and still makes use of middlewares like compression. It’s just HTML fragments but wrapped in a protocol that allows for streaming and server driven events.

Next ANOTHER DEPENDENCY