From artifact-refiner
Convert an HTMX + Alpine.js HTML artifact into a React TSX component ready for the scaffold-react-vite pipeline. Mechanical transforms run via a Node script; HTMX/Alpine constructs requiring judgment are surfaced as a sidecar markdown for review.
How this skill is triggered — by the user, by Claude, or both
Slash command
/artifact-refiner:convert-htmx-reactThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Convert an HTMX + Alpine.js HTML artifact into a React TSX component.
Convert an HTMX + Alpine.js HTML artifact into a React TSX component.
artifact_type: html (input) → react (output)content_type: direct:reactreferences/domain/ui.mdThe user will provide: $ARGUMENTS
Parse the arguments for:
--source <path-to-html> (required)--feature-name <kebab-name> (required) — used to name the component (PascalCase) and the hook--output <path-to-tsx> (required)--ambiguous-sidecar <path> (optional; default <output>.ambiguous.md)Dispatch to the orchestration script:
node scripts/convert-htmx-react.mjs \
--source "${SOURCE}" \
--feature-name "${FEATURE}" \
--output "${OUTPUT}"
The script:
parse5 (spec-conformant HTML5 parsing).class → className, for → htmlForstyle="a: b" → style={{ a: "b" }}data-*, aria-*, role, id, src, href, etc. pass through unchangedx-data="{ count: 0 }" into a named hook use<Feature>State exporting useState declarations.@click="count++" → onClick={() => setCount((v) => v + 1)}@click="x = expr" → onClick={() => setX(expr)}x-text="count" → {count} JSX childhx-* behaviors (hx-get, hx-post, hx-target, hx-swap)x-show, x-model, x-if (non-trivial Alpine constructs)The sidecar <output>.ambiguous.md lists each region the script couldn't auto-convert with confidence. For each region:
Review each region, accept the recommendation or propose an alternative, and apply the change manually before feeding the TSX into the scaffolder. The script's job is to do 90% mechanical work and document the remaining 10% clearly — not to guess.
When the source HTMX contains Alpine x-data="{ ... }", the converter lifts
the state to React. The threshold determines the shape of the React state:
| Alpine x-data shape | React shape |
|---|---|
Single boolean field ({ open: false }, { active: true }) | Local useState hook |
Multi-field ({ count: 0, label: "idle" }) | zustand+immer store + hook adapter |
Single non-boolean field ({ count: 0 }) | zustand+immer store + hook adapter |
Rationale: per references/scaffolds/state-architecture.md, ephemeral
single-component state (e.g., dropdown open/closed) belongs in local useState;
anything that might be shared, persisted, or grow beyond a toggle belongs in
a store. The threshold catches counts, labels, and arrays at conversion time so
the scaffolder's useXxxStore routing picks them up correctly.
.html fragment or document..tsx file with a default-exported component named <PascalFeature> and (if Alpine state was present) a named hook use<PascalFeature>State.artifact_type: react
content_type: direct:react
outputs:
- path: <output>.tsx
description: Scaffolder-ready TSX with default component + optional named hook
- path: <output>.ambiguous.md
description: (only when ambiguous regions found) review-required transforms
constraints_satisfied:
- mechanical_transforms_complete
- alpine_state_lifted_to_useState
- htmx_behaviors_documented_for_review
- scaffolder_input_shape_matched
Typical flow:
HTMX artifact → convert-htmx-react → TSX → scaffold-react-vite → built Vite project
↓
(optionally) → rebrand-artifact for brand swap
scripts/convert-htmx-react.mjs — the orchestration scriptopenspec/changes/phase-3-conversion-layer/ — design rationaleProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub gqadonis/artifact-refiner-skill --plugin artifact-refiner