| name | figma-to-code |
| description | Implements Figma designs to exact 1:1 fidelity by decomposing them into sub-components and building bottom-up with self-correcting validation loops. This skill should be used when implementing UI from Figma files, when a Figma URL is provided, or when the user mentions "implement design", "figma to code", "build from figma", "convert figma", "break down this design", "implement page", "implement component", "generate code", "build Figma design", or "pixel perfect". Works for both full pages and single components. Requires Figma MCP server connection. Do not use for non-Figma design tasks or when the user only wants a screenshot or metadata without implementation.
|
| metadata | {"mcp-server":"figma"} |
Figma to Code
Implement Figma designs to exact 1:1 visual fidelity through decomposition,
bottom-up implementation, and self-correcting validation loops.
Prerequisites
Before starting, verify the Figma MCP server is connected by checking that
tools like get_design_context are available. If not, guide the user to
enable the Figma MCP server and restart their MCP client.
Call whoami() once at the start to determine the user's plan tier:
- Starter / View / Collab seats: 6 tool calls/month — switch to
ultra-conservative mode (see
references/edge-cases.md Rate Limit Management).
- Dev / Full seat on Professional+: per-minute limits — use the standard workflow.
If the project has design system rules (generated by create_design_system_rules
or manually defined in CLAUDE.md / project config), load and respect them
throughout implementation.
Browser Validation (Playwright MCP)
Playwright MCP is the primary method for 1:1 fidelity. It connects to the
user's existing browser — same tabs, auth, cookies. If unavailable, fall back
to value-based correction only and recommend npx figma-to-code-skill setup-browser.
Tab rules: Use browser_tabs to find the frontend tab by matching
localhost URL/port. Navigate it freely. Do NOT touch non-frontend tabs.
Open a new tab if no matching localhost tab exists.
Gitignore: Add .playwright-mcp/ to the project's .gitignore if not already present.
Screenshot preconditions: Before taking comparison screenshots, ensure
deterministic rendering: set viewport to a fixed size (e.g. 1280x800),
use element-level capture (bounding box) when comparing individual components.
Workflow
Simple component (single node, few children)
If the Figma URL points to a single component or simple element:
- Call
get_design_context(fileKey, nodeId) — returns code AND screenshot (1 MCP call).
- Implement, adapting to project framework and conventions.
- Run the correction loop (Step 4c below). Fix until 1:1 match.
- Report (Step 6).
Skip Steps 2–3 and 5 — they are for complex multi-component designs only.
Step 1 — Parse the Figma URL
Extract fileKey and nodeId:
figma.com/design/:fileKey/:fileName?node-id=X-Y → nodeId = X:Y
- Branch:
figma.com/design/:fileKey/branch/:branchKey/:fileName → use branchKey
- Make:
figma.com/make/:makeFileKey/:makeFileName → use makeFileKey
- FigJam:
figma.com/board/:fileKey/:fileName → use get_figjam instead of
get_design_context. FigJam boards are diagrams, not implementable designs —
extract information and present it to the user rather than attempting code generation.
IMPORTANT — nodeId format: URLs use hyphens (node-id=1-2) but all MCP tools
expect colons (nodeId="1:2"). Always convert - → : before passing to any tool.
Step 2 — Fetch structure, tokens, and screenshot
Call all 3 in parallel:
get_metadata(fileKey, nodeId) → node tree
get_variable_defs(fileKey, nodeId) → design tokens (ONE-TIME, never again)
get_screenshot(fileKey, nodeId) → full-page visual reference
Record node IDs, layer names, and token mappings for later steps.
Use get_metadata + get_screenshot here because get_design_context on a
complex page root will truncate.
Step 3 — Build the implementation plan
3a. Pre-check Code Connect mappings: Call get_code_connect_map(fileKey, nodeId)
to retrieve existing Code Connect mappings for this design. Any node with a mapping
is automatically classified as "code-connected" — no get_design_context needed.
3b. Scan the project for existing components that match Figma nodes by name
or structure. Search in common locations:
src/components/, app/components/, lib/ui/, components/
- Project-specific paths from design system rules or CLAUDE.md
- Match by component name, variant props, and structural similarity
3c. Classify — Group nodes: atoms → compounds → sections → layout. Assign each:
- implement → needs
get_design_context (1 MCP call)
- code-connected → has Code Connect mapping from 3a — use that component directly (0 calls)
- reuse → matches existing project component from 3b (0 calls)
- layout-only → pure container from metadata (0 calls)
Component variant sets: If a node is a component set with variants
(e.g., size=sm/md/lg, state=default/hover/disabled), plan to fetch
get_design_context on the parent set, implement the base variant first,
then add variant props. Count as 1 MCP call, not 1 per variant.
Present the plan with MCP call estimates. Wait for user confirmation.
Step 4 — Implement each component (bottom-up)
Process atoms first, then compounds, then sections. Batch siblings in parallel.
4a. Call get_design_context(fileKey, childNodeId) — returns code AND
screenshot. Do NOT call get_screenshot or get_variable_defs again.
If the call fails, retry once. If it fails again, fall back to get_metadata
get_screenshot for that node and implement from visual reference.
4b. Implement:
- Code Connect: If
get_design_context returned a Code Connect snippet or
component documentation link, use the mapped codebase component directly.
Follow any linked documentation for usage context and prop mapping.
- Design annotations: If the response includes designer annotations (notes,
constraints, instructions), follow them — they represent explicit design intent.
- Complex designs: Use static/mock data matching the Figma visuals.
Simple components in existing codebases: Use real project patterns directly.
- Assets: Use
localhost URLs for assets directly. Do NOT import icon packages.
Save downloaded assets to the project's asset directory (e.g., public/assets/,
src/assets/). Assets are served through the Figma MCP server's built-in endpoint.
- Treat MCP output as reference — adapt to project framework and conventions.
- Map Figma variables to project tokens. Prefer project tokens on conflict.
- Dark mode / themes: If
get_variable_defs returned multiple token modes
(light/dark), implement theme switching using project conventions (CSS variables,
theme context, etc.) rather than hardcoding one mode.
- Reuse existing components — extend, don't duplicate. Keep composable.
- Follow project naming and directory conventions. Avoid inline styles.
- New components: Add TypeScript types for component props. Keep components
composable with a
className or style prop for composition.
- Absolute positioning: When Figma uses absolute positioning for overlapping
elements, prefer CSS Grid/Flexbox to reproduce the visual result. Only use
position: absolute when overlap is intentional (badges, overlays, decorative).
- Implement interactive states: hover, active, focus, disabled.
- Animation hints: If
get_design_context returns prototype connections or
interaction data, note them as implementation hints for CSS transitions/animations.
4c. Correction loop (MANDATORY):
REPEAT (up to 3x):
1. Cross-reference EVERY value against Figma data from 4a:
Layout | Typography | Colors | Effects | States | Accessibility (WCAG AA)
2. List discrepancies: "padding-left is 16px, Figma specifies 24px"
3. Fix ALL → repeat. Zero discrepancies → visual validation.
AFTER 3 ROUNDS: If discrepancies remain, STOP. Report unresolved diffs
to the user and ask how to proceed. Do NOT silently continue.
Visual validation (Playwright MCP) — max 2 screenshot rounds:
1. Find frontend tab by localhost URL/port (or open new) → navigate to component
2. browser_snapshot first (text, cheap) — verify structure, element
presence, hierarchy. Fix any structural issues before screenshotting.
3. Set viewport to fixed size. browser_take_screenshot (element-level
bounding box when possible, not full page)
→ compare against Figma screenshot from 4a
4. If mismatches → fix → ONE more screenshot round max
Component PASSES when browser screenshot matches Figma screenshot.
Do NOT proceed until component passes both value check AND visual match.
Do NOT screenshot every iteration of the value loop — only after it passes.
Reuse items: Compare existing component against Figma screenshot. If
mismatch, fetch get_design_context (1 call), modify, run correction loop.
Layout-only items: Use metadata + full-page screenshot. If layout doesn't
match after assembly, promote to "implement" and fetch design context.
Step 5 — Assemble the full page
Compose from implemented components. No MCP calls — use metadata + screenshot.
Assembly correction loop (MANDATORY):
REPEAT (up to 3x):
1. Check: section spacing, page background, alignment, component sizing,
scroll behavior, responsive constraints
2. Fix discrepancies. If component wrong in context → fetch
get_design_context for that node (1 targeted call)
3. Visual: browser_snapshot first (cheap) → then ONE full-page screenshot
to compare against Figma screenshot from Step 2 → fix → ONE more max
AFTER 3 ROUNDS: If discrepancies remain, STOP. Report unresolved diffs
to the user with specific details. Do NOT silently continue.
Step 6 — Report
Implementation Complete
- MCP calls used: X (of Y estimated)
- Components: created [paths], reused [paths], code-connected [names]
- Deviations: [with reasons, documented as code comments]
Next steps (if static data was used):
- [ ] Replace mock data with real data sources
- [ ] Wire up APIs, auth, state management
Post-implementation offers (ask user, don't auto-run):
- Code Connect: For newly created components, offer to map them to Figma via
add_code_connect_map so future implementations of the same design skip the
implement step. Only available on Organization/Enterprise plans.
- Design system rules: If no project rules exist, suggest running
create_design_system_rules to generate project-specific conventions.
MCP Efficiency
These rules reduce MCP calls by ~65% and minimize screenshot token cost:
| Rule | Saves |
|---|
get_design_context includes screenshot — skip get_screenshot per component | 1 call/component |
get_variable_defs once on root — skip per component | 1 call/component |
Batch sibling get_design_context in parallel | Faster execution |
| Skip MCP for "reuse" and "layout-only" items | 1 call/skip |
get_metadata for page root — skip get_design_context | Avoids truncation |
Simple component fast path — 1 get_design_context call total | Skips 2 root calls |
| Code Connect components — use mapped codebase component directly | 1 call/component |
| Component variant sets — fetch parent once, not each variant | N-1 calls/set |
get_code_connect_map in planning — skip implement for mapped nodes | 1 call/mapped node |
whoami once at start — skip if plan tier already known | Informs rate strategy |
browser_snapshot (text) before browser_take_screenshot (image) | Fewer image tokens |
| Element-level screenshots, not full-page, for individual components | Smaller images |
| Max 2 screenshot rounds per component, 2 for assembly | Caps token spend |
| Screenshot only AFTER value-based loop passes — never during | No wasted screenshots |
Edge Cases
See references/edge-cases.md for truncated responses, 20+ component designs,
responsive/multi-viewport, rate limits, error recovery, component variant sets,
dark mode/themes, absolute positioning, and browser validation troubleshooting.