mcpField
D
design-to-code

design-to-code

github.com/yonatangross设计与 UI300109 次安装今天更新
代码仓库

关于 design-to-code

design-to-code 通过四阶段流水线,将截图、URL 或文字描述转为 React 组件。它会先检查现有组件和项目规范;具备依赖时,还可将输出注册到 json-render 目录。

主要功能

  1. 01从输入中提取设计细节
  2. 02优先匹配现有组件
  3. 03适配项目令牌与规范
  4. 04生成带类型的 React 组件和测试
  5. 05将组件注册到 json-render 目录
  6. 06通过 Storybook MCP 验证组件

适用场景

  1. 01将截图转换为 React 组件
  2. 02根据网页 URL 构建组件
  3. 03复用项目或 Storybook 组件
  4. 04准备组件以供多界面渲染

MCP 相关

该技能可使用 Stitch MCP 提取屏幕细节,并通过 Storybook MCP 查找和测试组件。它会检测 MCP 工具是否可用;不可用时可改用文件系统搜索或手动分析继续执行。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yonatangross/orchestkit --skill design-to-code

安装后在 Claude Code 中输入/design-to-code确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

test-cases.json
rules/
_sections.md
catalog-registration.md

详细介绍

设计转代码

使用四阶段流水线将视觉设计转换为可用于生产环境的 React 组件:提取、匹配、适配、渲染。

design-to-code screenshot of hero section    # From description
design-to-code /tmp/mockup.png               # From screenshot
design-to-code https://example.com/pricing    # From URL

流水线概览

Input (screenshot/description/URL)
  │
  ▼
┌─────────────────────────┐
│ Stage 1: EXTRACT         │  Stitch MCP → screen details + URLs
│ generate_screen_from_text│  Create screens from a text prompt
│ get_screen               │  Screen details with download URLs
└─────────┬───────────────┘
          │
          ▼
┌─────────────────────────┐
│ 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
└─────────────────────────┘

参数解析

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

步骤 0:检测输入类型和项目上下文

# 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. 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
Grep("@theme", glob="**/*.css")   # Tailwind v4: theme lives in CSS, not a config file
Glob("**/tailwind.config.*")      # Tailwind v3 only (v4 ignores this file)
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

阶段 1:提取设计上下文

如果 stitch MCP 可用:

# Live Stitch MCP tools (https://stitch.googleapis.com/mcp), matching
# design-context-extractor / design-system-architect agent grants:
#   - list_projects() / get_project(projectId)
#   - list_screens(projectId)
#   - get_screen(name="projects/{projectId}/screens/{screenId}")
#       ONE required param: name. Returns screen details including
#       download URLs (fetch those URLs; no separate code/image export tool)
#   - generate_screen_from_text(projectId, prompt)
#       quota-costing write; can take a few minutes. DO NOT RETRY.
#       On timeout: poll get_screen(name=...) every 30 s, up to 10 times.
#
# For screenshot/URL input:
#   1. list_projects / get_project to locate the Stitch project
#   2. generate_screen_from_text with the extraction goal (or use an
#      existing screen if the project already has one). Never retry.
#   3. list_screens, then get_screen(name="projects/{projectId}/screens/{screenId}")
#   4. Fetch the download URLs (or Read multimodal) for token extraction
#
# For description input:
#   1. generate_screen_from_text(projectId, prompt=<description>) once
#   2. On timeout, poll get_screen(name=...) every 30 s up to 10 times
#   3. Otherwise get_screen(name="projects/{projectId}/screens/{screenId}")
#
# DESIGN.md import (Stitch Pro, Mar 2026+):
#   Prefer upload_design_md / create_design_system_from_design_md when
#   those tools are available on the live server; otherwise regenerate
#   via generate_screen_from_text from the DESIGN.md contents (once, no retry).

如果 stitch MCP 不可用(回退方案):

# 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

分辨率预算(Opus 5.5 / CC 2.1.111+): 长边不超过 2,576 px(约 3.75 MP,是之前上限的 3 倍)的模型图可更好地提取组件边界和间距。现在,原生分辨率的整页桌面模型图也在预算范围内;以前必须缩小尺寸,导致精细细节丢失。仅缩小超过 2,576 px 的输入图像。

提取并生成:

  • 调色板(hex/oklch 值)
  • 字体排版(字体系列、字号、字重)
  • 间距模式(内边距、外边距、间隙)
  • 组件结构(页眉、卡片、按钮等)
  • 布局模式(grid、flex、侧边栏等)

阶段 2:匹配组件(优先使用 Storybook)

优先级 1 — 检查项目自己的 Storybook(如果 storybook-mcp 可用):

# 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

优先级 2 — 搜索 21st.dev(如果未匹配到 Storybook 且 21st-dev-magic 可用):

# 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)

优先级 3 — 文件系统回退方案(如果没有 MCP 服务可用):

# 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

向用户展示匹配结果:

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
}])

阶段 3:适配项目

