| name | Project: Scaffold from Artefact |
| description | {{ ๐๐๐ }} Convert an exported Claude artefact (HTML or JSX) into a working Svelte 5 / SvelteKit 2 project |
| when_to_use | When a design or prototype exported from an Artifact (HTML or React/JSX) needs turning into a real, runnable project scaffold. |
| model | opus |
| disable-model-invocation | true |
| allowed-tools | ["Read","Glob","Grep","Edit","Write","Bash(bun:*)","Bash(bunx:*)","Bash(npm:*)","Bash(git:*)","Bash(mkdir:*)","Bash(open:*)","Bash(find:*)"] |
| argument-hint | ["path to the exported .html/.jsx artefact (optional); add \"react\" to opt into React/Next"] |
Take a single-file artefact exported from Claude Chat or Cowork (an interactive HTML page or a JSX component) and grow it into a real, runnable project in Jason's default stack. Understand the artefact, interview for the decisions only a human can make, then port it: scaffold a project, translate the artefact into components or routes, and rewire its styling onto Reasonable Colors. A full-project tail (tests, git, docs, deploy) follows and is skippable.
Default target is Svelte 5 (runes) / SvelteKit 2. A JSX artefact becomes Svelte 5 components; an HTML artefact becomes a SvelteKit route. React/Next.js is an explicit opt-in. Nothing is scaffolded until the project config is approved.
Announce at start: "I'm using the Scaffold-from-Artefact skill. I'll read {file} first, then ask a few quick questions before building anything."
Step 1 โ Interpret $ARGUMENTS and locate the artefact
Confirm the resolved absolute path and the detected artefact type back to the user in one line before reading.
Step 2 โ Read and understand the artefact
Read the whole file. Build an inventory before translating anything or asking any questions; a rushed port loses interactivity, and an uninformed interview asks questions the artefact already answers. Capture:
- Structure: the visible sections/components and how they nest. For a monolith, note the seams where it could decompose into components.
- State and interactivity: every piece of mutable state, what mutates it, and every event handler. This is the part that must survive the port; static markup is easy, state is where ports break.
- Data shapes: the objects the artefact renders (arrays of items, config objects, form state). These become TypeScript interfaces in Step 6.
- External dependencies: CDN
<script>/<link> tags (React UMD, Tailwind CDN, Babel standalone, charting libs, icon fonts), Google Fonts, inline import from esm.sh/unpkg. Each is a decision: replace with a bun dependency, keep as a CDN link, or drop.
- Styling: inline
style=, a <style> block, Tailwind utility classes, or a CSS-in-JS object. Note every hardcoded colour (hex, rgb(), named) for Step 7.
- Signs of a backend need: does the artefact simulate fetching data, persist anything to
localStorage, or fake an API call? This informs the backend/database question in Step 3.
- React-specific idioms (JSX only): hooks in use (
useState, useEffect, useMemo, useRef, useContext), portals, dangerouslySetInnerHTML, children composition, refs to DOM nodes, effect cleanup functions. Flag each one that will need care in Step 4.
Produce a short written inventory (components, state, deps, backend signals, React idioms found) and show it before the interview.
Step 3 โ Interview for the project-shaping decisions
Some decisions are the user's to make, not yours to assume. Run a short structured interview, adapting the round discipline of the roadmap-create-interview skill: ask 2โ4 questions per round, never dump a long list at once, acknowledge briefly (don't repeat answers verbatim), and end each round with "Anything else, or shall I write up the config?". This is a conversation, not a form.
Skip any question the arguments or the Step 2 inventory already answers (don't ask about a backend if the artefact is clearly static; don't ask the stack if react was passed).
Decisions to capture:
- Project name.
- Target stack: default Svelte 5 / SvelteKit 2; React/Next.js only on explicit opt-in. Recommend based on the detected artefact type.
- Backend/database needed? Informs SvelteKit server routes (
+page.server.ts) vs a static site. If yes, which paradigm per Jason's stack: PostgreSQL/Supabase (relational), Neo4j (graph), MongoDB (object), or none.
- Auth needed?
- Deployment target: Vercel / Deno Deploy / GitHub Pages. Recommend one based on whether a server is needed (GitHub Pages only suits a fully static build).
- Which tail parts (Step 9) the user wants: tests, git, docs, deploy, any combination, or none.
For closed choices (deployment target, stack, backend paradigm), use the AskUserQuestion tool with your recommendation listed first. Keep open-ended threads (project name, auth specifics) conversational.
Synthesise a short config proposal once the interview is done, e.g.:
Project: {name}
Stack: Svelte 5 / SvelteKit 2
Backend: none (static)
Auth: none
Deploy: Vercel
Tail: tests + git, skip docs/deploy config for now
Get explicit approval before scaffolding. Nothing is built until the user signs off; treat this the same as the interview skill treats "nothing is written to the roadmap until approved".
Step 4 โ Announce the translation
State the artefactโstack mapping from the approved config:
- JSX artefact โ Svelte 5 components. One
.svelte component per React component; a monolith decomposes in Step 6.
- HTML artefact โ a SvelteKit route. Markup goes into
+page.svelte; page-load data (if any) into +page.ts or +page.server.ts if a backend was chosen.
- React opt-in: mirror the artefact's own framework: JSX stays React components, HTML becomes a Next.js/Vite React page. Skip the rune mapping below but keep the styling and tail steps.
React idiom โ Svelte 5 rune mapping: read ~/.claude/library/references/react-to-svelte5.md and state the mappings actually used by this artefact (plus the gotchas it lists that apply โ effect cleanup timing, synchronous context, portals, ref-as-box).
Step 5 โ Scaffold the project skeleton
Choose the scaffold from the artefact type and approved stack:
- HTML โ SvelteKit 2:
bun create svelte@latest {name} (Skeleton project, TypeScript, add Vitest when the tail includes tests). Verify the current scaffold command via context7/docs rather than guessing; sv create has superseded create svelte in some tooling versions.
- JSX (few components, no routing) โ plain Svelte + Vite:
bun create vite@latest {name} --template svelte-ts.
- React opt-in:
bun create vite@latest {name} --template react-ts, or bunx create-next-app@latest if the artefact implies routing/SSR.
Package manager: bun (Jason's tiebreak: bun > deno > npm/pnpm). Use bun install, bun add, bun run.
TypeScript strict is mandatory. Ensure tsconfig.json has "strict": true (SvelteKit's default already does; verify). Encode Jason's TS standards as you write code: interfaces over types for object shapes, no any (use unknown), explicit return types on exported functions, discriminated unions where the data warrants.
File naming and indentation:
.ts/.js/.json: kebab-case (colour-utils.ts).
.svelte/.tsx/.jsx: PascalCase (FilterBar.svelte).
- Tabs, not spaces. Write files with tabs; when editing, preserve exact tab characters and use the Edit tool (never sed/awk).
Expected layout (SvelteKit):
src/
routes/
+page.svelte # ported page
+page.ts # load data, if any
+page.server.ts # only if the interview chose a backend
lib/
components/ # PascalCase .svelte components
types.ts # data-shape interfaces
styles/
tokens.css # Reasonable Colors semantic aliases (Step 7)
tests/
fixtures/ # named-export fixtures (tail)
docs/
adrs/ # 001-*.md (tail)
If the interview chose a backend/database, note where it wires in but do not build the data layer unless asked; that is out of scope for the port itself.
Step 6 โ Port the artefact into components/routes
Translate the inventory from Step 2 into real source files.
Step 7 โ Rewire styling onto Reasonable Colors
Replace every hardcoded colour from Step 2 with semantic aliases backed by Reasonable Colors. Read ~/.claude/library/references/reasonable-colors-reference.md first for the shade/contrast rules and the full palette; do not guess hex values.
- Install:
bun add reasonable-colors (or the CDN link unpkg.com/reasonable-colors@0.4.0/reasonable-colors.css for a no-build HTML case). Import it once at the app root.
- Define semantic aliases in
src/lib/styles/tokens.css, mapping RC vars to roles:
:root {
--color-primary: var(--color-azure-3);
--color-primary-bg: var(--color-azure-1);
--color-on-primary: var(--color-azure-6);
--color-surface: var(--color-gray-1);
--color-text: var(--color-gray-6);
--color-danger: var(--color-red-3);
}
Provide a @media (prefers-color-scheme: dark) counterpart if the artefact had any dark styling.
- Replace hardcoded colours in components with the semantic aliases only. Components must NEVER reference
--color-{name}-{shade} (RC vars) directly; they reference --color-primary etc. This is the non-negotiable rule.
- Respect contrast: choose shade pairs by the table (diff 2 = 3:1 AA large/UI, diff 3 = 4.5:1 AA body, diff 4 = 7:1 AAA). Body text against its background should be at least a 3-shade difference.
- The
color (US spelling) in RC var names is the library's convention and is acceptable; use British spelling everywhere else.
Step 8 โ Verify it runs (core deliverable)
The port is not done until the page runs and the interactivity works end-to-end. This step is part of the core, not the skippable tail.
bun run dev
Then load the served URL (Bash(open:*) the localhost address, or drive it with the browser tools) and check:
- The page renders and is visually recognisable versus the original artefact.
- Every interaction from the Step 2 inventory works: click each handler, toggle each piece of state, exercise each list/filter. Interactivity parity is the acceptance test.
- No console errors; TypeScript is clean (
bun run check on SvelteKit).
Report what runs and any behaviour that did not survive the port (with the reason), before touching the tail.
Step 9 โ Full-project tail (only the parts chosen in Step 3)
Run only the tail parts the user selected during the interview. Each sub-section stands alone.
9a. Vitest test stub + fixtures
- Vitest is the default (natural for Svelte/Bun). Add a
module-name.test.ts alongside one critical module (prefer an integration test on a critical path over exhaustive units).
- Fixtures as named exports in
tests/fixtures/<module>.ts, imported with import * as fixtures from '../fixtures/<module>'.
- Ship a real, passing stub test (e.g. render a ported component, assert one interaction) so the harness is proven, not just present.
9b. Git init and first commit
git init
git add . && git commit -m "chore: scaffold project from Claude artefact"
Confirm .gitignore covers node_modules, build output, and any .env before that first git add. No hook symlinks; there is no bootstrap template this skill depends on.
9c. ADR + README from Jason's templates
- Read
~/.claude/library/templates/ADR.md and write docs/adrs/001-initial-tech-stack.md recording the stack choice and the artefact-to-Svelte translation rationale. Follow the template's exact section order; do not invent a format.
- For the README, read
~/.claude/library/templates/readme-root.md and emit a README.md from it.
9d. Deploy config
Step 10 โ Report
Summarise: artefact source path; approved config (stack, backend, auth, deploy); component/route layout; interactions verified; which tail parts ran; anything that did not survive the port (with reasons). Surface any flagged React idiom that needed a manual workaround inline so the user sees it without opening files.
Quick Reference
| Stage | Rule |
|---|
| Locate | Resolve an existing absolute path; scan ~/Downloads/~/Desktop/cwd before asking |
| Understand | Full inventory (state, deps, colours, backend signals) before the interview |
| Interview | 2-4 questions per round; closed choices via AskUserQuestion; propose config, get approval before building |
| Target | Svelte 5 / SvelteKit 2 by default; React/Next only on explicit opt-in |
| JSX โ | Svelte 5 components ($state/$effect/$derived/$props) |
| HTML โ | SvelteKit route (+page.svelte / +page.ts) |
| Package mgr | bun (tiebreak: bun > deno > npm/pnpm) |
| Types | interface per shape, unknown over any, explicit return types |
| Naming | .ts/.json kebab-case; .svelte/.tsx PascalCase; tabs, Edit tool only |
| Colour | Reasonable Colors; semantic aliases only in components; read the reference doc |
| Contrast | shade diff 2 = 3:1, 3 = 4.5:1 (AA body), 4 = 7:1 (AAA) |
| Verify | bun run dev + drive every interaction; core, not tail |
| Tail | Only the parts chosen in the interview: tests / git / docs / deploy |
Common Mistakes
- Dumping all interview questions at once. 2-4 per round; it should read as a conversation, not a form.
- Scaffolding before the config is approved. The interview's proposal needs a sign-off first, same as the roadmap interviewer never writes before approval.
- Porting markup but dropping interactivity. The state and handlers are the point; catalogue them in Step 2 and verify each live in Step 8.
useEffect โ $effect without checking cleanup. Teardown timing differs; verify the cleanup fires on the right change.
- Turning a
useRef mutable box into $state. A ref-as-box is intentionally non-reactive; keep it a plain let.
- Referencing RC vars directly in components. Always go through the semantic alias layer.
- Guessing colour hexes. Read
reasonable-colors-reference.md.
- Spaces instead of tabs, or sed/awk edits. Tabs only; Edit tool only.
- Running tail parts the user didn't choose. The interview decides the tail; don't add scope back in.
- Inventing a README format. Use
readme-root.md; use ADR.md for the ADR.
- Guessing the scaffold command. Verify the current
create svelte/sv create invocation against docs before running.
Red Flags
Never:
- Commit secrets,
.env, or node_modules (set .gitignore before the first git add).
- Leave a hardcoded colour or a direct RC-var reference in a component.
- Use
any, spaces for indentation, or sed/awk to edit files.
- Ship the port without running it and driving every interaction.
- Silently drop an interaction because it was awkward to translate; flag it.
- Scaffold before the project config is proposed and approved.
- Run tail parts beyond what the interview selected.
- Use em dashes in body prose, US spelling, or "not X but Y" couplets.
Always:
- Understand the artefact fully before asking a single interview question.
- Ask in small rounds; end each round offering to write up the config.
- Announce the artefact-to-stack translation before writing code.
- Default to Svelte 5 / SvelteKit 2; treat React/Next as an explicit opt-in.
- Declare data shapes once as interfaces and import them.
- Route all component colours through semantic aliases; read the reference doc.
- Verify with
bun run dev and live interaction before the tail.
- Generate the ADR and README from the library templates.