Figma to Code skill for Codex

Match the frame using your own components and tokens. With this skill Codex treats Figma output as a spec rather than code to paste. It fetches the frame's screenshot, design context and variables, builds token and component mapping tables, converts Auto Layout, strokes and text metrics to correct CSS, reuses existing components, and compares a rendered screenshot with the design before reporting remaining deltas.

  • Design & UX
  • $figma-to-code
  • 182 lines
  • 2 files
  • ~2,050 tokens
  • MIT
  • Updated

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- figma-to-code

Installs to ~/.agents/skills/figma-to-code/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $figma-to-code, or pick it from /skills. You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.

What Codex reads before loading it

Implements Figma frames faithfully in an existing codebase using the Figma MCP server (get_design_context, get_variable_defs, get_screenshot) or the REST API, mapping Auto Layout to flexbox and grid, Figma variables to project tokens, components to existing code components, and verifying with side-by-side screenshot comparison. Use when given a Figma link or node-id, asked to build a screen or component "from the design", to match a mockup pixel-close, or to set up Figma MCP in Codex.

Use it when

  • You have a Figma link or node-id to implement
  • An implementation drifts from its mockup and needs a fidelity pass
  • Connecting Codex to Figma through MCP or the REST API
  • Mapping Figma variables and components onto an existing codebase

Use something else when

How to check the result

A screenshot of the implementation at the frame's width matches the Figma export in structure, spacing and type, and no raw hex or off-scale pixel values remain in the new code.

The mistake it prevents

Pasting the generated reference code as-is, which hard-codes values and duplicates components the project already has.

~/.agents/skills/figma-to-code/SKILL.md

--- name: figma-to-code description: Implements Figma frames faithfully in an existing codebase using the Figma MCP server (get_design_context, get_variable_defs, get_screenshot) or the… license: MIT ---

A faithful implementation matches the frame at its design width within a few pixels, uses the project’s existing components and tokens instead of pasted values, behaves sensibly at other widths, and covers the states the design implies. Generated code that looks right but hard-codes #3B82F6 and padding: 23px is a screenshot, not a build.

Setup: getting design data into Codex

Pick the first that works:

SourceHowNotes
Figma remote MCP serverAdd to ~/.codex/config.toml, then codex mcp login figmaNeeds network and OAuth in a browser
Figma desktop MCP serverEnable it in the desktop app’s Dev Mode, point Codex at http://127.0.0.1:3845/mcpDesktop app must be open; selection-based
REST APIcurl with a personal access token from an env varRead-only; no design context generation
Screenshot or export onlyUser attaches PNGs and specsMeasure from the image; ask for key values
# ~/.codex/config.toml
[mcp_servers.figma]
url = "https://mcp.figma.com/mcp"

Check with /mcp in the Codex TUI. The MCP server is network access; in a sandbox with network off, ask the user to approve or to provide exports.

REST fallback (token stays in the environment, never in files or chat):

# node-id in the URL is 12-345; the API uses 12:345
curl -s -H "X-Figma-Token: $FIGMA_TOKEN" \
  "https://api.figma.com/v1/files/$FILE_KEY/nodes?ids=12:345" > .figma/node.json
curl -s -H "X-Figma-Token: $FIGMA_TOKEN" \
  "https://api.figma.com/v1/images/$FILE_KEY?ids=12:345&format=png&scale=2"   # returns a URL to download

Before writing code

  • Read AGENTS.md, the component directory, the token/theme files and one similar existing screen. Your output must look like it was written by the same team.
  • Get the exact frame: a link with node-id, not the whole file. Large frames overflow context; fetch the page outline with get_metadata, then request child frames one at a time.
  • Collect from MCP for each target node:
    • get_screenshot: the visual truth to compare against.
    • get_design_context: structure, styles and a reference implementation (React + Tailwind by default). Treat it as a spec, not as code to paste.
    • get_variable_defs: the Figma variables and styles used, with values.
    • get_code_connect_map when Code Connect is set up: which code component each Figma component maps to.

Workflow

- [ ] 1. Fetch screenshot, design context and variables for the frame
- [ ] 2. Map Figma variables and styles to project tokens (table)
- [ ] 3. Map Figma components to existing code components (table)
- [ ] 4. Decompose the frame into sections and new components
- [ ] 5. Implement layout (Auto Layout -> flex/grid), then content, then states
- [ ] 6. Export and optimize assets
- [ ] 7. Compare screenshots at design width; fix deltas
- [ ] 8. Check other widths and states; report gaps

2. Token mapping

Build a table before coding. Every Figma value lands on a token or gets flagged:

FigmaValueProject tokenStatus
color/bg/brand#1D5FD6--color-bg-action-defaultmatch
spacing/lg24space-6 (24px)match
raw fill#1E60D5--color-bg-action-defaultnear-duplicate, use token
raw padding23space-6off-scale, snap to 24
Heading/H2Inter 600 28/36text-2xl font-semiboldsize match, check leading

Snap off-scale values (1–2 px away) to the nearest token and say so in the report. Values far from any token mean a missing token; ask before adding one.

3. Component mapping

Figma componentVariant propsCode component
ButtonType=Primary, Size=M, State=Hover<Button variant="primary" size="md"> (hover is CSS)
Input/With labelError=True<TextField invalid errorMessage=...>
Card/Pricingnonenew: PricingCard (compose Card)

Never rebuild an existing component because the Figma layer names differ. Hover, pressed and focus variants in Figma are CSS states, not props.

5. Auto Layout to CSS

FigmaCSS
Horizontal / Verticaldisplay:flex; flex-direction: row / column
Gap between itemsgap
Spacing mode “Auto”justify-content: space-between
Paddingpadding (per side)
Hug contentswidth: fit-content or default auto sizing; flex: none in a flex parent
Fill container (main axis)flex: 1 1 0; min-width: 0
Fill container (cross axis)align-self: stretch
Fixed widthwidth only for icons, avatars, controls; otherwise max-width
Wrapflex-wrap: wrap plus row-gap from counter-axis spacing
Grid auto layoutdisplay:grid; grid-template-columns
Absolute position childposition:absolute inside a position:relative parent
Min/max widthmin-width / max-width
Clip contentoverflow: hidden

Text conversions:

  • Line height in % or px: use unitless ratio (36/28 = 1.286, round to the token). “Auto” means normal.
  • Letter spacing in %: divide by 100 and use em (-2% -> -0.02em).
  • Text box “fixed height” usually means the designer dragged it; let text flow.
  • Text styles map to type tokens; mixed styles in one text layer map to inline elements.

Stroke conversions: inside stroke -> border with box-sizing: border-box; outside -> outline or box-shadow: 0 0 0 1px; center -> pick inside and note the 0.5 px shift. Drop shadows map directly to box-shadow (x, y, blur, spread, color); layer blur maps to filter: blur(), background blur to backdrop-filter: blur().

6. Assets

  • Icons: use the project’s icon library if the Figma icon matches by name; otherwise export SVG, run SVGO, and add to the icon set (see icon-systems).
  • Images: export at 2x, convert to AVIF/WebP, set width/height to prevent layout shift. Do not ship Figma’s placeholder images as final assets.
  • MCP may serve assets from a localhost URL; download them into the repo, never ship references to that URL.

7. Compare

Render at the frame’s width, then compare against the Figma screenshot:

npx playwright screenshot --viewport-size "1440,900" --full-page http://localhost:5173/pricing .shots/pricing-impl.png

Open both images (Codex can view local images) and check, in order: overall structure and section heights, alignment edges, type size and leading, spacing between groups, colors, radii and shadows, icon sizes. For a numeric check, overlay with 50% opacity in the browser or use Playwright’s toHaveScreenshot against an exported reference with a small maxDiffPixelRatio; font rendering differences make exact matches impossible.

8. Beyond the frame

  • Designs usually show one width. Derive behavior at 360, 768 and 1280+: what stacks, what wraps, what truncates. If the file has mobile frames, implement those too.
  • Implied states: hover, focus-visible, disabled, loading, empty, error, long text.
  • If the design breaks accessibility (contrast under 4.5:1, tiny tap targets), implement the accessible version and list the deviation.

Gotchas

  • Pasting get_design_context output wholesale: it uses absolute values and generic markup. Rewrite with project components and tokens.
  • Requesting a whole page at once: output truncates and quality drops. Go frame by frame.
  • Figma fonts not installed in the project: confirm the web font and license; never silently substitute a different family.
  • Hidden layers and detached instances in the file produce phantom elements.
  • Design width 1440 with a 1200 container: implement the container, not 1440 fixed.
  • Desktop MCP server tools act on the current selection; ask the user to select the frame or pass the node-id link.

Output contract

**Frame:** <file name / node-id>  **Route/component:** <path>
**Token mapping:** <n> matched, <n> snapped (list), <n> missing (asked/added)
**Components reused:** Button, TextField, Card. **New:** PricingCard (src/...)
**Assets:** <icons/images added and where>
**Fidelity check:** compared at 1440 px; remaining deltas: <font rendering, ...>
**Responsive behavior chosen:** <what stacks at which width>
**Deviations from design:** <with reasons, e.g. contrast fix>

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "Figma to Code"
  short_description: "Match the frame using your own components and tokens"
  default_prompt: "$figma-to-code Implement this Figma frame as the new pricing page using our components"

About this skill

Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.

esc
Just launched

Codex Skills Pro is live

79 premium skills for Codex, each with scripts, references and an evidence report that proves the result.

Bought one by one$882.21
All 79 skills$49
94% off

That's $0.62 a skill, paid once.

Get all 79 for $49Or pick single skills from $4.99 →

Secure checkout by Creem