htmx-patterns

HTMX Patterns for Django

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "htmx-patterns" with this command: npx skills add kjnez/claude-code-django/kjnez-claude-code-django-htmx-patterns

HTMX Patterns for Django

Core Philosophy

  • Server renders HTML, not JSON - HTMX requests return HTML fragments, not data

  • Partial templates for dynamic updates - separate _partial.html files for HTMX responses

  • Progressive enhancement - pages work without JavaScript, HTMX enhances UX

  • Minimal client-side complexity - let the server do the heavy lifting

Critical Hints & Reminders

UX Best Practices

Always include loading indicators

  • Use hx-indicator to show loading states during requests

  • Users should never wonder if their action worked

  • Example: <button hx-get="/data/" hx-indicator="#spinner">Load</button>

Always provide user feedback

  • Use Django messages framework for success/error feedback

  • Return error messages in HTMX responses, not silent failures

  • Show what happened after an action completes

Handle errors gracefully

  • Return proper HTTP status codes (400 for validation errors, 500 for server errors)

  • Render form errors in partial templates

  • Don't swallow exceptions - log and show user-friendly messages

Django-Specific Patterns

Always detect HTMX requests

  • Check request.headers.get("HX-Request") to detect HTMX requests

  • Return partial templates for HTMX, full page templates otherwise

  • Pattern: if request.headers.get("HX-Request"): return render(request, "_partial.html", context)

Always return partials for HTMX

  • HTMX requests should return _partial.html templates, not full pages with base.html

  • Full page responses to HTMX requests break the UX and send duplicate HTML

  • Partials should be self-contained HTML fragments

Always validate request.method

  • Check request.method == "POST" before processing form data

  • Return proper status codes (405 Method Not Allowed for wrong methods)

CSRF is already configured globally

  • The base template has hx-headers on <body>

  • no need to add CSRF tokens to individual forms

  • All HTMX requests automatically include the CSRF token

Template Organization

Naming convention

  • Partials: _partial.html (underscore prefix)

  • Full pages: page.html (no prefix)

  • Example: posts/list.html (full page) includes posts/_list.html (partial)

Structure

  • Full page template extends base.html and includes partial

  • Partial contains only the dynamic HTML fragment

  • HTMX targets the partial's container div

Keep partials focused

  • Each partial should represent one logical UI component

  • Avoid partials that are too large or do too much

  • Compose larger UIs from multiple smaller partials

Django View Patterns

HTMX Detection

Check the HX-Request header to detect HTMX requests:

def my_view(request): context = {...}

if request.headers.get("HX-Request"):
    return render(request, "app/_partial.html", context)

return render(request, "app/full_page.html", context)

Form Handling Pattern

Key points:

  • Validate form normally

  • On success: return partial with new data OR trigger client-side event

  • On error: return partial with form errors

  • Always handle both HTMX and non-HTMX cases

def create_view(request): if request.method == "POST": form = MyForm(request.POST) if form.is_valid(): obj = form.save() if request.headers.get("HX-Request"): return render(request, "app/_item.html", {"item": obj}) return redirect("app:list")

    # Return form with errors
    if request.headers.get("HX-Request"):
        return render(request, "app/_form.html", {"form": form})
else:
    form = MyForm()

return render(request, "app/create.html", {"form": form})

Response Headers Reference

HTMX respects special response headers for client-side behavior:

HX-Trigger

Trigger client-side events after response

  • Use case: Update other parts of page after action

  • Example: response["HX-Trigger"] = "itemCreated"

  • Template listens: <div hx-get="/count/" hx-trigger="itemCreated from:body">

HX-Redirect

Client-side redirect

  • Use case: Redirect after successful action

  • Example: response["HX-Redirect"] = reverse("app:detail", args=[obj.pk])

HX-Retarget / HX-Reswap

Override hx-target and hx-swap from server

  • Use case: Different targets for success vs error

  • Success: response["HX-Retarget"] = "#main"

  • Error: Return partial without changing target (targets the form)

HX-Refresh

Force full page refresh

  • Use case: Major state change that affects whole page

  • Example: response["HX-Refresh"] = "true"

Common Pitfalls

  • Missing loading indicators: Always use hx-indicator

  • users click multiple times without feedback

  • Full pages in HTMX responses: Return _partial.html , not full pages with base.html

  • check HX-Request header

  • Not handling form errors: Always return the form with errors on validation failure, not just the success case

  • Not disabling buttons: Use hx-disabled-elt="this" to prevent duplicate submissions

  • N+1 queries: HTMX views need select_related() /prefetch_related() just like regular views

Integration with Other Skills

  • django-templates: Partial template organization and inheritance patterns

  • django-forms: HTMX form submission and validation

  • django-extensions: Use show_urls to verify HTMX endpoints

  • pytest-django-patterns: Testing HTMX endpoints and headers

  • systematic-debugging: Debug HTMX request/response issues

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

django-templates

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

pytest-django-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

django-forms

No summary provided by upstream source.

Repository SourceNeeds Review