pencil-to-code

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Pencil to Code

将Pencil .pen设计导出为代码

Export Pencil .pen designs to production React/Tailwind code.
将Pencil .pen设计导出为可用于生产环境的React/Tailwind代码。

Interface

接口

Input:
  • Frame ID to export (or entire document)
  • Target framework: React (default), Vue, HTML
  • Optional: Component name, output path
Output:
  • React component(s) with Tailwind classes
  • Tailwind theme configuration (from .pen variables)
  • Optional: Screenshot comparison for validation
输入:
  • 要导出的框架ID(或整个文档)
  • 目标框架:React(默认)、Vue、HTML
  • 可选:组件名称、输出路径
输出:
  • 带有Tailwind类的React组件
  • Tailwind主题配置(来自.pen变量)
  • 可选:用于验证的截图对比

Workflow

工作流程

1. Read Design Structure

1. 读取设计结构

javascript
// Get full frame tree
mcp__pencil__batch_get({
  filePath: "<path>.pen",
  nodeIds: ["frameId"],
  readDepth: 10,
  resolveInstances: true,
  resolveVariables: true
})

// Get design variables/theme
mcp__pencil__get_variables({ filePath: "<path>.pen" })
javascript
// Get full frame tree
mcp__pencil__batch_get({
  filePath: "<path>.pen",
  nodeIds: ["frameId"],
  readDepth: 10,
  resolveInstances: true,
  resolveVariables: true
})

// Get design variables/theme
mcp__pencil__get_variables({ filePath: "<path>.pen" })

2. Extract Design Tokens

2. 提取设计令牌

Transform .pen variables → Tailwind theme:
css
/* From .pen variables */
@theme {
  --color-primary: [from variables.colors.primary];
  --color-background: [from variables.colors.background];
  --font-sans: [from variables.fonts.body];
  /* ... */
}
Reference:
references/token-extraction.md
将.pen变量转换为Tailwind主题:
css
/* From .pen variables */
@theme {
  --color-primary: [from variables.colors.primary];
  --color-background: [from variables.colors.background];
  --font-sans: [from variables.fonts.body];
  /* ... */
}
参考:
references/token-extraction.md

3. Map Nodes to Components

3. 将节点映射为组件

.pen Node TypeReact Output
frame
with layout
<div className="flex ...">
frame
with children
Component with children
text
<p>
,
<h1-6>
, or
<span>
ref
(instance)
Reusable component
rectangle
<div>
with fill
ellipse
<div className="rounded-full">
image
<img>
or
fill: url()
Reference:
references/node-mapping.md
.pen节点类型React输出
frame
with layout
<div className="flex ...">
frame
with children
包含子元素的组件
text
<p>
,
<h1-6>
, 或
<span>
ref
(instance)
可复用组件
rectangle
带有填充的
<div>
ellipse
<div className="rounded-full">
image
<img>
fill: url()
参考:
references/node-mapping.md

4. Generate Code

4. 生成代码

Component structure:
tsx
// components/[ComponentName].tsx
import { cn } from "@/lib/utils"

interface [ComponentName]Props {
  className?: string
  // Extracted props from design
}

export function [ComponentName]({ className, ...props }: [ComponentName]Props) {
  return (
    <div className={cn("[tailwind classes]", className)}>
      {/* Nested structure */}
    </div>
  )
}
Tailwind mapping:
.pen property → Tailwind class
--------------------------------
fill: #000     → bg-black
layout: horizontal → flex flex-row
gap: 16        → gap-4
padding: [16,24,16,24] → py-4 px-6
fontSize: 24   → text-2xl
fontWeight: 700 → font-bold
cornerRadius: [8,8,8,8] → rounded-lg
组件结构:
tsx
// components/[ComponentName].tsx
import { cn } from "@/lib/utils"

interface [ComponentName]Props {
  className?: string
  // Extracted props from design
}

export function [ComponentName]({ className, ...props }: [ComponentName]Props) {
  return (
    <div className={cn("[tailwind classes]", className)}>
      {/* Nested structure */}
    </div>
  )
}
Tailwind映射规则:
.pen属性 → Tailwind类
--------------------------------
fill: #000     → bg-black
layout: horizontal → flex flex-row
gap: 16        → gap-4
padding: [16,24,16,24] → py-4 px-6
fontSize: 24   → text-2xl
fontWeight: 700 → font-bold
cornerRadius: [8,8,8,8] → rounded-lg

5. Validate (Optional)

5. 验证(可选)

javascript
// Screenshot the .pen frame
mcp__pencil__get_screenshot({ nodeId: "frameId" })

// Compare visually with rendered React
// (Manual step or browser automation)
javascript
// Screenshot the .pen frame
mcp__pencil__get_screenshot({ nodeId: "frameId" })

// Compare visually with rendered React
// (Manual step or browser automation)

6. Output

6. 输出

markdown
undefined
markdown
undefined

Generated Components

生成的组件

[ComponentName]

[ComponentName]

  • File:
    components/[ComponentName].tsx
  • Props: [list extracted props]
  • 文件:
    components/[ComponentName].tsx
  • 属性:[提取的属性列表]

