image
![]()
or background-image
```
### Icons (Material → Lucide)
```
search →
arrow_forward →
close →
person →
menu →
settings →
home →
notifications →
add →
check →
edit →
delete →
chevron_right →
favorite →
```
All Lucide icons accept `className` for sizing: `
`
## Mode: Export (Full Code Generation)
Generate from scratch when no implementation exists.
1. Read design tokens: `get_variables` → generate `@theme` block with `--color-*` and `--radius-*` prefixes
2. Read design tree: `batch_get` with sufficient `readDepth`
3. Read reusable components: `batch_get` with `{ reusable: true }` → map to shadcn/ui components
4. Generate code using semantic Tailwind classes, TypeScript, React 19 patterns (no `forwardRef`)
### Theme Generation
```css
@import "tailwindcss";
@theme {
--color-primary: oklch(...); /* from .pen "primary" variable */
--color-background: oklch(...); /* from .pen "background" variable */
--radius-md: 0.375rem; /* from .pen "radius-md" variable */
}
```
Colors MUST use `--color-*` prefix, radii MUST use `--radius-*` prefix — this is how Tailwind v4 auto-generates semantic utilities.
### Component Patterns
- Reusable .pen components with variants → CVA (`class-variance-authority`)
- Class merging → `cn()` from `@/lib/utils`
- Pencil component → shadcn/ui when a match exists (Button, Card, Input, Badge, Avatar, Dialog, Tabs, Table, etc.)
- Custom components when no shadcn/ui match → same CVA + cn() conventions
### Responsive (Multi-Artboard)
When .pen has artboards at multiple widths: generate mobile-first, add `md:`/`lg:` prefixes for larger breakpoints. Never hardcode artboard pixel widths.
## Mode: Sync (Incremental Updates)
Update existing code to match design changes. **The design is the source of truth.**
### Protected Code
These code regions have no design counterpart — never modify them during sync:
- Event handlers, React hooks, state management
- Conditional rendering logic, API calls, navigation
- Animation/transition code not represented in .pen
Only modify: JSX structure, `className` values, text content, asset references.
### Diff Systematically
Compare design and code in this order (most commonly missed first):
1. **Assets** — image format mismatches (`.jpg` vs `.png`), missing files, wrong paths
2. **Design tokens** — new, changed, or removed variables vs CSS custom properties
3. **Screen structure** — layout direction, alignment, gap, padding, typography, colors, icons, children count/order
4. **Cross-screen patterns** — shared components that changed, affecting multiple screens
### Report Before Editing
Output a structured diff report before making any changes:
```
## Design Sync Report
### Token Changes
- Added: --new-variable: #value
- Changed: --existing: #old → #new
### Screen: [Name]
- [file:line] property: old → new
- [file:line] added: new element
```
### Dead Code Cleanup
If the design removed something, the code must too:
- Deleted screens → remove component file + route
- Orphaned components → grep for imports, remove if zero
- Removed variables → remove CSS declaration, grep for `var()` references
- Unused imports → clean up after removing components
## Parallelization
For multi-screen projects, don't process sequentially — fan out after establishing shared context.
### Export: Parallel Code Generation
**Orchestrator setup** (sequential — shared dependencies):
1. Read design tokens (`get_variables`) → generate the `@theme` CSS block
2. Read reusable components (`batch_get` with `{ reusable: true }`) → identify shared component mappings (which Pencil components → which shadcn/ui components)
3. Read all screen frames (top-level `batch_get`)
**Then spawn a teammate per screen.** Each gets:
- The generated `@theme` block
- The component mapping table
- The property mapping reference (from this skill)
- Their specific screen's node tree (read with full depth)
- Target file path
Each teammate generates its screen component independently. The orchestrator reviews outputs and handles cross-screen deduplication (shared components that multiple teammates extracted).
### Sync: Parallel Diff + Apply
**Orchestrator setup** (sequential):
1. Read all design tokens — token changes affect everything
2. Identify which screens changed (or read all if unclear)
3. Read the existing code inventory
**Then spawn a teammate per modified screen.** Each gets:
- The token diff (new/changed/removed variables)
- Their screen's design tree (resolved)
- Their screen's current code file
- The protected code principle
- The property mapping reference
Each teammate produces a diff report and applies changes. The orchestrator consolidates reports and handles dead code cleanup (orphaned files, routes, imports) which requires cross-screen awareness.
### When to Parallelize
- **2+ screens** in export or sync → parallelize
- **Single screen** → not worth the overhead
- **Token-only changes** (no screen structure changes) → single agent, apply to CSS file directly
- **Tightly coupled screens** (shared state, navigation flow) → consider sequential for consistency
## Pencil-Specific Gotchas
- `fill` on text nodes → text color (`text-*`), not background (`bg-*`)
- `textGrowth: "fixed-width"` → set explicit width on the element
- `fill: "$variable"` → `bg-[var(--variable)]` (only when no semantic utility exists)
- `stroke.fill` + `stroke.thickness` → `border-[Npx] border-[var(--color)]`
- Padding arrays: `[T,R,B,L]` — watch the array length (1, 2, or 4 values)
- Image format: design references `.png`, code imports `.jpg` — always verify
- `cornerRadius: [3,24,24,24]` → needs explicit per-corner rounded syntax