AGENT SKILL

htmx-go-templates

htmx on Go html/template: how a handler picks page, fragment or redirect, how templates carry hx-* attributes, where client JS lives, and how errors and polling surface. TRIGGER — load BEFORE writing, not after: a .tmpl or .gohtml file is created or edited; an hx-* attribute or HX-* header is added or changed; a Go handler calls ExecuteTemplate or reads HX-Request; the prompt names htmx, hx-get, hx-swap, a fragment, partial, swap target, polling or an htmx event. Trigger on plain requests in a Go + htmx repo — "add a page", "make this form inline", "refresh this every 5s", "why doesn't the error show". Load alongside go-idiomatic. SKIP for templ components, JSON APIs and React or Solid UIs.

使用场景前端开发
License 许可
MIT
最近更新
2026-11-11
Stars
★ 0
Forks
0

01 前言 Front Matter

name
htmx-go-templates
description
htmx on Go html/template: how a handler picks page, fragment or redirect, how templates carry hx-* attributes, where client JS lives, and how errors and polling surface. TRIGGER — load BEFORE writing, not after: a .tmpl or .gohtml file is created or edited; an hx-* attribute or HX-* header is added or changed; a Go handler calls ExecuteTemplate or reads HX-Request; the prompt names htmx, hx-get, hx-swap, a fragment, partial, swap target, polling or an htmx event. Trigger on plain requests in a Go + htmx repo — "add a page", "make this form inline", "refresh this every 5s", "why doesn't the error show". Load alongside go-idiomatic. SKIP for templ components, JSON APIs and React or Solid UIs.
allowed-tools
Read, Edit, Write, Glob, Grep, Bash(go:*), Bash(git:*)

02 资源文件 7

03 SKILL.md 正文

htmx on Go html/template

The server owns state; a template only presents it; htmx moves HTML between the two. Most drift in these apps comes from that split being decided ad hoc, per handler and per template: seven ways to detect an htmx request, the same four attributes hand-copied across files, errors that vanish. The rules below make each of those decisions once.

This skill holds the general rules. The repo's AGENTS.md holds what only the repo knows: its swap-target ids, the names of its shared partials, and the htmx version it vendors. Read it first.

Where to look

If you're working on… Load
A handler: choosing page / fragment / redirect, htmx headers, Vary, 303, error responses references/responses.md
A template: partials, repeated attribute bundles, forms, live regions, conditionals references/templates.md
Any client JS: whether you need it at all, islands, htmx glue, polling guards, aria-busy references/client.md

The rules

  1. htmx headers go through one helper set, never hand-typed strings. A typo in "HX-Request" or a check for "" instead of "true" fails silently; one package of constants and predicates makes the wrong spelling unrepresentable. If the repo has no such set yet, introduce it the first time a handler you touch needs an htmx header — Vary included.
  2. Every route declares its response shape — page, fragment or redirect — in one place. A handler that sniffs headers inline grows a new branch per feature. When one URL can return either a page or a fragment, set Vary: HX-Request, or a cache or the back button can serve the bare fragment as a page. A history-restore request (HX-History-Restore-Request: true) always gets the full page.
  3. A non-htmx form POST answers 303 to a GET; an htmx one answers HX-Location or a fragment. 303 stops a refresh from resubmitting. A 303 to an htmx request is followed by the XHR and the whole redirected page gets swapped into the target, which is never what you want.
  4. Forms work without JavaScript. Real action and method, a real submit button; htmx attributes layer on top. The non-JS path is also the path the 303 rule serves.
  5. A repeated attribute bundle becomes a named {{define}} partial. Four attributes copied to seventeen links drift the moment one copy changes. One partial, one place to change it. (codebase-design has the vocabulary for why: one deep module beats many shallow copies.)
  6. Polling never fights the user. hx-sync on every polling element, a guard that skips the poll while the user is focused or typing inside the target, and a target that never contains an input the user may be editing.
  7. Errors reach the user. htmx 2.x does not swap 4xx/5xx bodies by default, so a refused action looks like nothing happened. Fix it in two halves: a responseHandling entry that swaps the status you use (typically 422), and HX-Retarget / HX-Reswap from the server so the error lands in a known region. That region is a persistent aria-live container.
  8. In-flight state is visible. hx-disabled-elt on submit controls so a double-click cannot double-submit; hx-indicator or aria-busy on the region being replaced.
  9. Client JS is the exception, and it is never inline. Before writing any, ask whether the server can own it (a preference, a re-rendered region) or HTML can (<details>, <dialog>, popover). A widget with real client state becomes an island in the repo's frontend framework, mounted through htmx.onLoad and unmounted on swap. The only other JS is a fixed set of htmx glue listeners. No <script> blocks, onclick or hx-on in templates: inline handlers are untestable and re-run unpredictably on swaps. htmx config goes in <meta name="htmx-config"> with "allowEval": false, so htmx itself refuses hx-on and js: values.
  10. Templates branch on presentation only. {{if eq .Status "failed"}} chains are domain logic in the wrong layer. Compute a view-model field in Go (.Badge, .CanRetry) and let the template read it.

