本文へ移動
cccskills
無料GitHub で公開

htmx-progressive-enhancement

Use when building server-driven UIs with htmx, designing hx-* attribute compositions, choosing swap strategies (innerHTML/outerHTML/morph), wiring out-of-band updates, integrating with form validation, or migrating from a SPA back to server-rendered HTML. Triggers: hx-get/hx-post setup, hx-target + hx-swap interplay, hx-trigger debouncing, OOB swaps for parts of the page outside the request target, response headers like HX-Trigger and HX-Push-Url, integration with Hyperscript or Alpine.js, accessibility considerations on partial updates. NOT for full SPAs (use React/Vue), framework-specific server libraries (use those skills directly), or non-HTML responses.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md8.8 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

htmx Progressive Enhancement

htmx adds AJAX, CSS transitions, WebSockets, and server-sent events to HTML via attributes. The mental model is "the server returns HTML; the client swaps it in." For most CRUD apps, this beats a SPA in time-to-ship and bundle size.

When to use

  • Server-rendered app where SPA complexity isn't paying off.
  • Adding partial updates to a Rails/Django/Laravel/Phoenix/Hono app.
  • Form-heavy UIs (admin panels, dashboards) without React's overhead.
  • Migrating away from a SPA that grew past its complexity budget.
  • Real-time updates via SSE or WebSockets without a frontend framework.

Core capabilities

Basic request/swap

<button hx-get="/api/widget" hx-target="#out" hx-swap="innerHTML">
  Load
</button>
<div id="out"></div>

Click → GET /api/widget → response HTML replaces #out content.

Common attributes

AttributePurpose
hx-get / hx-post / hx-put / hx-delete / hx-patchHTTP method + URL.
hx-targetCSS selector for the swap. Default: the element itself. closest, next, previous selectors supported.
hx-swapHow to swap. innerHTML (default), outerHTML, beforebegin, afterbegin, beforeend, afterend, delete, none.
hx-triggerWhen to fire. click (default for buttons), change, keyup changed delay:500ms, revealed, every 5s.
hx-includeExtra fields to include with the request.
hx-valsStatic or JS-computed extra params.
hx-confirmBrowser confirm() before request.
hx-indicatorCSS selector to mark "request in flight."
hx-disabled-eltDisable elements while request runs.
hx-push-urlUpdate browser URL on success.

Swap strategies

<!-- Replace contents of target -->
<a hx-get="/feed/items" hx-target="#list" hx-swap="innerHTML">Refresh</a>

<!-- Replace the target itself -->
<button hx-delete="/items/42" hx-target="closest tr" hx-swap="outerHTML swap:300ms">
  Delete
</button>

<!-- Append to a list (newest at top) -->
<form hx-post="/comments" hx-target="#comments" hx-swap="afterbegin">
  ...
</form>

swap:300ms is a CSS transition delay — the old content gets htmx-swapping class for 300ms, you animate it out, then htmx swaps.

Triggers — debouncing search

<input
  type="search"
  name="q"
  hx-get="/search"
  hx-trigger="keyup changed delay:300ms, search"
  hx-target="#results"
/>
<div id="results"></div>

changed skips events that don't change the value (arrow keys). delay:300ms debounces. Multiple comma-separated triggers are OR'd.

Out-of-band swaps

When a request needs to update something outside the target:

<!-- Server returns -->
<div id="cart-count" hx-swap-oob="true">3</div>
<div>Item added to cart.</div>

The browser sees the OOB element and swaps it into the page wherever id="cart-count" lives. The remaining content goes to hx-target.

Response headers — server controls the client

HeaderEffect
HX-TriggerFire a custom event on the document. JSON for events with payload.
HX-Push-UrlUpdate browser URL.
HX-RedirectClient-side redirect.
HX-Refresh: trueReload the page.
HX-Reswap / HX-RetargetOverride the swap strategy or target server-side.
HX-LocationLike Redirect, but uses htmx (preserves boost).
# Flask example
return render_template('partials/item.html', item=item), 200, {
    'HX-Trigger': json.dumps({'cart-updated': {'count': 3}})
}
<div hx-get="/cart/count" hx-trigger="cart-updated from:body">...</div>

Forms with validation

<form hx-post="/users" hx-target="#form-area" hx-swap="outerHTML">
  <label>
    Email
    <input name="email" required hx-post="/validate/email"
           hx-trigger="change" hx-target="next .error" hx-swap="innerHTML" />
    <span class="error"></span>
  </label>
  <button>Save</button>
</form>

The change-time validation hits /validate/email; the form-submit hits /users. Server returns either the next form state or the success view.

Boost — turn regular links into AJAX

<body hx-boost="true">
  <a href="/about">About</a>      <!-- becomes an htmx swap -->
  <a href="/external" hx-boost="false">External</a>
</body>

Boosted navigation does an AJAX GET, swaps <body>, and pushes URL. SPA-like navigation without writing a SPA.

Loading indicators

<button hx-post="/submit" hx-indicator="#spinner">Submit</button>
<span id="spinner" class="htmx-indicator">Saving…</span>
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator { display: inline; }

The htmx-request class is added to the element making the request for the duration; CSS handles the rest.

Server-sent events

<div hx-ext="sse" sse-connect="/events" sse-swap="message">
  Waiting for events…
</div>

Each event: message from the server triggers a swap of the response body into the div.

WebSockets

<div hx-ext="ws" ws-connect="/chat">
  <ul id="messages"></ul>
  <form ws-send>
    <input name="text" />
  </form>