将提取的设计上下文与匹配或生成的组件合并:

  1. 应用项目 Token — 将硬编码的颜色和间距替换为项目的设计 Token
  2. 应用 shadcn 样式类 — 如果检测到 SHADCN_STYLE,使用符合样式的类名:
    • Luma:按钮和卡片使用 rounded-4xl、shadow-md + ring-1 ring-foreground/5、gap-6 py-6
    • Nova:紧凑的 px-2 py-1、缩小外边距、紧凑间距
    • Lyra:rounded-none、锐利边缘、适合等宽字体
    • Mira:超紧凑、最小内边距
  3. 遵循命名约定 — 遵循项目的组件命名模式
  4. 添加 TypeScript 类型 — 提供完整类型安全,并使用 Zod 验证任何数据属性
  5. 包含测试 — 对由 API 支持的组件使用 MSW 处理程序,对静态组件进行渲染测试
  6. 响应式 — 采用移动优先设计,断点与项目系统保持一致
输出结构
src/components/
  └── {ComponentName}/
      ├── {ComponentName}.tsx       # Main component
      ├── {ComponentName}.test.tsx  # Tests
      └── index.ts                 # Barrel export

阶段 4:注册到 json-render 目录

ADAPT 生成可用的 React 组件后,将其注册为 json-render 目录条目,以便在多个界面中复用。

  1. 生成 Zod schema — 根据组件的 TypeScript 属性推导 Zod schema
  2. 添加目录条目 — 在项目的 defineCatalog() 调用中注册,并提供属性 schema 和子项声明
  3. 验证渲染 — 确认组件可通过 <Render catalog={catalog} /> 路径正确渲染
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 } from '@json-render/core'
import { existingCatalog } from './catalog'

export const catalog = {
  ...existingCatalog,
  {ComponentName}: {
    props: componentSchema,
    children: true, // or false for leaf components
  },
}

支持: 将同一组件输出用于 PDF、电子邮件、视频或 MCP 响应,无需重新实现。

跳过条件: 如果项目没有 json-render 依赖或目录,请告知用户并跳过目录注册。阶段 3 生成的组件仍可独立使用。

阶段 4b:自修复验证(如果 storybook-mcp 可用)

生成组件后,使用 Storybook MCP 对其进行验证:

# 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

跳过条件: 如果 storybook-mcp 不可用,则跳过验证。组件仍可使用,只是不会自动验证。

优雅降级

stitch21st-dev-magicstorybook-mcp行为
可用可用可用完整流程:提取 + 优先匹配 Storybook + 适配 + 渲染 + 自愈验证
可用可用不可用提取 + 匹配 21st.dev + 适配 + 渲染(不进行验证)
可用不可用可用提取 + 匹配 Storybook + 适配 + 验证
不可用可用可用基于描述搜索 + 检查 Storybook + 适配 + 验证
不可用不可用可用仅进行文件系统搜索 + Storybook 验证
不可用不可用不可用手动分析 + 从头生成(仍可正常工作)

无论 MCP 是否可用,此技能总会生成输出。Storybook MCP 可实现组件复用(阶段 2)和自愈验证(阶段 4b)——即使跳过这些步骤,仍能得到可用的组件。

反模式

  • 绝不输出带有硬编码颜色的组件——请使用设计令牌
  • 绝不跳过 TypeScript 类型——所有属性都必须有类型
  • 绝不在检查现有项目模式前就开始生成
  • 绝不忽视项目现有的组件库结构

质量标准

满足以下所有条件才算完成:

  • 生成的组件不包含硬编码颜色或字面量间距——每个视觉值都通过项目设计令牌解析。
  • 每个属性都有 TypeScript 类型;承载数据的属性还需进行 Zod 验证。
  • 阶段 2 在从头生成前检查了现有组件(先查 Storybook,再查 21st.dev,最后查文件系统),并注明了所选匹配来源。
  • storybook-mcp 可用时,组件在交付前通过 run-story-tests(组件 + 无障碍)测试,并在最多 3 次尝试内完成自愈。
  • 输出遵循 {ComponentName}/ 结构——包含组件、测试和 barrel 导出。
  • 仅当依赖项缺失时才跳过各阶段(json-render catalog、Storybook 验证),并说明跳过原因。

相关技能

  • storybook-mcp-integration — Storybook MCP 工具:组件发现、测试、预览
  • component-search — 独立搜索 21st.dev 注册表
  • design-context-extract — 从截图中提取设计 DNA
  • design-stylecards — 用于生成组件润色阶段的命名美学配方(阴影堆栈、玻璃表面、渐变、字体比例)
  • design-system-tokens — 令牌架构与管理
  • storybook-testing — CSF3 模式、Vitest 集成、Chromatic TurboSnap
  • json-render-catalog — 目录定义、Zod 模式、defineCatalog 模式
  • multi-surface-render — 将目录条目渲染为 PDF、电子邮件、视频、MCP

评论

支持 Markdown