Stitch-kit stitch-svelte-components
Converts Stitch designs into Svelte 5 / SvelteKit components using the runes API — scoped CSS with custom properties, built-in transitions, TypeScript, dark mode, and accessible markup.
git clone https://github.com/gabelul/stitch-kit
T=$(mktemp -d) && git clone --depth=1 https://github.com/gabelul/stitch-kit "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/stitch-svelte-components" ~/.claude/skills/gabelul-stitch-kit-stitch-svelte-components && rm -rf "$T"
skills/stitch-svelte-components/SKILL.mdStitch → Svelte 5 / SvelteKit Components
You are a Svelte 5 engineer. You convert Stitch design screens into idiomatic Svelte components — using the runes API (
$state, $props, $derived, $effect), not the legacy Options API. Components use scoped CSS with custom properties for theming, built-in Svelte transitions for animation, and accessible markup by default.
Note: This is the only Stitch skill that targets Svelte. The official
skill targets Vite/React. Use this skill when the project uses SvelteKit.react-components
When to use this skill
Use this skill when:
- The target project uses SvelteKit or Svelte 5 standalone
- You see
files,.svelte
, orsvelte.config.js
conventions+page.svelte - The user mentions
,svelte
,sveltekit
,$state
, or$propsrunes
Prerequisites
- Access to the Stitch MCP server
- A Stitch project with at least one generated screen
- Target project uses Svelte 5 (runes enabled) — check
forpackage.json"svelte": "^5"
Step 1: Retrieve the Stitch design
- Namespace discovery — Run
to find the Stitch MCP prefix. Use it for all subsequent calls.list_tools - Fetch screen metadata — Call
to retrieve design JSON.[prefix]:get_screen - Download HTML — Use the reliable downloader:
bash scripts/fetch-stitch.sh "[htmlCode.downloadUrl]" "temp/source.html" - Visual reference — Check
before writing code.screenshot.downloadUrl
Step 2: SvelteKit file conventions
SvelteKit uses file-based routing. Map Stitch screens to this structure:
src/ ├── routes/ │ ├── +layout.svelte ← Persistent shell (nav, footer) │ ├── +layout.ts ← Layout load function (optional) │ ├── +page.svelte ← Route page component │ ├── [route]/ │ │ ├── +page.svelte ← Sub-route page │ │ └── +page.ts ← Page load function (server-side data) ├── lib/ │ ├── components/ ← Reusable components │ │ └── [Name].svelte │ ├── data/ │ │ └── mockData.ts ← Decoupled static content │ └── types/ │ └── index.ts ← Shared types static/ ← Static assets
Key rules:
- Pages live in
assrc/routes/+page.svelte - Reusable components live in
src/lib/components/ - Import
is an alias for$lib/
— always use itsrc/lib/
Step 3: Svelte 5 runes API
Use runes exclusively. Never use the old
export let, let x = 0 reactive syntax, or $: labels.
Props
<script lang="ts"> interface Props { title: string description?: string onAction?: () => void } // $props() replaces export let const { title, description = 'Default text', onAction }: Props = $props() </script>
Reactive state
<script lang="ts"> // $state() replaces let count = 0 let count = $state(0) let isOpen = $state(false) // $derived() replaces $: doubled = count * 2 const doubled = $derived(count * 2) // $effect() replaces onMount / afterUpdate for side effects $effect(() => { console.log('count changed:', count) }) </script>
Event handling
<!-- Direct event attributes, no createEventDispatcher --> <button onclick={() => count++}>Increment</button> <button onclick={onAction}>Custom action</button>
Step 4: Scoped CSS with design tokens
Svelte scopes CSS to the component by default — use this aggressively. Map Stitch colors to custom properties in the
:root (via +layout.svelte or app.css) and reference them in each component.
In
(global):src/app.css
:root { --color-background: #ffffff; --color-surface: #f4f4f5; --color-primary: /* dominant color from Stitch design */; --color-primary-foreground: #ffffff; --color-text: #09090b; --color-text-muted: #71717a; --color-border: #e4e4e7; } [data-theme='dark'] { --color-background: #09090b; --color-surface: #18181b; --color-primary: /* same hue, adjusted for dark bg */; --color-primary-foreground: #09090b; --color-text: #fafafa; --color-text-muted: #a1a1aa; --color-border: #27272a; }
In each component (scoped):
<style> .card { background-color: var(--color-surface); border: 1px solid var(--color-border); color: var(--color-text); border-radius: 0.5rem; padding: 1.5rem; } .card:hover { /* Scoped — won't leak to parent or children */ border-color: var(--color-primary); } </style>
Dark mode toggle — Add a
$state in +layout.svelte:
<script lang="ts"> let theme = $state<'light' | 'dark'>('light') function toggleTheme() { theme = theme === 'light' ? 'dark' : 'light' document.documentElement.setAttribute('data-theme', theme) } </script> <svelte:element this="div" data-theme={theme}> {@render children()} </svelte:element>
Step 5: Built-in transitions and animations
Svelte has first-class transition support. Apply these from the Stitch design intent:
<script lang="ts"> import { fade, fly, slide, scale } from 'svelte/transition' import { cubicOut } from 'svelte/easing' let show = $state(false) </script> <!-- Page entry fade --> <div transition:fade={{ duration: 200 }}> Content that fades in </div> <!-- Slide panel --> {#if isOpen} <aside transition:fly={{ x: -300, duration: 300, easing: cubicOut }}> Sidebar content </aside> {/if} <!-- Collapsible section --> {#if expanded} <div transition:slide={{ duration: 200 }}> Expandable content </div> {/if}
Always respect reduced motion:
<script lang="ts"> // Check user preference once const prefersReducedMotion = $state( typeof window !== 'undefined' ? window.matchMedia('(prefers-reduced-motion: reduce)').matches : false ) // Conditionally disable transitions const transitionOptions = $derived( prefersReducedMotion ? {} : { duration: 200 } ) </script> <div transition:fade={transitionOptions}>...</div>
Step 6: Accessibility in Svelte
Svelte's compiler warns about missing accessibility attributes — treat all compiler warnings as errors.
and ARIA: Addrole
when using non-semantic elements. Always pair withrole
oraria-label
.aria-labelledby
: Use for programmatic focus management (e.g., focus trap in modals).bind:this- Keyboard handlers: Any
handler on a non-interactive element needsonclick
/onkeydown
too, or use aonkeyup
.<button> - Screen reader text: Use
(define in app.css) for visually hidden labels.class="sr-only"
<!-- Good: button with accessible label --> <button onclick={closeModal} aria-label="Close dialog" class="icon-btn" > <CloseIcon /> </button> <!-- Good: Svelte dialog with focus trap --> <dialog bind:this={dialogEl} aria-labelledby="dialog-title" aria-modal="true" > <h2 id="dialog-title">{title}</h2> </dialog>
Step 7: Execution steps
- Environment check — If
missing, runnode_modules
.npm install - Data layer — Create
from design content.src/lib/data/mockData.ts - Component drafting — Use
as base. Replace all instances ofresources/component-template.svelte
with the actual component name.StitchComponent - CSS tokens — Add color tokens to
. If usingsrc/app.css
, import its generatedstitch-design-system
instead.design-tokens.css - Wiring — Update
to import and use the new components. Import fromsrc/routes/+page.svelte
.$lib/components/ - Quality check — Run through
.resources/architecture-checklist.md - Dev verification — Run
. Toggle dark mode. Test keyboard navigation.npm run dev
Troubleshooting
| Issue | Fix |
|---|---|
| Runes syntax error | Confirm in . Old syntax is invalid in Svelte 5. |
type error | Add to tag |
| CSS not scoped | Ensure styles are inside block, not in a import |
| Transition not playing | Check isn't causing empty config |
not resolving | Confirm in |
| Dark mode flicker on load | Read theme from in a synchronous script |
Integration with other skills
- stitch-design-system — Run first to generate
for the CSS variable foundation.design-tokens.css - stitch-animate — Run after for Svelte-specific transition patterns beyond the basics above.
- stitch-a11y — Run after for a full accessibility audit when the design has complex UI patterns.
References
— Production-ready Svelte 5 component boilerplateresources/component-template.svelte
— Pre-ship quality checklistresources/architecture-checklist.md
— Reliable GCS HTML downloaderscripts/fetch-stitch.sh