Skip to content

Unify response processing and add hx-multipart extension#3911

Open
scriptogre wants to merge 9 commits into
bigskysoftware:four-devfrom
scriptogre:4.0/canonical-response-context
Open

Unify response processing and add hx-multipart extension#3911
scriptogre wants to merge 9 commits into
bigskysoftware:four-devfrom
scriptogre:4.0/canonical-response-context

Conversation

@scriptogre

@scriptogre scriptogre commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Organize ctx, and give requests and streaming extensions one swap path, one action path, and one lifecycle.

Public API

Canonical response context

event.detail.ctx = {
  request: { /* fetch options */ },
  response: { raw, status, headers },
  swap: { content, target, style, select, selectOOB, /* modifiers */ },
  actions: { trigger, pushUrl, replaceUrl, /* custom HX-* actions */ }
}
  • ctx.swap replaces flat ctx.target, ctx.swap, ctx.select, ctx.text, and related swap fields.
  • ctx.actions replaces separate history and response-header state. HX-Toast becomes actions.toast for extensions.
  • ctx.status is removed. Queue admission is tracked internally as run, queued, or dropped.

Positional htmx.swap()

await htmx.swap(html, '#messages', { style: 'beforeend' })

This replaces htmx.swap({ text, target, swap, ... }) and is closer to what we had in htmx 2.0.

Shared server actions

api.runActions({ trigger: 'saved', toast: 'Done' }, element, { ctx })
  • Adds htmx:before:actions and htmx:after:actions.
  • Adds actions to htmx.ajax() options. push and replace remain shorthands.
  • Status rules, response headers, normal requests, and streaming parts use the same executor.
  • History events no longer include detail.response, because actions can run without a response.

Explicit response lifecycle

before:request → after:request → before:response → after:response → swap → done
  • after:request means fetch resolved. The body is still unread.
  • after:response exposes the body as ctx.swap.content.
  • done replaces finally:request and fires once an admitted pipeline ends.
  • Bundled extensions, types, upgrade checks, and docs follow these semantics.

hx-multipart

New extension for streaming hypermedia, alongside hx-sse and hx-ws.

<div hx-multipart:connect="/events"></div>
Content-Type: multipart/mixed; boundary=x

--x
Content-Type: text/html
HX-Target: #status

Connected
--x--

One Fetch response can now stream ordered multipart/mixed parts through same swap and action APIs.

Brings a few public API changes for which I'd create an hx-htmx-4-beta-compat extension, which should be quite lightweight.

@scriptogre scriptogre changed the title Canonicalize response handling and add multipart streams Unify response processing across requests and streams Jul 21, 2026
@scriptogre scriptogre changed the title Unify response processing across requests and streams Unify response processing and add hx-multipart streaming Jul 22, 2026
@scriptogre scriptogre changed the title Unify response processing and add hx-multipart streaming Unify response processing and add hx-multipart extension Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant