Cursor's AI can write a lot of UI code. What it can't do is read your Figma file. You paste in a screenshot and it guesses — wrong spacing, wrong color values, made-up component names. The gap isn't the model. It's the missing structured context.

figmascope bridges that gap. It exports a Figma file as a zip bundle — design tokens, per-screen layout trees, reference renders, component inventory, UI strings — everything a language model needs to generate accurate code rather than plausible-looking code. The main app runs entirely in your browser with no backend or upload required.

This page walks through the full workflow from Figma URL to Cursor codegen. If you use Claude Code instead of Cursor, see Figma to Claude Code for the Claude-specific workflow. For a broader look at what makes handoff agent-ready, see AI Design Handoff.

What's in the context bundle

When you run figmascope against a Figma file, you get a .zip containing:

Nothing is uploaded. Your Personal Access Token lives in browser memory only and is sent only to api.figma.com. The zip is assembled client-side and handed to your browser's download.

Step 1 — Get a Figma Personal Access Token

Go to Figma → Account Settings → Personal Access Tokens and create a token with File content: read-only scope. That's the minimum required.

The token never leaves your browser session; figmascope sends it in the X-Figma-Token header on requests to api.figma.com and nowhere else. See PAT security and figmascope for the full threat model.

Step 2 — Export the context bundle

  1. Open figmascope.dev in your browser.
  2. Paste the Figma file URL (e.g. https://www.figma.com/file/ABC123/MyDesign).
  3. Paste your Personal Access Token.
  4. Click Export Context Bundle.
  5. A figmascope-<fileKey>.zip downloads to your machine.

Unzip it into your project. A sensible location is a design/ folder at the repo root:

unzip figmascope-ABC123.zip -d design/
# → design/CONTEXT.md
# → design/tokens.json
# → design/screens/Home.json
# → design/screens/Home.png
# → design/components/inventory.json
# → design/strings.json
# → design/_meta.json

Step 3 — Open the project in Cursor

Open your project folder in Cursor as normal. The design/ directory is now part of the workspace and Cursor's indexer will include it.

Before you prompt the model, read design/CONTEXT.md yourself once. It tells you which frames were exported, what the token naming scheme is, and lists any warnings emitted during export (e.g. layout-mode-none-inferred for frames where Figma reported no auto-layout). These warnings are the same ones your agent will encounter.

Step 4 — Write an effective Cursor prompt

The simplest starting point is a reference prompt you can paste into Cursor Chat:

Read design/CONTEXT.md first, then implement the Home screen.

Use:
- design/tokens.json for all color, spacing, and typography values
- design/screens/Home.json for the layout tree
- design/screens/Home.png as the visual reference
- design/strings.json for all copy (use the resource keys as i18n identifiers)
- design/components/inventory.json to match component names

Target: React + Tailwind CSS. Map token values to Tailwind config entries rather
than hardcoding hex values. Use the component names from inventory.json as
component file names (PascalCase).

Cursor's Composer will follow CONTEXT.md's constraints, look up the layout tree in Home.json, pull spacing from tokens.json, and produce code that matches your design system rather than approximating it.

The model doesn't know your design. It knows what you give it. Structured JSON beats a screenshot every time.

Step 5 — Map tokens to your framework config

The exported tokens.json uses a W3C-ish nested shape:

{
  "color": {
    "surface": { "$value": "#f6f2ea", "$type": "color" },
    "accent":  { "$value": "#d96a3a", "$type": "color" }
  },
  "spacing": {
    "4":  { "$value": "16px", "$type": "dimension" },
    "8":  { "$value": "32px", "$type": "dimension" }
  },
  "radius": {
    "sm": { "$value": "4px",  "$type": "dimension" },
    "md": { "$value": "8px",  "$type": "dimension" }
  },
  "typography": {
    "body": {
      "fontFamily": { "$value": "Inter",  "$type": "fontFamily" },
      "fontSize":   { "$value": "14px",   "$type": "dimension" },
      "fontWeight": { "$value": 400,       "$type": "number" }
    }
  }
}

For Tailwind, ask Cursor to generate a tailwind.config.js theme.extend block directly from tokens.json. See Design Token Export for AI Agents for a deep dive on the token format and frequency inference. The token structure is flat enough to traverse in a single Node script if you want to automate it:

// scripts/tokens-to-tailwind.js
const tokens = require('../design/tokens.json');

const colors = Object.fromEntries(
  Object.entries(tokens.color).map(([k, v]) => [k, v.$value])
);
const spacing = Object.fromEntries(
  Object.entries(tokens.spacing).map(([k, v]) => [k, v.$value])
);

module.exports = { colors, spacing };

Step 6 — Handle multi-screen projects

Each frame in your Figma file becomes a screens/<FrameName>.json and a matching .png. For a project with a dozen screens, work through them incrementally. Cursor Composer handles one screen per session well; give it the screen JSON and PNG as explicit @file references:

@design/screens/Settings.json
@design/screens/Settings.png

Implement the Settings screen. Follow the same component structure
as the Home screen already implemented. Use tokens from design/tokens.json.

The component inventory (design/components/inventory.json) helps you avoid name drift across screens — every component referenced in a screen JSON has a canonical id and name in the inventory. If you're generating a shared component library, use those names as the source of truth.

What the IR looks like in practice

The per-screen JSON uses a recursive node structure. A simplified example for a card component:

{
  "kind": "stack",
  "name": "ProductCard",
  "direction": "vertical",
  "gap": { "$ref": "spacing.4" },
  "padding": { "top": 16, "right": 16, "bottom": 16, "left": 16 },
  "background": { "$ref": "color.surface" },
  "radius": { "$ref": "radius.md" },
  "children": [
    {
      "kind": "leaf",
      "name": "ProductImage",
      "type": "image",
      "width": 320,
      "height": 200
    },
    {
      "kind": "leaf",
      "name": "ProductTitle",
      "type": "text",
      "text": { "$ref": "strings.product.card.title" },
      "style": { "$ref": "typography.heading.sm" }
    }
  ]
}

Token references use $ref strings that match keys in tokens.json. The model can resolve them without a separate lookup step. See per-screen IR explained for the full node schema.

Keeping context fresh

Design files change. A good habit: re-run figmascope whenever the design has a significant revision, commit the updated design/ folder, and note the version in your PR description. The _meta.json includes a timestamp and the Figma file's lastModified field, so you can diff when the bundle was last regenerated versus when the file was last touched.

// _meta.json
{
  "figmascopeVersion": "1.0.0",
  "fileKey": "ABC123",
  "exportedAt": "2026-05-11T09:14:00Z",
  "figmaLastModified": "2026-05-10T18:30:00Z",
  "frameCount": 12,
  "warnings": []
}

If warnings is non-empty, address them before handing context to the agent. Common warnings: strings-collision (two nodes with the same slug resolved to the same key) and layout-mode-none-inferred (a container without explicit auto-layout, where figmascope inferred layout from child positions).

Common Cursor workflows

Diff-based updates

When the design has a minor revision — say, a spacing value changed from spacing.4 to spacing.6 on the card component — you can ask Cursor to apply only the delta rather than regenerate the whole screen:

The design/tokens.json was updated. spacing.4 is now 24px instead of 16px.
Find all components using spacing.4 and update them. Do not touch anything else.

This works because your generated components reference token names as Tailwind classes (gap-spacing-4) rather than raw pixel values. A token change is a find-and-replace, not a redesign.

Adding a new screen to an existing codebase

When you're adding screen N to a codebase that already has screens 1 through N-1 implemented, the key prompt addition is grounding the agent in the existing component library:

@design/screens/Checkout.json
@design/screens/Checkout.png

Implement the Checkout screen. Reuse existing components from src/components/
wherever the component name matches design/components/inventory.json.
Only create new component files for components not already implemented.
Use design/tokens.json for all token values.

The component inventory is the bridge between the design component name and the codebase file name. Without it, the agent will make up import paths and create duplicate components.

Generating a design system baseline

Before implementing any screens, use the context bundle to generate a baseline design system: the token configuration, a color palette component, and the base typography styles. This anchors all subsequent screen implementations to the same foundation:

Read design/tokens.json and design/CONTEXT.md.

Generate:
1. tailwind.config.ts theme.extend block from all tokens
2. src/styles/tokens.css with CSS custom properties for the same tokens
3. src/components/foundations/ColorPalette.tsx showing all color tokens
4. src/styles/typography.css with the typography token classes

Name all classes and variables using the token key paths
(e.g. --color-accent, text-ink, bg-surface).

Once this baseline exists, every screen implementation can reference it. The agent won't re-derive colors from the design on each session — it'll use the already-generated classes.

Limitations to know upfront

figmascope's context bundle captures static structure. A few things it can't represent:

The CONTEXT.md file notes which frames were excluded and why, so the agent doesn't attempt to implement something that was intentionally out of scope.