htmx Endpoint Design
Use this skill when the hard part is the server/browser contract: which element makes the request, which endpoint handles it, what HTML comes back, and where that HTML lands.
Contract First
Define the endpoint contract before writing attributes:
- Request source: the element that sends the request.
- HTTP method:
GET for safe reads; POST, PUT, PATCH, or DELETE for mutations when the server/framework supports them.
- Input data: normal form fields, included elements, path params, or explicit values.
- Response shape: full page, partial fragment, empty response, redirect, or event-only response.
- Swap target: the element to replace or update.
- Follow-up effects: events, out-of-band fragments, URL changes, focus changes, and messages.
Endpoint Workflow
- Run the same auth, permission, and data-loading logic for full-page and htmx requests.
- Branch late on whether the request is an htmx request.
- Reuse the same partial in the full-page render and the htmx response.
- Return a fragment whose root matches the intended
hx-target when using outerHTML.
- Use response headers or events for cross-component effects instead of coupling unrelated targets.
- Test the normal request and the htmx request separately.
Requests
- Prefer normal form encoding so server validation, CSRF, and file limitations are explicit.
- Keep mutation requests same-origin unless the project has a deliberate CORS and CSRF design.
- Use
hx-include when one control must submit data from a nearby form or filter panel.
- Use
hx-vals only for small explicit values. Avoid secrets and avoid executable js: values; prefer form fields, hidden inputs, or URL parameters instead.
- Debounce or throttle chatty triggers such as
keyup, input, and polling.
- Use real links and forms when possible, then enhance them with htmx attributes.
Responses
Choose the smallest response that keeps the UI honest:
| Situation |
Response |
| Replace one component |
Return that component fragment |
| Update several unrelated components |
Return primary fragment plus hx-swap-oob fragments |
| Mutation succeeds and another element should refresh |
Return 204 plus an event/header when supported |
| Validation fails |
Return the bound form fragment with errors |
| Browser should navigate |
Return a normal redirect for non-htmx, and an htmx redirect/location response for htmx |
| Server needs a different target/swap |
Use framework helpers or htmx response headers where available |
Targeting And Swapping
- Use stable IDs for durable targets and keep them unique.
- Use
hx-target="this" for self-contained components.
- Use
outerHTML when replacing the target element itself.
- Use
innerHTML when preserving the target shell and replacing only its contents.
- Use insert swaps such as
beforeend for appending rows, log entries, or feed items.
- Use
hx-select when the server returns a larger document but the client should extract one fragment.
- Do not swap a parent that contains long-lived local browser state unless that state is intentionally reset.
Out-Of-Band Updates
Use out-of-band swaps for shared chrome and secondary facts:
- flash messages
- cart counts
- notification badges
- summary totals
- list counters
- modal shells outside the main target
Keep out-of-band fragments small and predictable. If many out-of-band updates are required for one action, consider returning the larger owner component instead.
Events
Use events to decouple server results from browser-local behavior:
- Fire a server-triggered event after save/delete when another component should refresh.
- Listen for htmx lifecycle events for instrumentation, custom confirmation, and cleanup.
- Use custom events as boundaries between htmx and Alpine, plain JavaScript, or
_hyperscript.
- Keep event names domain-specific, such as
invoice:saved or filters:changed.
Status Codes
- Use
200 for normal fragment replacement, including many invalid form responses.
- Use
204 when no visible fragment should be swapped.
- Use redirects deliberately; do not let htmx silently insert a login page into a small target.
- For polling, use the framework or htmx convention that stops polling when the server says the job is done.
Testing Checklist
- Assert status code and key response headers.
- Assert the partial contains the intended root element.
- Assert the partial omits full-page chrome when it should.
- Assert invalid forms render errors into the expected target.
- Assert out-of-band fragments are present when secondary UI must change.
- Assert redirects or client events are represented in headers, not only in body text.
Avoid
- Do not create one endpoint that performs unrelated actions based on arbitrary request parameters.
- Do not let templates become the authorization layer.
- Do not return raw JSON for htmx UI updates unless the same endpoint must serve a real API client.
- Do not use broad selectors that can hit multiple targets by accident.
- Do not mix server-rendered truth with stale client-side copies of the same state.
Source: hashgraph-online/awesome-codex-plugins → plugins/LVTD-LLC/skills/skills/htmx-endpoint-design/SKILL.md
1---2name: htmx-endpoint-design3description: Design and review htmx endpoint contracts for server-rendered HTML fragments. Use when adding or debugging hx-get, hx-post, hx-put, hx-patch, hx-delete, hx-target, hx-swap, hx-select, out-of-band swaps, HX-Trigger events, partial template responses, redirects, retargeting, or response headers.4---567# htmx Endpoint Design89Use this skill when the hard part is the server/browser contract: which element makes the request, which endpoint handles it, what HTML comes back, and where that HTML lands.1011## Contract First1213Define the endpoint contract before writing attributes:1415- **Request source**: the element that sends the request.16- **HTTP method**: `GET` for safe reads; `POST`, `PUT`, `PATCH`, or `DELETE` for mutations when the server/framework supports them.17- **Input data**: normal form fields, included elements, path params, or explicit values.18- **Response shape**: full page, partial fragment, empty response, redirect, or event-only response.19- **Swap target**: the element to replace or update.20- **Follow-up effects**: events, out-of-band fragments, URL changes, focus changes, and messages.2122## Endpoint Workflow23241. Run the same auth, permission, and data-loading logic for full-page and htmx requests.252. Branch late on whether the request is an htmx request.263. Reuse the same partial in the full-page render and the htmx response.274. Return a fragment whose root matches the intended `hx-target` when using `outerHTML`.285. Use response headers or events for cross-component effects instead of coupling unrelated targets.296. Test the normal request and the htmx request separately.3031## Requests3233- Prefer normal form encoding so server validation, CSRF, and file limitations are explicit.34- Keep mutation requests same-origin unless the project has a deliberate CORS and CSRF design.35- Use `hx-include` when one control must submit data from a nearby form or filter panel.36- Use `hx-vals` only for small explicit values. Avoid secrets and avoid executable `js:` values; prefer form fields, hidden inputs, or URL parameters instead.37- Debounce or throttle chatty triggers such as `keyup`, `input`, and polling.38- Use real links and forms when possible, then enhance them with htmx attributes.3940## Responses4142Choose the smallest response that keeps the UI honest:4344| Situation | Response |45| --- | --- |46| Replace one component | Return that component fragment |47| Update several unrelated components | Return primary fragment plus `hx-swap-oob` fragments |48| Mutation succeeds and another element should refresh | Return `204` plus an event/header when supported |49| Validation fails | Return the bound form fragment with errors |50| Browser should navigate | Return a normal redirect for non-htmx, and an htmx redirect/location response for htmx |51| Server needs a different target/swap | Use framework helpers or htmx response headers where available |5253## Targeting And Swapping5455- Use stable IDs for durable targets and keep them unique.56- Use `hx-target="this"` for self-contained components.57- Use `outerHTML` when replacing the target element itself.58- Use `innerHTML` when preserving the target shell and replacing only its contents.59- Use insert swaps such as `beforeend` for appending rows, log entries, or feed items.60- Use `hx-select` when the server returns a larger document but the client should extract one fragment.61- Do not swap a parent that contains long-lived local browser state unless that state is intentionally reset.6263## Out-Of-Band Updates6465Use out-of-band swaps for shared chrome and secondary facts:6667- flash messages68- cart counts69- notification badges70- summary totals71- list counters72- modal shells outside the main target7374Keep out-of-band fragments small and predictable. If many out-of-band updates are required for one action, consider returning the larger owner component instead.7576## Events7778Use events to decouple server results from browser-local behavior:7980- Fire a server-triggered event after save/delete when another component should refresh.81- Listen for htmx lifecycle events for instrumentation, custom confirmation, and cleanup.82- Use custom events as boundaries between htmx and Alpine, plain JavaScript, or `_hyperscript`.83- Keep event names domain-specific, such as `invoice:saved` or `filters:changed`.8485## Status Codes8687- Use `200` for normal fragment replacement, including many invalid form responses.88- Use `204` when no visible fragment should be swapped.89- Use redirects deliberately; do not let htmx silently insert a login page into a small target.90- For polling, use the framework or htmx convention that stops polling when the server says the job is done.9192## Testing Checklist9394- Assert status code and key response headers.95- Assert the partial contains the intended root element.96- Assert the partial omits full-page chrome when it should.97- Assert invalid forms render errors into the expected target.98- Assert out-of-band fragments are present when secondary UI must change.99- Assert redirects or client events are represented in headers, not only in body text.100101## Avoid102103- Do not create one endpoint that performs unrelated actions based on arbitrary request parameters.104- Do not let templates become the authorization layer.105- Do not return raw JSON for htmx UI updates unless the same endpoint must serve a real API client.106- Do not use broad selectors that can hit multiple targets by accident.107- Do not mix server-rendered truth with stale client-side copies of the same state.108109---110111**Source:** [`hashgraph-online/awesome-codex-plugins`](https://github.com/hashgraph-online/awesome-codex-plugins) → `plugins/LVTD-LLC/skills/skills/htmx-endpoint-design/SKILL.md`