</div>

The form sends JSON on submit; server echoes HTML back, swapping into the page.

Anti-patterns

Returning JSON when htmx wanted HTML

Symptom: Endpoint returns 200 but nothing changes on the page. Diagnosis: htmx swaps response bodies as HTML. JSON ends up rendered as text. Fix: Server returns HTML fragments for htmx requests (detect via HX-Request header). Keep JSON endpoints separate.

Tracking state on the client

Symptom: Race conditions; page shows stale data after multiple actions. Diagnosis: Trying to maintain client-side state in JS variables. Fix: Server is the source of truth. Each response includes the new state's HTML. If you're tempted to maintain client state, you probably want a SPA.

Forgotten hx-target for forms

Symptom: Form submission replaces the form's container instead of updating output area. Diagnosis: hx-target defaults to the element itself; for forms, this is the form. Fix: Add hx-target="#output" and hx-swap explicitly.

Missing CSRF token

Symptom: POST/PUT/DELETE returns 403 from a framework that enforces CSRF. Diagnosis: Form helpers usually inject CSRF; htmx requests don't unless you tell them. Fix: Use hx-headers='{"X-CSRF-Token": "..."}' or include in hx-vals. Some frameworks have htmx-aware CSRF middleware.

No fallback for JS-disabled

Symptom: Site unusable without JS even though it could degrade. Diagnosis: Forms and links that only work via htmx. Fix: Use hx-boost="true" on links and forms — without JS they're regular HTML; with JS they upgrade. Combine action="/path" with hx-post="/path" so POST works either way.

Accessibility: focus + announcements

Symptom: Screen reader users don't know content updated. Diagnosis: Partial swaps don't trigger ARIA live regions automatically. Fix: Mark dynamic regions with aria-live="polite". Manage focus on swap with hx-on::after-swap. Add visually-hidden announcements for important changes.

Quality gates

  • htmx request endpoints return HTML, not JSON.
  • CSRF tokens included on every state-changing request.
  • Forms work without JS (progressive enhancement, not JS-required).
  • Dynamic regions have aria-live for screen readers.
  • Focus managed on swap (hx-on::after-swap).
  • No client-side state beyond htmx attributes; server is the source of truth.
  • Loading indicators on every request that takes >300ms.
  • OOB swaps used for cross-region updates instead of multiple requests.
  • Trigger debouncing (delay:) on every type-as-you-search input.

NOT for

  • Full SPAs with rich client state — htmx adds friction for that case.
  • Framework-specific server-side rendering — use the framework's idioms (Phoenix LiveView, Rails Hotwire, Laravel Livewire are similar but not htmx).
  • Native mobile — htmx is web-only.
  • Heavy real-time collaborative apps (Figma-like) — the round-trip cost is too high.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Expert in 2000s-era music visualization (Milkdrop, AVS, Geiss) and modern WebGL implementations. Specializes in Butterchurn integration, Web Audio API AnalyserNode FFT data, GLSL shaders for audio-reactive visuals, and psychedelic generative art. Activate on "Milkdrop", "music visualization", "WebGL visualizer", "Butterchurn", "audio reactive", "FFT visualization", "spectrum analyzer". NOT for simple bar charts/waveforms (use basic canvas), video editing, or non-audio visuals.

日本語の概要は準備中です。原文の説明を表示しています。

curiositech/windags-skills132026年10月12日 更新

Expert legal research agent for finding and scraping expungement data state by state. Knows authoritative sources, URL patterns, Firecrawl configuration, and 2026 legal landscape.

日本語の概要は準備中です。原文の説明を表示しています。

curiositech/windags-skills132026年10月12日 更新

Expert in 3D computer vision labeling tools, workflows, and AI-assisted annotation for LiDAR, point clouds, and sensor fusion. Covers SAM4D/Point-SAM, human-in-the-loop architectures, and vertical-specific training strategies. Activate on '3D labeling', 'point cloud annotation', 'LiDAR labeling', 'SAM 3D', 'SAM4D', 'sensor fusion annotation', '3D bounding box', 'semantic segmentation point cloud'. NOT for 2D image labeling (use clip-aware-embeddings), general ML training (use ml-engineer), video annotation without 3D (use computer-vision-pipeline), or VLM prompt engineering (use prompt-engineer).

日本語の概要は準備中です。原文の説明を表示しています。

curiositech/windags-skills132026年10月12日 更新

Apply crisis decision-making research to agent routing, uncertainty triage, and coordination failure analysis in time-pressured systems. Use when diagnosing handoff failures, analytical paralysis, or expert judgment under incomplete information. NOT for routine coding, simple CRUD design, or static single-agent tasks with complete information.

日本語の概要は準備中です。原文の説明を表示しています。

curiositech/windags-skills132026年10月12日 更新

Use for insight, reframing, contradiction, impasse, and anomaly-driven problem solving when execution effort no longer helps. NOT for routine optimization, error correction, or well-specified tasks with known solution paths.

日本語の概要は準備中です。原文の説明を表示しています。

curiositech/windags-skills132026年10月12日 更新

Apply normative BDI reasoning to agents that must detect norms, choose which commitments to internalize, and resolve conflicts by comparing consequences. Use when obligations, prohibitions, or policies collide in autonomous systems. NOT for simple fixed-priority rules, pure constraint satisfaction, or domains where no real normative conflict exists.

日本語の概要は準備中です。原文の説明を表示しています。

curiositech/windags-skills132026年10月12日 更新

curiositech のスキルをすべて見る

このスキルの問題を報告する