Mutations return 204; SSE refreshes the lists¶
The conventional HTMX mutation returns the updated list partial for the client to swap in.
We instead return 204 No Content with an HX-Trigger: closeDialog header, and rely on the
SSE "items" channel to tell every connected client to re-fetch its list.
The app is used by two people on several devices at once, so a mutation has to reach screens other than the one that caused it regardless. Returning the partial as well would give the acting device a different, earlier refresh path than everyone else's — two code paths to keep in agreement, and a visible inconsistency whenever they drift.
Consequences¶
- A mutation that fails to emit on the SSE channel leaves every client stale, including the one that performed it. The emit is not optional.
- Validation failures are the exception: they re-render the sheet partial with
status=400, which swaps into the open sheet.
Amendment (htmx 4 migration)¶
The decision above stands unchanged; one consequence no longer does.
Under HTMX 2 the 400 re-render needed help: HTMX skipped 4xx swaps by default, so
frontend/main.js forced the swap in an htmx:beforeSwap handler. htmx 4 swaps every
response except 204 and 304 (htmx.config.noSwap), so that handler was redundant and
has been deleted. Nothing replaced it.
The 204 No Content + HX-Trigger: closeDialog half of the decision is untouched: htmx 4
still reads the response header, and it dispatches the event on the request's source element
with bubbles, from a code path that runs even for a 204 — so it reaches the document-level
listener from inside a <dialog> exactly as before.