Skip to content

Recipes

Each recipe documents the short form, the expanded HTML, the optional macro, and the server response contract. Recipes with an entry in the Needs column require an installX() from @hypermedia-components/core; the rest (”—”) are pure htmx attributes.

Get any recipe’s scaffold with npx @hypermedia-components/cli add <name>; machine-check your copy against its contract with npx @hypermedia-components/cli validate.

Every recipe page also has a Live demo — real htmx requests against a demo API served by this site’s Worker, implementing that recipe’s server response contract under api/recipes/<name>/.

RecipeYou need to…Needs
Mutating formpost a form with inline 4xx errors, a success redirect, and a double-submit guardinstallFieldErrors()
Field errorsdistribute a server-sent validation-error fragment to the fields it namesinstallFieldErrors()
Multi-step formbuild a wizard — the server owns the step and the draft; whole-step swaps
Confirm actionguard a destructive request behind a confirmation dialoginstallConfirm()
Undo deletedelete immediately (optimistic delete) — the toast’s Undo restores the row within a grace periodinstallToast()
Request actionfire an htmx request from a button with a busy state
Inline editswap a value between display and edit modes in place (click-to-edit)
File uploadupload multipart files with a live progress bar and an out-of-band form resetinstallUploadProgress()
Datagrid bulk actionsselect rows with checkboxes and POST one action against all of theminstallDatagridActions()
Transferassign / unassign across a dual listbox as a server round trip — whole-form swaps, zero custom JS
Cascading selectchain dependent selects for hierarchical selection; each change loads the next level
Copy to clipboardcopy a read-only value (URL, token, snippet) to the clipboardinstallCopy()
RecipeYou need to…Needs
Live searchsearch as you type (typeahead) — debounced input swaps the results
Filter popoverhost a filter form in a popover that closes on successinstallClosePopover()
RecipeYou need to…Needs
Lazy paneldefer loading a panel until it is revealed
Lazy treeload a tree branch’s children on first expandinstallTree()
Data regionrefresh a region on HX-Trigger invalidations (self-refreshing region)
Datagrid paginationpage a datagrid server-side with out-of-band row swapsinstallDatagrid()
RecipeYou need to…Needs
SSE updatespush fragment updates from the server over Server-Sent Events — named events and out-of-band pushes
SSE toastturn SSE events with JSON payloads into allow-listed DOM events; toasts work unchangedinstallSseDispatch()
RecipeYou need to…Needs
Chat messagesappend a chat exchange — user message + aria-busy assistant placeholder — from one composer POST, with a 422 path that never pollutes the transcriptinstallChatScroll()
Streaming responsefill the assistant placeholder over SSE — chunks append while aria-busy defers the announcement; done swaps in the final message and closes the stream
RecipeYou need to…Needs
Chartupgrade a server-sent data table into an Observable Plot SVG chartinstallChart() + Plot
RecipeYou need to…Needs
Remote dialogload a dialog’s (modal’s) contents from the server on openinstallRemoteDialog() + installCloseDialog()
Toastfire toast notifications (snackbars) from the client or an HX-Trigger headerinstallToast()