{"id":4084,"library":"litestar-htmx","title":"Litestar HTMX Plugin","description":"litestar-htmx is an official plugin for the Litestar web framework, integrating HTMX into Litestar applications. It provides the `HTMXPlugin` for global configuration, a special `HTMXRequest` class for accessing HTMX client details, `HTMXTemplate` for rendering HTML fragments, and a suite of HTMX-specific response primitives. It streamlines server-rendered partial updates, progressive enhancement, polling, history-aware interactions, and HTMX-driven redirects. The current version is 0.5.0, actively maintained with regular updates.","status":"active","version":"0.5.0","language":"en","source_language":"en","source_url":"https://github.com/litestar-org/litestar-htmx","tags":["web framework","htmx","litestar","plugin","frontend"],"install":[{"cmd":"pip install litestar-htmx","lang":"bash","label":"Install `litestar-htmx`"}],"dependencies":[{"reason":"Core dependency for the plugin to function within a Litestar application.","package":"litestar"}],"imports":[{"symbol":"HTMXPlugin","correct":"from litestar.plugins.htmx import HTMXPlugin"},{"symbol":"HTMXRequest","correct":"from litestar.plugins.htmx import HTMXRequest"},{"note":"HTMXTemplate is from the plugin, not directly from litestar.response. However, handlers *returning* HTMXTemplate should be annotated as returning `Template` from `litestar.response`.","wrong":"from litestar.response import HTMXTemplate","symbol":"HTMXTemplate","correct":"from litestar.plugins.htmx import HTMXTemplate"},{"symbol":"ClientRedirect","correct":"from litestar.plugins.htmx import ClientRedirect"},{"symbol":"PushUrl","correct":"from litestar.plugins.htmx import PushUrl"}],"quickstart":{"code":"import os\nfrom pathlib import Path\nfrom litestar import Litestar, get\nfrom litestar.contrib.jinja import JinjaTemplateEngine\nfrom litestar.template.config import TemplateConfig\nfrom litestar.plugins.htmx import HTMXPlugin, HTMXRequest, HTMXTemplate\nfrom litestar.response import Template\n\n\n# Create a dummy template directory and file for the example\nTEMPLATE_DIR = Path(\"./templates\")\nTEMPLATE_DIR.mkdir(exist_ok=True)\n(TEMPLATE_DIR / \"full_page.html\").write_text(\n    \"\"\"\n    <!DOCTYPE html>\n    <html>\n    <head><title>Full Page</title></head>\n    <body>\n        <h1>Full Page Content</h1>\n        <div id=\"content\" hx-get=\"/partial\" hx-trigger=\"load\">Loading partial...</div>\n    </body>\n    </html>\n    \"\"\"\n)\n(TEMPLATE_DIR / \"partial.html\").write_text(\n    \"\"\"\n    <p>This is a partial loaded by HTMX!</p>\n    <button hx-post=\"/clicked\" hx-target=\"#message\">Click Me</button>\n    <div id=\"message\"></div>\n    \"\"\"\n)\n\n\n@get(path=\"/\")\nasync def get_full_page(request: HTMXRequest) -> Template:\n    if request.htmx:\n        # This branch should ideally not be hit for the root page on initial load\n        # but demonstrates checking for HTMX request.\n        return HTMXTemplate(template_name=\"partial.html\", context={\"is_htmx\": True})\n    return Template(template_name=\"full_page.html\")\n\n@get(path=\"/partial\")\nasync def get_partial(request: HTMXRequest) -> HTMXTemplate:\n    # This handler expects an HTMX request\n    return HTMXTemplate(template_name=\"partial.html\", context={\"from_partial\": True})\n\n@post(path=\"/clicked\")\nasync def post_clicked() -> HTMXTemplate:\n    return HTMXTemplate(template_name=\"<p>Button was clicked!</p>\") # Inline template\n\n\napp = Litestar(\n    route_handlers=[get_full_page, get_partial, post_clicked],\n    plugins=[HTMXPlugin()],\n    template_config=TemplateConfig(\n        directory=TEMPLATE_DIR,\n        engine=JinjaTemplateEngine,\n    ),\n    debug=True\n)\n\n# To run this:\n# 1. Save as e.g., `app.py`\n# 2. `pip install litestar litestar-htmx jinja2 uvicorn`\n# 3. `uvicorn app:app --reload`\n# 4. Navigate to http://127.0.0.1:8000\n","lang":"python","description":"This quickstart demonstrates setting up a Litestar application with `litestar-htmx`. It configures the `HTMXPlugin` globally and uses `HTMXRequest` to detect HTMX requests. The example includes two routes: one for a full page load and another for an HTMX-driven partial update using `HTMXTemplate`. It also shows a POST request for an HTMX interaction."},"warnings":[{"fix":"Update imports to `from litestar.plugins.htmx import ...` and add `HTMXPlugin()` to `Litestar` application's `plugins` list.","message":"The HTMX integration was migrated from `litestar.contrib.htmx` to `litestar.plugins.htmx` as a standalone plugin. Users upgrading from Litestar versions where HTMX was part of `litestar.contrib` must update their imports and integrate the `HTMXPlugin`.","severity":"breaking","affected_versions":"<2.x (where `litestar.contrib.htmx` was used)"},{"fix":"Annotate handlers as `-> Template` (imported from `litestar.response`) even if the actual return type is `HTMXTemplate`.","message":"When defining route handlers that return `HTMXTemplate`, the return type annotation should be `litestar.response.Template`, not `HTMXTemplate` directly. `HTMXTemplate` is a specialized `Template` for HTMX-specific headers.","severity":"gotcha","affected_versions":"All versions of `litestar-htmx`"},{"fix":"Access HTMX request details via `request.htmx.header_name` (e.g., `request.htmx.current_url`) instead of `request.headers.get('HX-Current-URL')`.","message":"Avoid manually parsing raw `HX-*` headers from the request. The `HTMXRequest` class provides a convenient `request.htmx` object (an `HTMXDetails` instance) with strongly typed properties for all HTMX-specific headers.","severity":"gotcha","affected_versions":"All versions of `litestar-htmx`"},{"fix":"Design handlers and templates so that HTMX requests always return small, swap-oriented fragments. Use conditional logic (`if request.htmx:`) to render different content for HTMX vs. non-HTMX requests if a route serves both.","message":"Ensure that HTMX responses return only the HTML fragment expected by the client's `hx-target`. Accidentally returning a full page layout into a fragment target can lead to UI breakage.","severity":"gotcha","affected_versions":"All versions of `litestar-htmx`"},{"fix":"Upgrade to `litestar-htmx` version 0.5.0 or newer. This issue was resolved in PR #14, making `HTMXRequest` generic like `litestar.Request`.","message":"Prior to version 0.5.0, `HTMXRequest` was not generic in `UserT`, `AuthT`, and `StateT`. This meant that type-safe access to `request.user`, `request.auth`, or `request.state` (if configured with custom types) was not properly propagated through `HTMXRequest`.","severity":"breaking","affected_versions":"<0.5.0"}],"env_vars":null,"last_verified":"2026-04-11T00:00:00.000Z","next_check":"2026-07-10T00:00:00.000Z"}