All guides

Figma to code: turn a link into code that matches

Paste a link to a Figma screen or flow. Your agent builds it with your own components and tokens, then proves the match with a screenshot diff.

Ask an agent to build a screen from a screenshot and it guesses. The spacing is close, the font is a substitute, and the colors are hard-coded hex values instead of your tokens. You then spend the afternoon nudging pixels.

There is a better loop. Give your agent a Figma link. It reads the real nodes behind that frame, builds the screen from your repository's own components and tokens, and then proves the match by comparing a screenshot of the app with a screenshot of the design. This guide shows the setup and the loop, for Claude Code, Cursor, Codex, or any MCP client running Canvashand.

What you need

  • Figma desktop, with the file open and the Canvashand plugin running in it.
  • canvashand setup done for your client (step-by-step for Claude Code and Cursor), which adds the tools and the canvashand skill that carries this workflow.
  • A repository with the components and tokens you want the screen built from.
  • A browser tool in your client for the screenshot check. ImageMagick is optional.

The file behind the link has to be open with the plugin running. Canvashand tools work on files the plugin is connected to, and the plugin cannot read a file's key, so Canvashand cannot match a link to a file or open one for you. If you have several files open, tell the agent which one the link belongs to.

1. Copy the link

In Figma, right-click the frame, or the board that holds a flow, and choose Copy link to selection. The URL contains something like node-id=12-34. That is node 12:34: Figma writes the colon as a dash in URLs. The Canvashand tools take node IDs, not URLs, so the agent converts the link to 12:34 itself. You do not need to do it.

2. Ask your agent

Paste the link into your client with a short request:

Build this screen in our app so it matches Figma exactly:
https://www.figma.com/design/<file-key>/<file-name>?node-id=12-34
Use canvashand. Reuse our components and tokens, and prove the match with screenshots.

<file-key> and <file-name> stay as written here: they show the shape of the URL. Paste your own link.

The agent starts in your repository, not in Figma. It finds the component library, the token file, the font setup, the icon package, and a similar existing page. Your components and tokens are what the code uses. Figma supplies the values they must produce.

3. What the agent reads

A whole frame at full detail is a lot of data, so the agent reads narrowly, one question at a time.

Need Tool call
Map of the frame: ids, names, types, bounds get_design_context with depth=2 and detail="minimal"
Layout, tokens, and text of one region get_design_context on the region with detail="full"
Exact values of a few leaves: text, icons, small controls get_nodes_info
All copy, with its family and size scan_text_nodes on the frame
Tokens to map export_tokens with format="css", or your repository's own format
Hover, press, and transition behavior get_reactions on the action node
Reference image save_screenshots with the frame's node ID, an output path, and scale: 1

Every node read takes node IDs in colon form, not URLs. The minimal map is cheap, so the agent can look at the whole frame first, then spend detail only on the region it is about to build. get_node returns a whole subtree at full detail, so the agent uses it only on small nodes, and it avoids get_document, which returns the whole page. Narrow reads keep each response, and the agent's context, small. Each read is still one call; for how call limits compare with Figma's own server, see Canvashand vs the official Figma MCP server.

4. Map, never approximate

The design supplies values. The repository supplies the code. The rules for joining them:

  • Tokens. Every Figma variable maps to a repository token. A value with no token is listed as a finding. It is not hard-coded quietly.
  • Typography. Family, style, size, line height, letter spacing, case, and decoration map exactly. If the font is not installed in the app, the agent reports it instead of substituting another.
  • Components. A Figma instance maps to the repository component with the same role, and the variant comes from the instance's componentProperties.
  • Layout. Auto layout becomes your flex or grid primitives: direction, gap, padding, alignment, and hug, fill, or fixed sizing on each axis.
  • Platform chrome. Status bar, home indicator, and navigation bar instances under System/ become safe-area insets, not markup.
  • Icons and images. If your icon set has the same glyph, use it. Otherwise the agent exports the exact vector with save_screenshots as SVG, and photos as PNG. No emoji and no lookalike icons.

5. Prove the match

This is the step that turns "looks close" into "matches". The agent runs a loop until only text anti-aliasing differs:

  1. Render the page at the frame's width, at device scale factor 1, with the same content as the frame.
  2. Screenshot the full page with the client's browser tool.
  3. Compare it with the saved Figma PNG, first the whole page, then the regions that differ.
  4. For each differing region, read the element's getBoundingClientRect() and getComputedStyle() and compare them with the Figma values read in section 3.
  5. Fix the code and repeat.

If ImageMagick is installed, this command counts the differing pixels and writes a diff image:

compare -metric AE -fuzz 3% figma.png app.png diff.png

Done means positions and sizes within 1px, and typography, colors, radii, borders, and shadows exact. Every remaining diff pixel has an explanation. The agent reports the diff image path, a table of any values still unequal, and the states or viewports it did not render.

Whole flows

A link can point at a board instead of one screen: a whole flow, or one screen in several states with component specimens and notes beside it. The agent maps the board and classifies each child. Component sets become props or variants of your components. Small text-only frames are notes, and it treats them as requirements. Screens with a different name prefix become separate routes, and states of one screen share one screen driven by one state source.

Prototype reactions drive the navigation. The agent calls get_reactions on the visible buttons and links, and turns what it finds into routes and transitions. A transition with no reaction is inferred from notes and names, and the agent marks it as inferred. Before it writes code for a board, the agent shows you a preview of what it plans to build, so you can correct the plan first. Then it runs the proof loop for every state and every screen.

Tips

  • Install the design's fonts on the machine that renders the app. A fallback font shifts every line.
  • A value with no token becomes a finding. Decide whether to add the token or change the design, rather than hard-coding the number.
  • Keep the frame width and the render width the same. The comparison only means something at the same size.
  • Start with one screen. Once the loop works, point the agent at a flow.