skills/project-scaffold-from_artefact/SKILL.md
{{ 𝛀𝛀𝛀 }} Convert an exported Claude artefact (HTML or JSX) into a working Svelte 5 / SvelteKit 2 project
npx skillsauth add jasonwarrenuk/goblin-mode Project: Scaffold from ArtefactInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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."
$ARGUMENTS and locate the artefact.html, .htm, .jsx, .tsx, .svelte).react (or next) appears in the arguments: set the target stack to React/Next.js instead of the Svelte default. Note it and carry it into Step 3.find . ~/Downloads ~/Desktop -maxdepth 3 \
\( -iname "*.jsx" -o -iname "*.tsx" -o -iname "*.html" \) \
-not -path "*/node_modules/*" -mtime -7 2>/dev/null
Present the candidates (most-recently-modified first) and ask which one. Do not guess if more than one plausible match exists.Confirm the resolved absolute path and the detected artefact type back to the user in one line before reading.
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:
<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.style=, a <style> block, Tailwind utility classes, or a CSS-in-JS object. Note every hardcoded colour (hex, rgb(), named) for Step 7.localStorage, or fake an API call? This informs the backend/database question in Step 3.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.
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:
+page.server.ts) vs a static site. If yes, which paradigm per Jason's stack: PostgreSQL/Supabase (relational), Neo4j (graph), MongoDB (object), 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".
AskUserQuestion with a recommendationState the artefact→stack mapping from the approved config:
.svelte component per React component; a monolith decomposes in Step 6.+page.svelte; page-load data (if any) into +page.ts or +page.server.ts if a backend was chosen.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).
Choose the scaffold from the artefact type and approved stack:
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.bun create vite@latest {name} --template svelte-ts.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).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.
tsconfig strict verifiedTranslate the inventory from Step 2 into real source files.
Decompose the monolith. Split by the seams noted in Step 2: one component per cohesive UI region (a FilterBar, a Card, a Chart). Keep components small; lift shared state to the parent or a lib rune module (.svelte.ts).
Types first. Write the data-shape interfaces into src/lib/types.ts before the components, and import them where the data flows. Explicit interface per object shape, unknown over any.
Translate state and handlers per the Step 4 mapping. Port interactivity behaviour-for-behaviour; do not silently drop a handler because it is awkward.
Replace external deps per the Step 2 decisions: swap CDN libs for bun dependencies (bun add), keep Google Fonts as links, remove React/Babel-standalone CDN tags entirely (the framework now provides them).
Preserve the markup structure so the ported page is visually recognisable before restyling.
Leave styling hardcoded for now; Step 7 rewires it. Wire up structure and behaviour here.
[ ] Monolith decomposed into named components in their real files
[ ] Data shapes declared once as interfaces and imported
[ ] Every stateful behaviour from Step 2 reproduced
[ ] External deps resolved (added, kept, or removed)
[ ] No any; exported functions have explicit return types
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.
bun add reasonable-colors (or the CDN link unpkg.com/[email protected]/reasonable-colors.css for a no-build HTML case). Import it once at the app root.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.--color-{name}-{shade} (RC vars) directly; they reference --color-primary etc. This is the non-negotiable rule.color (US spelling) in RC var names is the library's convention and is acceptable; use British spelling everywhere else.reasonable-colors installed/linked and imported oncetokens.cssThe 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:
bun run check on SvelteKit).Report what runs and any behaviour that did not survive the port (with the reason), before touching the tail.
bun run dev serves without errorsbun run check / typecheck cleanRun only the tail parts the user selected during the interview. Each sub-section stands alone.
9a. Vitest test stub + fixtures
module-name.test.ts alongside one critical module (prefer an integration test on a critical path over exhaustive units).tests/fixtures/<module>.ts, imported with import * as fixtures from '../fixtures/<module>'.9b. Git init and first commit
# .gitignore BEFORE the first git add: never commit secrets, node_modules, or build output.
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
~/.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.~/.claude/library/templates/readme-root.md and emit a README.md from it.9d. Deploy config
Configure only the target chosen in Step 3: Vercel (@sveltejs/adapter-vercel or auto), Deno Deploy (adapter-deno / static), GitHub Pages (@sveltejs/adapter-static + base path). Install and set the one adapter; do not scaffold config for targets not chosen.
[ ] Only the tail parts chosen in Step 3 ran
[ ] .gitignore covers node_modules / build / .env before first commit
[ ] Conventional-commit first commit (chore:)
[ ] ADR + README generated from the library templates (not invented)
[ ] Deploy adapter matches the interviewed target, nothing else configured
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.
| 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 |
useEffect → $effect without checking cleanup. Teardown timing differs; verify the cleanup fires on the right change.useRef mutable box into $state. A ref-as-box is intentionally non-reactive; keep it a plain let.reasonable-colors-reference.md.readme-root.md; use ADR.md for the ADR.create svelte/sv create invocation against docs before running.Never:
.env, or node_modules (set .gitignore before the first git add).any, spaces for indentation, or sed/awk to edit files.Always:
bun run dev and live interaction before the tail.tools
{{ 𝚫𝚫𝚫 }} Rebuild roadmap-system.zip, the distributable snapshot of the roadmap tooling (scripts, HTML template, conventions reference, and every roadmap-touching skill, including this one).
tools
--- name: "Suggest: Task" description: "{{ 𝚫𝚫𝚫 }} Suggest the next logical task — grounded in the roadmap's pre-vetted ready-set when one exists, codebase analysis otherwise" when_to_use: "When you don't know what to work on next and want a grounded recommendation rather than picking arbitrarily." model: haiku effort: low disable-model-invocation: true allowed-tools: ["Read", "Glob", "Grep", "Bash(python3:*)", "Bash(npm:*)", "Bash(bun:*)", "Bash(pnpm:*)", "Bash(deno:*)"] argument-hint: [named
development
{{ 𝛀𝛀𝛀 }} Convert an old simple-style roadmap (single Markdown, four statuses, <a name> anchors, roadmaps.json pointer registry) into the rich phase-array format (roadmaps.json source of truth + PHASE task list + prose overview).
data-ai
{{ ƔƔƔ }} Create a pull request to main — wordy or shiny (with screenshots), ready-for-review or draft