Theme Configuration

主题配置

  • File:
    app/globals.css
    (additions)
  • 文件:
    app/globals.css
    (新增内容)

Verification

验证

Screenshot comparison: [attached]
undefined
截图对比:[已附加]
undefined

Translation Rules

转换规则

Layout System

布局系统

.pen                          Tailwind
--------------------------------------
layout: "vertical"         → flex flex-col
layout: "horizontal"       → flex flex-row
layout: "grid"             → grid
alignItems: "center"       → items-center
justifyContent: "center"   → justify-center
gap: 8                     → gap-2
gap: 16                    → gap-4
gap: 24                    → gap-6
width: "fill_container"    → w-full
height: "fill_container"   → h-full
.pen                          Tailwind
--------------------------------------
layout: "vertical"         → flex flex-col
layout: "horizontal"       → flex flex-row
layout: "grid"             → grid
alignItems: "center"       → items-center
justifyContent: "center"   → justify-center
gap: 8                     → gap-2
gap: 16                    → gap-4
gap: 24                    → gap-6
width: "fill_container"    → w-full
height: "fill_container"   → h-full

Spacing (8-point grid)

间距(8点网格系统)

.pen padding                  Tailwind
----------------------------------------
[8,8,8,8]                  → p-2
[16,16,16,16]              → p-4
[16,24,16,24]              → py-4 px-6
[24,32,24,32]              → py-6 px-8
.pen padding                  Tailwind
----------------------------------------
[8,8,8,8]                  → p-2
[16,16,16,16]              → p-4
[16,24,16,24]              → py-4 px-6
[24,32,24,32]              → py-6 px-8

Typography

排版

.pen                          Tailwind
----------------------------------------
fontSize: 12               → text-xs
fontSize: 14               → text-sm
fontSize: 16               → text-base
fontSize: 20               → text-xl
fontSize: 24               → text-2xl
fontSize: 32               → text-3xl
fontSize: 48               → text-5xl
fontWeight: 400            → font-normal
fontWeight: 500            → font-medium
fontWeight: 600            → font-semibold
fontWeight: 700            → font-bold
.pen                          Tailwind
----------------------------------------
fontSize: 12               → text-xs
fontSize: 14               → text-sm
fontSize: 16               → text-base
fontSize: 20               → text-xl
fontSize: 24               → text-2xl
fontSize: 32               → text-3xl
fontSize: 48               → text-5xl
fontWeight: 400            → font-normal
fontWeight: 500            → font-medium
fontWeight: 600            → font-semibold
fontWeight: 700            → font-bold

Colors

颜色

.pen                          Tailwind
----------------------------------------
fill: "#FFFFFF"            → bg-white
fill: "#000000"            → bg-black
fill: variable             → bg-[var(--color-name)]
textColor: "#6B7280"       → text-gray-500
stroke: "#E5E5E5"          → border-gray-200
.pen                          Tailwind
----------------------------------------
fill: "#FFFFFF"            → bg-white
fill: "#000000"            → bg-black
fill: variable             → bg-[var(--color-name)]
textColor: "#6B7280"       → text-gray-500
stroke: "#E5E5E5"          → border-gray-200

Border Radius

边框圆角

.pen cornerRadius             Tailwind
----------------------------------------
[0,0,0,0]                  → rounded-none
[4,4,4,4]                  → rounded
[8,8,8,8]                  → rounded-lg
[16,16,16,16]              → rounded-2xl
[9999,9999,9999,9999]      → rounded-full
.pen cornerRadius             Tailwind
----------------------------------------
[0,0,0,0]                  → rounded-none
[4,4,4,4]                  → rounded
[8,8,8,8]                  → rounded-lg
[16,16,16,16]              → rounded-2xl
[9999,9999,9999,9999]      → rounded-full

Constraints

约束条件

  • Single concern: Export → code. No design modifications.
  • Tailwind 4 @theme: CSS-first token system
  • React + TypeScript: Default output target
  • Semantic HTML: Choose appropriate elements
  • Accessibility: Include aria attributes where detectable
  • 单一职责:仅负责导出为代码,不修改设计。
  • Tailwind 4 @theme:基于CSS的令牌系统
  • React + TypeScript:默认输出目标
  • 语义化HTML:选择合适的HTML元素
  • 可访问性:在可检测到的情况下包含aria属性

References

参考资料

  • references/node-mapping.md
    — Complete node → component mapping
  • references/token-extraction.md
    — Variable → theme extraction
  • design-tokens/
    — Token system conventions
  • references/node-mapping.md
    — 完整的节点→组件映射规则
  • references/token-extraction.md
    — 变量→主题提取规则
  • design-tokens/
    — 令牌系统约定

Integration

集成

Called by:
  • design-exploration
    orchestrator (after direction selection)
  • Direct user invocation
Composes:
  • design-tokens
    (for theme structure)
调用方:
  • design-exploration
    编排器(在选择方向后)
  • 用户直接调用
组合依赖:
  • design-tokens
    (用于主题结构)