DEV Community

Cover image for Even With The Figma MCP, AI Eyeballs Your Design and Ships Pixel-Wrong UI
Boris Grinshpun
Boris Grinshpun

Posted on

Even With The Figma MCP, AI Eyeballs Your Design and Ships Pixel-Wrong UI

Every hardcoded value now traces to a Figma node, and "looks right" is no longer accepted as proof.

We packaged the fix as a reusable Claude Code skill, implementing-figma-designs. It turned Figma-to-code from a "build it, then eyeball it against the PNG for three correction rounds" loop into a staged extract-then-prove protocol.

The Problem

An LLM handed a Figma frame will happily invent a 1px solid #91A3B3 border, size a 24px icon at 28px, and guess the icon→text gap — because a faint border and an off-by-4px value both look correct in a screenshot, so a screenshot-based "does it match?" check passes while the running DOM is wrong.

How we solved it

  • Screenshots are for layout only — never for values. Every color/size/spacing/radius must come from the Figma MCP (get_variable_defs / get_metadata / get_design_context) per node, or be explicitly flagged as off-system. No value is read off the PNG.
  • Staged query protocol so ground truth is extracted before any product code: orient → classify nodes → confirm component mappings → triangulate code+tokens+geometry → implement.
  • Tokens beat raw hex. Whatever get_design_context emits as #EE0F51 gets reconciled back to the project's design token; anything with no token is raised to the designer, not silently hardcoded.
  • Real interactive components, never the flattened <img> that the MCP emits for un-wired toggles/inputs — every interactive node is mapped to a confirmed repo component via a human gate.
  • Evidence-on-claim verification (the key move): the running implementation is driven in a real browser (chrome-devtools MCP), and each suspect value is confirmed with getComputedStyle against the Figma node value. The screenshot tells you that something is off; the computed style tells you what.
  • The trade-off: verification is slower and chattier than a glance at a PNG — more tool calls, a human confirmation per interactive component — but it's the only thing that catches a design-system specificity loss (an sx override that loses to .MuiOutlinedInput-notchedOutline and silently keeps the wrong border while nothing errors).

Before → After

# BEFORE — value read off the screenshot, "looks right" == done
- <Icon size={28} />                 // guessed; node is actually 24
- border: '1px solid #91A3B3'        // invented; frame has no border
- // verification: screenshot looks close → PASS  (DOM still wrong)

# AFTER — value traced to a node, proven in the DOM
+ // get_metadata(node) -> width/height = 24  → <Icon size={24} />
+ // get_variable_defs(node) -> no border token → frame has NO border → omit
+ // Stage 6, in a real browser:
+ getComputedStyle($icon).width         // "24px"  ✔ matches node
+ getComputedStyle($toolbar).borderWidth // "0px"  ✔ matches frame
+ // PASS only when computed CSS == node value, per element
Enter fullscreen mode Exit fullscreen mode

The protocol, end to end

Figma frame URL
   │
   ▼
[0] resolve to a concrete node ──► [1] orient (PNG = structure only)
   │                                     │
   ▼                                     ▼
[2] classify nodes ──► [3] confirm component mappings (human gate)
   │
   ▼
[4] triangulate: get_design_context + get_variable_defs + get_metadata
   │        └─ raw hex/px  →  project token  (or flag off-system)
   ▼
[5] implement from tokens + geometry + real components
   │
   ▼
[6] VERIFY in a real browser: getComputedStyle(el) == node value ?
        PASS only per-element, with evidence — not "the PNG looks right"
Enter fullscreen mode Exit fullscreen mode

Results

  • The three defects that slipped past a human PNG-review on the origin ticket (invented border, 28px-vs-24px icon, guessed gap) are now caught mechanically at Stage 6 instead of over several by-hand correction rounds.
  • Screenshot-only sign-off is explicitly disallowed — a node isn't "done" until computed CSS is proven to equal the node value.
  • Reusable across the team: it's a versioned skill, auto-invoked when planning-dev-task hands off a Figma-linked PRD, and its verification leg (checking-figma-fidelity) plugs into our test-plan runner as a visual T-<n>.

Want to try it?! Ping me and I'll send the skill over

Top comments (0)