Project scaffold from artefact
Skill JasonWarrenUK/goblin-mode/skills/project-scaffold-from_artefact
Three goblins in a trenchcoat pretending to be a senior developer. Claude Code config shaped by ADHD, friction, and spite.
npx -y skills add JasonWarrenUK/goblin-mode --skill project-scaffold-from_artefactAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 5 stars5 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
{{ πππ }} Convert an exported Claude artefact (HTML or JSX) into a working Svelte 5 / SvelteKit 2 project
SKILL.md
19.4 KB, ~4.7k tokens by cl100k_base, as published. Nobody here has run it
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
- A path is given and the file exists: use it. Record its extension (
.html,.htm,.jsx,.tsx,.svelte). react(ornext) 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.- No path given: search the likely export locations before asking. Run a read-only scan:
Present the candidates (most-recently-modified first) and ask which one. Do not guess if more than one plausible match exists.find . ~/Downloads ~/Desktop -maxdepth 3 \ \( -iname "*.jsx" -o -iname "*.tsx" -o -iname "*.html" \) \ -not -path "*/node_modules/*" -mtime -7 2>/dev/null - Nothing found: ask the user for the path and stop. Do not invent an artefact.
Confirm the resolved absolute path and the detected artefact type back to the user in one line before reading.
- Artefact file resolved to an absolute path that exists
- Artefact type detected (HTML vs JSX/TSX)
- Any stack opt-in from the arguments recorded
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, inlineimportfromesm.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,childrencomposition, 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.
- Every stateful behaviour catalogued
- Every external dependency listed with a keep/replace/drop decision proposed
- Backend/persistence signals noted
- React-specific idioms flagged (JSX case)
- Hardcoded colours collected for the styling step
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".
- All undetermined decisions covered in 2-4-question rounds, none dumped at once
- Closed choices used
AskUserQuestionwith a recommendation - Config proposal shown and approved before Step 4 begins
Step 4 β Announce the translation
State the artefactβstack mapping from the approved config:
- JSX artefact β Svelte 5 components. One
.sveltecomponent 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.tsor+page.server.tsif 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).
- Every React idiom in the artefact has a named Svelte target (or a flagged manual port)
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 createhas supersededcreate sveltein 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, orbunx create-next-app@latestif 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.
- Scaffold created with bun and the right template
-
tsconfigstrict verified - Directory layout matches the stack and approved config
Step 6 β Port the artefact into components/routes
Translate 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, aCard, aChart). Keep components small; lift shared state to the parent or alibrune module (.svelte.ts). -
Types first. Write the data-shape interfaces into
src/lib/types.tsbefore the components, and import them where the data flows. Explicitinterfaceper object shape,unknownoverany. -
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
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 linkunpkg.com/[email protected]/reasonable-colors.cssfor 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:
Provide a: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); }@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-primaryetc. 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.
-
reasonable-colorsinstalled/linked and imported once - Semantic alias layer defined in
tokens.css - Zero hardcoded colours left in components
- Zero direct RC-var references in components (aliases only)
- Body text meets at least AA (shade diff β₯ 3)
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 checkon SvelteKit).
Report what runs and any behaviour that did not survive the port (with the reason), before touching the tail.
-
bun run devserves without errors - Every catalogued interaction verified live
-
bun run check/ typecheck clean
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.tsalongside one critical module (prefer an integration test on a critical path over exhaustive units). - Fixtures as named exports in
tests/fixtures/<module>.ts, imported withimport * 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
# .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
- Read
~/.claude/library/templates/ADR.mdand writedocs/adrs/001-initial-tech-stack.mdrecording 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.mdand emit aREADME.mdfrom it.
9d. Deploy config
-
Configure only the target chosen in Step 3: Vercel (
@sveltejs/adapter-vercelor 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
-
.gitignorecovers 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
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β$effectwithout checking cleanup. Teardown timing differs; verify the cleanup fires on the right change.- Turning a
useRefmutable box into$state. A ref-as-box is intentionally non-reactive; keep it a plainlet. - 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; useADR.mdfor the ADR. - Guessing the scaffold command. Verify the current
create svelte/sv createinvocation against docs before running.
Red Flags
Never:
- Commit secrets,
.env, ornode_modules(set.gitignorebefore the firstgit 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 devand live interaction before the tail. - Generate the ADR and README from the library templates.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.