--- name: design-to-code license: MIT compatibility: "Claude Code 2.1.148+. Optional: stitch (official Google Stitch), 21st-dev-magic, storybook-mcp (@storybook/addon-mcp) MCP servers." description: "Mockup-to-component pipeline using Google Stitch, 21st.dev, and Storybook MCP. Accepts screenshots, descriptions, or URLs as input and produces production-ready React components. Checks existing Storybook components before generating, orchestrates design extraction via Stitch MCP, component matching via 21st.dev registry, adaptation to project design tokens, and self-healing verification via run-story-tests. Use when converting visual designs to code, implementing UI from mockups, or building components from screenshots." argument-hint: "[screenshot-path | description | url]" tags: [design-to-code, stitch, 21st-dev, ui-generation, mockup, component, react, frontend] context: fork version: 1.0.1 author: OrchestKit user-invocable: true complexity: complex persuasion-type: collaborative effort: high model: sonnet allowed-tools: - Read - Write - Edit - Glob - Grep - Bash - WebFetch - WebSearch - AskUserQuestion - Agent - TaskCreate - TaskUpdate - TaskList skills: - design-system-tokens - component-search - storybook-mcp-integration - design-context-extract - remember - memory metadata: category: workflow-automation mcp-server: stitch, 21st-dev-magic, storybook-mcp triggers: keywords: ["design to code", "mockup to code", "screenshot to component", "convert design", "implement ui from", "build from mockup"] examples: - "convert this screenshot into a React component" - "implement the UI from this Figma mockup" - "build a component from this design" anti-triggers: [explore, assess, review, brainstorm, extract design] paths: - "src/components/**/*.{tsx,css}" - "**/*design-tokens*" - ".storybook/**" --- # Design to Code Convert visual designs into production-ready React components using a four-stage pipeline: Extract, Match, Adapt, Render. ```bash /ork:design-to-code screenshot of hero section # From description /ork:design-to-code /tmp/mockup.png # From screenshot /ork:design-to-code https://example.com/pricing # From URL ``` ## Pipeline Overview ``` Input (screenshot/description/URL) │ ▼ ┌─────────────────────────┐ │ Stage 1: EXTRACT │ Stitch MCP → HTML + design context │ build_site │ Generate up to 5 screens from prompt │ get_screen_code / _image │ Extract React/HTML + PNG for each └─────────┬───────────────┘ │ ▼ ┌─────────────────────────┐ │ Stage 2: MATCH │ 1. Storybook MCP → check existing │ Storybook-first lookup │ 2. 21st.dev → search public registry │ Then 21st.dev fallback │ 3. Filesystem → grep codebase └─────────┬───────────────┘ │ ▼ ┌─────────────────────────┐ │ Stage 3: ADAPT │ Merge extracted design + matched │ Apply project tokens │ components into final implementation │ Customize to codebase │ Tests + types included └─────────┬───────────────┘ │ ▼ ┌─────────────────────────┐ │ Stage 4: RENDER │ Register as json-render catalog entry │ Generate Zod schema │ Same component → PDF, email, video │ Add to defineCatalog() │ Multi-surface reuse via MCP output └─────────┬───────────────┘ │ ▼ ┌─────────────────────────┐ │ Stage 4b: VERIFY │ Storybook MCP → self-healing loop │ run-story-tests(a11y) │ Fix violations, retry (max 3) │ preview-stories │ Embed live preview in chat └─────────────────────────┘ ``` ## Argument Resolution ```python INPUT = "" # Full argument string # Detect input type: # - Starts with "/" or "~" or contains ".png"/".jpg" → screenshot file path # - Starts with "http" → URL to screenshot or live page # - Otherwise → natural language description ``` ## Step 0: Detect Input Type and Project Context ```python # 1. Create main task IMMEDIATELY TaskCreate(subject="Design to code: {INPUT}", description="Four-stage pipeline: extract, match, adapt, render", activeForm="Converting design to code") # 2. Create subtasks for each stage TaskCreate(subject="Extract design context", activeForm="Extracting design context") # id=2 TaskCreate(subject="Match components (Storybook-first)", activeForm="Matching components") # id=3 TaskCreate(subject="Adapt to project tokens and conventions", activeForm="Adapting to project") # id=4 TaskCreate(subject="Register in json-render catalog", activeForm="Registering in catalog") # id=5 TaskCreate(subject="Verify with Storybook self-healing", activeForm="Verifying component") # id=6 # 3. Set dependencies for sequential stages TaskUpdate(taskId="3", addBlockedBy=["2"]) # Match needs extracted design context TaskUpdate(taskId="4", addBlockedBy=["3"]) # Adapt needs matched components TaskUpdate(taskId="5", addBlockedBy=["4"]) # Render needs adapted component TaskUpdate(taskId="6", addBlockedBy=["5"]) # Verify needs rendered component # 4. Before starting each task, verify it's unblocked task = TaskGet(taskId="2") # Verify blockedBy is empty # 5. Update status as you progress TaskUpdate(taskId="2", status="in_progress") # When starting TaskUpdate(taskId="2", status="completed") # When done — repeat for each subtask # Detect project's design system Glob("**/tailwind.config.*") Glob("**/tokens.css") Glob("**/.tokens.json") # Read existing tokens if found → used in Stage 3 # Detect shadcn/ui style (v4 style system) Glob("**/components.json") # Read → style field (e.g., "radix-luma", "base-nova") # Determines class names: Luma=rounded-4xl, Nova=compact, Lyra=sharp # Store: SHADCN_STYLE for Stage 2 filtering + Stage 3 adaptation ``` ## Stage 1: Extract Design Context **If stitch MCP is available:** ```python # Official Stitch MCP tools (stitch.withgoogle.com/docs/mcp): # - build_site(prompt) → multi-screen app, up to 5 interconnected screens # - get_screen_code(screenId) → returns React/HTML for a generated screen # - get_screen_image(screenId) → returns PNG of a generated screen # # For screenshot/URL input: # 1. Upload screenshot to Stitch (or pass URL) # 2. Call build_site() with the visual as context # 3. get_screen_code() to retrieve the React/HTML output # # For description input: # 1. Call build_site(prompt=) # 2. get_screen_code() / get_screen_image() to retrieve the result # # DESIGN.md import (Stitch Pro, Mar 2026+): # Stitch can also import a natural-language DESIGN.md file to regenerate # a layout without starting from scratch. Useful for iterative edits. ``` **If stitch MCP is NOT available (fallback):** ```python # For screenshot: Read the image file directly (Claude is multimodal) # Analyze layout, colors, typography, spacing from the image # For URL: WebFetch the page, extract HTML structure # For description: Skip extraction, proceed to Stage 2 with description ``` > **Resolution budget (Opus 4.8 / CC 2.1.111+):** Mockups up to **2,576 px on the long edge** (~3.75 MP, 3× prior ceiling) produce better component boundaries and spacing extraction. Full-page desktop mockups at native resolution are now in-budget; previously they had to be resized down and lost fine detail. Only downscale inputs exceeding 2,576 px. Extract and produce: - Color palette (hex/oklch values) - Typography (font families, sizes, weights) - Spacing patterns (padding, margins, gaps) - Component structure (headers, cards, buttons, etc.) - Layout pattern (grid, flex, sidebar, etc.) ## Stage 2: Match Components (Storybook-First) **Priority 1 — Check project's own Storybook (if storybook-mcp available):** ```python # Search the project's existing component library first inventory = list-all-documentation() # Full component + docs manifest for component in inventory.components: if component matches extracted_description: details = get-documentation(id=component.id) # Returns: props schema, stories, usage patterns # → Existing component found — skip external search ``` **Priority 2 — Search 21st.dev (if no Storybook match and 21st-dev-magic available):** ```python # Search 21st.dev for matching components # Use the component descriptions from Stage 1 # Example: "animated pricing table with toggle" # Filter: React, Tailwind CSS, shadcn/ui compatible # If SHADCN_STYLE detected, prefer components matching style's visual language # (e.g., Luma → rounded/pill-shaped, Nova → compact/dense, Lyra → sharp/boxy) ``` **Priority 3 — Filesystem fallback (if no MCP servers available):** ```python # Search for components in the project's existing codebase Grep(pattern="export.*function|export.*const", glob="**/*.tsx") # Check for shadcn/ui components Glob("**/components/ui/*.tsx") # Generate from scratch if no matches found ``` Present matches to user: ```python AskUserQuestion(questions=[{ "question": "Which component approach for {component_name}?", "header": "Component", "options": [ {"label": "Reuse from Storybook", "description": "{existing_component} — props: {prop_list}"}, {"label": "Use 21st.dev match", "description": "{matched_component_name} — {match_score}% match"}, {"label": "Adapt from codebase", "description": "Modify existing {existing_component}"}, {"label": "Generate from scratch", "description": "Build new component from extracted design"} ], "multiSelect": false }]) ``` ## Stage 3: Adapt to Project Merge the extracted design context with matched/generated components: 1. **Apply project tokens** — Replace hardcoded colors/spacing with project's design tokens 2. **Apply shadcn style classes** — If `SHADCN_STYLE` detected, use style-correct class names: - Luma: `rounded-4xl` buttons/cards, `shadow-md` + `ring-1 ring-foreground/5`, `gap-6 py-6` - Nova: compact `px-2 py-1`, reduced margins, tight spacing - Lyra: `rounded-none`, sharp edges, monospace-friendly - Mira: ultra-dense, minimal padding 3. **Match naming conventions** — Follow project's component naming patterns 4. **Add TypeScript types** — Full type safety with Zod validation for any data props 5. **Include tests** — MSW handlers for API-backed components, render tests for static 6. **Responsive** — Mobile-first with breakpoints matching project's system ### Output Structure ``` src/components/ └── {ComponentName}/ ├── {ComponentName}.tsx # Main component ├── {ComponentName}.test.tsx # Tests └── index.ts # Barrel export ``` ## Stage 4: Register in json-render Catalog After ADAPT produces a working React component, register it as a json-render catalog entry for multi-surface reuse. 1. **Generate Zod schema** — Derive a Zod schema from the component's TypeScript props 2. **Add catalog entry** — Register in the project's `defineCatalog()` call with props schema and children declaration 3. **Verify rendering** — Confirm the component renders correctly through `` path ```typescript import { z } from 'zod' // Zod schema derived from {ComponentName}Props const componentSchema = z.object({ title: z.string().max(100), variant: z.enum(['default', 'featured']).default('default'), // ... props from the adapted component }) // Add to project catalog import { defineCatalog, mergeCatalogs } from '@json-render/core' import { existingCatalog } from './catalog' export const catalog = mergeCatalogs(existingCatalog, { {ComponentName}: { props: componentSchema, children: true, // or false for leaf components }, }) ``` **Enables:** same component output to PDF, email, video, or MCP response — no reimplementation needed. **Skip condition:** If the project has no json-render dependency or catalog, inform the user and skip catalog registration. The component from Stage 3 is still fully usable standalone. ### Stage 4b: Self-Healing Verification (if storybook-mcp available) After generating the component, verify it with Storybook MCP: ```python # 1. Write CSF3 story for the new component Write("src/components/{Name}/{Name}.stories.tsx", story_code) # 2. Run tests via MCP (component + a11y) results = run-story-tests( stories=[{ "storyId": "{name}--default" }], a11y=True ) # 3. Handle failures — self-heal up to 3 attempts if not results.all_passed: for failure in results.failures: # Read violation details, fix the component Edit("src/components/{Name}/{Name}.tsx", fix) # Re-run failing tests results = run-story-tests(stories=[...], a11y=True) # 4. Preview — embed live story in chat for user confirmation previews = preview-stories(stories=[ { "absoluteStoryPath": "src/components/{Name}/{Name}.stories.tsx", "exportName": "Default" } ]) # Include preview URLs in response for visual confirmation ``` **Skip condition:** If storybook-mcp is not available, skip verification. The component is still usable — just not auto-verified. ## Graceful Degradation | stitch | 21st-dev-magic | storybook-mcp | Behavior | |--------|----------------|---------------|----------| | Available | Available | Available | Full pipeline: extract + Storybook-first match + adapt + render + self-heal verify | | Available | Available | Unavailable | Extract + 21st.dev match + adapt + render (no verification) | | Available | Unavailable | Available | Extract + Storybook match + adapt + verify | | Unavailable | Available | Available | Description-based search + Storybook check + adapt + verify | | Unavailable | Unavailable | Available | Filesystem search + Storybook verify only | | Unavailable | Unavailable | Unavailable | Manual analysis + generate from scratch (still works) | The skill ALWAYS produces output regardless of MCP availability. Storybook MCP adds component reuse (Stage 2) and self-healing verification (Stage 4b) — skipping them still yields a working component. ## Anti-Patterns - **NEVER** output components with hardcoded colors — use design tokens - **NEVER** skip TypeScript types — all props must be typed - **NEVER** generate without checking existing project patterns first - **NEVER** ignore the project's existing component library structure ## Related Skills - `storybook-mcp-integration` — Storybook MCP tools: component discovery, testing, previews - `component-search` — Search 21st.dev registry standalone - `design-context-extract` — Extract design DNA from screenshots - `design-system-tokens` — Token architecture and management - `storybook-testing` — CSF3 patterns, Vitest integration, Chromatic TurboSnap - `json-render-catalog` — Catalog definition, Zod schemas, defineCatalog patterns - `multi-surface-render` — Render catalog entries to PDF, email, video, MCP