Choosing a response shape

request ──► HX-History-Restore-Request: true? ──yes──► page
               │ no
               ▼
            HX-Request: true? ──no──► POST? ──yes──► 303 to GET (or re-render page with 422 on invalid)
               │ yes                       └─no──► page
               ▼
            route declares: fragment ──► ExecuteTemplate(w, "<block>", vm)
                            page+select ──► page (template uses hx-select)
                            redirect ──► HX-Location (or HX-Redirect for a full reload)

references/responses.md has the helper set and a handler written both ways.

htmx version

These rules target htmx 2.x. Check the version the repo vendors before relying on defaults. If it is on 4.x, re-check rules 7 and 9 against the 4.x migration notes:

  • error responses swap by default, with per-status control through hx-status;
  • attribute inheritance is explicit, so bundles that relied on inheriting hx-target break;
  • event names changed, so listeners in the TS module need renaming.

What not to do

  • Don't reach for the response-targets extension to route errors. It moves a server decision into markup and adds a second mechanism next to HX-Retarget.
  • Don't swap an aria-live region with outerHTML. Screen readers track the original node; a replaced live region announces nothing. Swap its innerHTML.
  • Don't render into the ResponseWriter directly. Execute into a buffer first, so a template error becomes a 500 rather than a half-written 200.
  • Don't add hx-boost to fix a navigation problem. Declare the nav-link partial instead; boost changes every link and form under it at once.
  • Don't restate the htmx attribute reference here or in the repo; link htmx.org/reference.

04 同仓库更多 Skills

O-Marsters-1997
O-Marsters-1997/my-claude-code

to-tickets

Breaks a source into independently-grabbable GitHub tickets. For a code feature the source is the plan (`docs/plans/<feature>.md`, from /to-plan) and every new or changed symbol lands in exactly one ticket, its signatures copied into the ticket body; a non-code feature is cut from the PRD's slices. Cuts tickets for one feature per run. If a code feature has no approved plan, offers /to-plan instead of cutting from prose. In a repo that runs command-centre, also emits `[[task]]` blocks into its config; in a plain treepad repo, emits a Batch Manifest instead so the tickets materialise as stacked worktrees.

★ 0
O-Marsters-1997
O-Marsters-1997/my-claude-code

to-seams

Records an agreed-but-unlanded cross-repo interface as a seam: the file a consumer's agent gets pasted into its prompt as ground truth, plus the `[[seam]]` block command-centre reads for the retirement pointer. Use when two repos need to build against an interface neither has landed yet — "record a seam for X", "we agreed on this schema, seam it", "add a seam so Y can build against Z's new field". Halts for approval before writing either file.

Skill与智能体开发
★ 0
O-Marsters-1997
O-Marsters-1997/my-claude-code

to-roadmap

Prioritises settled features into a Now / Next / Later kanban board, rendered as a self-contained ./ideas/roadmap.html. Each card is a feature, not a ticket — one card later becomes several tickets via /to-prd -> /to-plan -> /to-tickets. Boards the features in ./docs/approach.md, or the "## Accepted ideas" in ./ideas/CONTEXT.md when there is no approach doc. The approach doc is settled truth: this assigns tiers and reasons about ordering, it never re-litigates what was decided.

产品经理
★ 0
O-Marsters-1997
O-Marsters-1997/my-claude-code

to-prd

Turns one feature idea into a PRD built on journeys: a one-line problem, journeys (each ending in an observable state) and delivery slices that say what is usable after each. Interviews, explores the codebase, and saves to docs/prds/<feature>.md. Covers exactly one feature: given a multi-feature source, ask which one. Reads any approach doc or ideate report as priors so it doesn't re-ask what's settled, but needs none. Starts the per-feature spine (/to-prd -> /to-plan -> /to-tickets).

产品经理
★ 0
O-Marsters-1997
O-Marsters-1997/my-claude-code

to-plan

Turns one feature's PRD into a skimmable plan in docs/plans/<feature>.md: a short overview, then per phase a glossary, the journeys it satisfies, and its new and modified definitions (types, enums, ports, schema), with the project:<slug> label. No code, branch or PR; the user's review of the file is the gate. Use for "plan this feature", "write the contract", "what are the types". One feature per run. Slash-only.

★ 0
O-Marsters-1997
O-Marsters-1997/my-claude-code

ticket-tracker

Use when the request is about the *current state* of GitHub issues rather than creating new ones: "where are my tickets", "show the board", "what's in progress", "what's ready to pick up", "move issue N to in-review", "mark N done", "update the ticket status". Live triage board over GitHub issues via the gh CLI, moving each between backlog -> ready -> in-progress -> in-review -> done using status labels. This is the ticket-level board; ./ideas/roadmap.html is the feature-level one. To file new tickets, use /to-tickets, file-issue for a single ad-hoc one, or /sweep for a batch of small fixes.

★ 0