Litestar HTMX Plugin

0.5.0 · active · verified Sat Apr 11

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.

Warnings

Install

Imports

Quickstart

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.

import os
from pathlib import Path
from litestar import Litestar, get
from litestar.contrib.jinja import JinjaTemplateEngine
from litestar.template.config import TemplateConfig
from litestar.plugins.htmx import HTMXPlugin, HTMXRequest, HTMXTemplate
from litestar.response import Template


# Create a dummy template directory and file for the example
TEMPLATE_DIR = Path("./templates")
TEMPLATE_DIR.mkdir(exist_ok=True)
(TEMPLATE_DIR / "full_page.html").write_text(
    """
    <!DOCTYPE html>
    <html>
    <head><title>Full Page</title></head>
    <body>
        <h1>Full Page Content</h1>
        <div id="content" hx-get="/partial" hx-trigger="load">Loading partial...</div>
    </body>
    </html>
    """
)
(TEMPLATE_DIR / "partial.html").write_text(
    """
    <p>This is a partial loaded by HTMX!</p>
    <button hx-post="/clicked" hx-target="#message">Click Me</button>
    <div id="message"></div>
    """
)


@get(path="/")
async def get_full_page(request: HTMXRequest) -> Template:
    if request.htmx:
        # This branch should ideally not be hit for the root page on initial load
        # but demonstrates checking for HTMX request.
        return HTMXTemplate(template_name="partial.html", context={"is_htmx": True})
    return Template(template_name="full_page.html")

@get(path="/partial")
async def get_partial(request: HTMXRequest) -> HTMXTemplate:
    # This handler expects an HTMX request
    return HTMXTemplate(template_name="partial.html", context={"from_partial": True})

@post(path="/clicked")
async def post_clicked() -> HTMXTemplate:
    return HTMXTemplate(template_name="<p>Button was clicked!</p>") # Inline template


app = Litestar(
    route_handlers=[get_full_page, get_partial, post_clicked],
    plugins=[HTMXPlugin()],
    template_config=TemplateConfig(
        directory=TEMPLATE_DIR,
        engine=JinjaTemplateEngine,
    ),
    debug=True
)

# To run this:
# 1. Save as e.g., `app.py`
# 2. `pip install litestar litestar-htmx jinja2 uvicorn`
# 3. `uvicorn app:app --reload`
# 4. Navigate to http://127.0.0.1:8000

view raw JSON →