Auto-activate for litestar_htmx, HTMXPlugin, HTMXConfig, HTMXRequest, HTMXTemplate, HXLocation, ReplaceUrl, TriggerEvent, HX-* headers, or Litestar partial HTML. Not for generic browser-side HTMX or Litestar Vite JSON templating — those are client concerns.
Scanned 9/6/2026
Install to Claude Code
npx -y skills add litestar-org/litestar-skills --skill litestar-htmx --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Litestar Htmx?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/litestar-org-litestar-htmx-litestar-skills)More formats (shields.io, HTML) on the badges page.
---
name: litestar-htmx
description: "Auto-activate for litestar_htmx, HTMXPlugin, HTMXConfig, HTMXRequest, HTMXTemplate, HXLocation, ReplaceUrl, TriggerEvent, HX-* headers, or Litestar partial HTML. Not for generic browser-side HTMX or Litestar Vite JSON templating — those are client concerns."
---
# litestar-htmx
`litestar-htmx` is the standalone Litestar integration for HTMX. Version 0.5.0
ships the `litestar_htmx` import package with request helpers, an optional
application plugin, template responses, and typed HTMX response-header helpers.
## Code Style Rules
- Import the integration from `litestar_htmx`, never
`litestar.plugins.htmx`; Litestar no longer owns this package's import
surface.
- Use `HTMXRequest` when handlers inspect HTMX request headers.
- Return template fragments from HTMX endpoints; keep full-page routes and
fragment routes distinct.
- Use the response classes for `HX-*` headers; do not assemble those headers
by hand.
- Keep browser-side HTMX extensions separate from this server package.
## Quick Reference
### Configure the plugin
```python
from litestar import Litestar
from litestar_htmx import HTMXPlugin
app = Litestar(
route_handlers=[...],
plugins=[HTMXPlugin()],
)
```
`HTMXPlugin()` is the convenience path: it registers the package's request and
response types. Its default `HTMXConfig(set_request_class_globally=True)` sets
`HTMXRequest` only when the application does not already have a request class.
Preserve an existing custom request class by extending `HTMXRequest`:
```python
from litestar_htmx import HTMXRequest
class ApplicationRequest(HTMXRequest):
"""Application request with HTMX helpers."""
```
If the application only needs response helpers, use
`HTMXConfig(set_request_class_globally=False)`. To inspect `request.htmx`,
configure `HTMXRequest` (or a subclass) as the application request class. The
plugin never replaces a request class already present in `AppConfig`.
The plugin itself is optional. Applications can instead set
`request_class=HTMXRequest` directly and return the response subclasses without
registering `HTMXPlugin`.
### Inspect request headers
`request.htmx` is always an `HTMXDetails` object. Its truth value is `True` only
when `HX-Request` is exactly `"true"`.
```python
from litestar import get
from litestar.response import Template
from litestar_htmx import HTMXRequest
@get("/items")
async def list_items(request: HTMXRequest) -> Template:
template_name = "partials/item-list.html" if request.htmx else "pages/items.html"
return Template(template_name=template_name, context={"items": []})
```
Available request helpers:
| Property | Source | Result |
| --- | --- | --- |
| `bool(request.htmx)` | `HX-Request` | Whether this is an HTMX request |
| `request.htmx.boosted` | `HX-Boosted` | `bool` |
| `request.htmx.current_url` | `HX-Current-URL` | `str \| None` |
| `request.htmx.current_url_abs_path` | `HX-Current-URL` | Same-origin path, query, and fragment, or `None` |
| `request.htmx.history_restore_request` | `HX-History-Restore-Request` | `bool` |
| `request.htmx.prompt` | `HX-Prompt` | `str \| None` |
| `request.htmx.target` | `HX-Target` | `str \| None` |
| `request.htmx.trigger` | `HX-Trigger` | `str \| None` |
| `request.htmx.trigger_name` | `HX-Trigger-Name` | `str \| None` |
| `request.htmx.triggering_event` | `Triggering-Event` | Decoded JSON value, or `None` |
`triggering_event` is supplied by HTMX's `event-header` extension. Malformed
JSON resolves to `None`. Headers accompanied by
`<Header>-URI-AutoEncoded: true` are URL-decoded before use.
### Return template fragments with HTMX headers
`HTMXTemplate` extends Litestar's `Template`. Annotate handlers with
`Template`, then pass normal `Template` arguments plus HTMX-specific options:
```python
from litestar import get
from litestar.response import Template
from litestar_htmx import HTMXTemplate
@get("/items/fragment")
async def item_list() -> Template:
return HTMXTemplate(
template_name="partials/item-list.html",
context={"items": []},
push_url=False,
re_swap="outerHTML",
re_target="#item-list",
trigger_event="itemsLoaded",
params={"count": 0},
after="receive",
)
```
`trigger_event`, `params`, and `after` form one event declaration. When
triggering an event, set `after` to `"receive"`, `"settle"`, or `"swap"`.
### Response helper signatures
All helpers are exported from `litestar_htmx` and
`litestar_htmx.response`.
| Helper | Constructor | Behavior |
| --- | --- | --- |
| `HXStopPolling` | `HXStopPolling()` | Returns status `286` |
| `ClientRedirect` | `ClientRedirect(redirect_to)` | Sets `HX-Redirect`; no `Location` header |
| `ClientRefresh` | `ClientRefresh()` | Sets `HX-Refresh: true` |
| `PushUrl` | `PushUrl(content, push_url, **response_kwargs)` | Sets `HX-Push-Url` |
| `ReplaceUrl` | `ReplaceUrl(content, replace_url, **response_kwargs)` | Sets `HX-Replace-Url` |
| `Reswap` | `Reswap(content, method, **response_kwargs)` | Sets `HX-Reswap` |
| `Retarget` | `Retarget(content, target, **response_kwargs)` | Sets `HX-Retarget` |
| `TriggerEvent` | `TriggerEvent(content, name, after, params=None, **response_kwargs)` | Sets the selected `HX-Trigger*` header |
| `HXLocation` | `HXLocation(redirect_to, source=None, event=None, target=None, select=None, swap=None, hx_headers=None, values=None, **response_kwargs)` | Sets JSON in `HX-Location` |
`push_url=False` and `replace_url=False` emit `"false"` to prevent the
corresponding history update.
### Soft navigation with `HXLocation`
Use `HXLocation` for an HTMX navigation request without a full-page reload.
`select` chooses a fragment from the fetched response before it is swapped:
```python
from litestar import post
from litestar_htmx import HXLocation
@post("/items")
async def create_item() -> HXLocation:
return HXLocation(
redirect_to="/items",
source="#create-item",
event="submit",
target="#content",
select="#item-list",
swap="innerHTML",
hx_headers={"X-View": "compact"},
values={"created": "true"},
)
```
The response uses status `200`, carries `HX-Location`, and removes the ordinary
`Location` header.
### Trigger an event while returning content
`TriggerEvent` requires the response `content`, event `name`, and `after`
phase:
```python
from litestar import post
from litestar_htmx import TriggerEvent
@post("/items")
async def create_item() -> TriggerEvent[str]:
return TriggerEvent(
content="<li>Saved</li>",
name="itemCreated",
after="swap",
params={"id": 42},
media_type="text/html",
)
```
Prefer `HTMXTemplate` when the content is HTML assembled from application data.
### Litestar Vite is a separate client layer
The standalone package owns Python request parsing and response headers:
```python
from litestar_htmx import HTMXPlugin, HTMXRequest, HTMXTemplate
```
Litestar Vite's `hx-ext="litestar"` JSON templating and CSRF integration come
from the separate `litestar-vite-plugin/helpers` JavaScript export. They are not
installed, registered, or enabled by `HTMXPlugin()`. Use them only when the
project already uses Litestar Vite and needs client-side JSON swaps. See
[Litestar Vite Integration](references/litestar_vite.md).
<workflow>
## Workflow
1. Check the project's installed `litestar-htmx` version and existing request
class.
2. Register `HTMXPlugin()` or set `request_class=HTMXRequest` directly. Extend
`HTMXRequest` when the application needs custom request behavior.
3. Separate full-page endpoints from fragment endpoints. Branch on
`request.htmx` only when one URL intentionally supports both.
4. Render fragments with `Template` or `HTMXTemplate`.
5. Select the narrow response helper matching the required HTMX header.
6. Configure CSRF protection for every state-changing HTMX request.
7. Test the response body, status, and exact `HX-*` header.
8. Add Litestar Vite's client extension only for bundled assets, CSRF header
injection, or JSON templating.
</workflow>
<guardrails>
## Guardrails
- **Use `litestar_htmx`, never `litestar.plugins.htmx`.** The 0.5.0 package is a
standalone distribution with its own public import root.
- **Pass every required response-helper argument.** `TriggerEvent` requires
`content`, `name`, and `after`; `PushUrl`, `ReplaceUrl`, `Reswap`, and
`Retarget` also require content.
- **Use `select=` on `HXLocation` to choose returned content.** Do not confuse
it with `target=`, which chooses the receiving element.
- **Do not assume `HTMXPlugin` overrides an existing request class.** It
preserves a non-null `AppConfig.request_class`.
- **Do not treat `request.htmx` as an optional object.** Test its truth value to
identify HTMX requests.
- **Do not send a normal redirect for `HXLocation` or `ClientRedirect`.** These
helpers return `200` with HTMX response headers.
- **Do not attribute `hx-ext="litestar"` to `litestar-htmx`.** That browser
extension ships with Litestar Vite's npm package.
- **Do not return unsanitized, concatenated HTML.** Render templates so escaping
and template caching remain intact.
</guardrails>
<validation>
## Validation Checkpoint
- [ ] Imports use `litestar_htmx`, not `litestar.plugins.htmx`
- [ ] `HTMXPlugin()` or `request_class=HTMXRequest` wires request helpers
- [ ] A custom global request class extends `HTMXRequest`
- [ ] Full pages and HTMX fragments have explicit boundaries
- [ ] `TriggerEvent` includes `content`, `name`, and a valid `after` value
- [ ] `ReplaceUrl` uses `replace_url=`, not `push_url=`
- [ ] `HXLocation.select` and `HXLocation.target` serve distinct purposes
- [ ] State-changing HTMX requests include the application's CSRF token
- [ ] Tests assert the exact status, body, and `HX-*` response header
- [ ] Litestar Vite client-extension guidance is identified as a separate layer
</validation>
<example>
## Example
Return a fragment, retarget the swap, prevent a history update, and verify the
HTMX response:
```python
from litestar import Controller, get
from litestar.response import Template
from litestar_htmx import HTMXRequest, HTMXTemplate
class ItemController(Controller):
path = "/items"
@get("/")
async def index(self, request: HTMXRequest) -> Template:
items = [{"id": 1, "name": "Widget"}]
if request.htmx:
return HTMXTemplate(
template_name="partials/item-list.html",
context={"items": items},
re_target="#item-list",
re_swap="outerHTML",
push_url=False,
)
return Template(template_name="pages/items.html", context={"items": items})
```
```python
async def test_htmx_item_list(client) -> None:
response = await client.get(
"/items/",
headers={"HX-Request": "true", "HX-Target": "item-list"},
)
assert response.status_code == 200
assert response.headers["HX-Retarget"] == "#item-list"
assert response.headers["HX-Reswap"] == "outerHTML"
assert response.headers["HX-Push-Url"] == "false"
assert "<html" not in response.text
```
</example>
## References Index
- **[Litestar Vite Integration](references/litestar_vite.md)** — Keep the
standalone Python package distinct from Litestar Vite's browser extension.
- **[Litestar](../litestar/SKILL.md)** — Application setup, templates, and
lifecycle fundamentals.
- **[Litestar Vite](../litestar-vite/SKILL.md)** — Asset bundling, template
mode, HMR, and the client helper package.
- **[Litestar Testing](../litestar-testing/SKILL.md)** — Async clients and
application fixtures.
## Official References
- <https://pypi.org/project/litestar-htmx/0.5.0/>
- <https://github.com/litestar-org/litestar-htmx/tree/v0.5.0/litestar_htmx>
- <https://github.com/litestar-org/litestar-htmx/blob/v0.5.0/litestar_htmx/request.py>
- <https://github.com/litestar-org/litestar-htmx/blob/v0.5.0/litestar_htmx/response.py>
- <https://github.com/litestar-org/litestar-htmx/tree/v0.5.0/tests>
- <https://htmx.org/reference/>
## Shared Styleguide Baseline
- [General Principles](../litestar-styleguide/references/general.md)
- [Python](../litestar-styleguide/references/python.md)
- [Litestar](../litestar-styleguide/references/litestar.md)
- [Testing](../litestar-styleguide/references/testing.md)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!