---
title: Figma integration
description: "Bring Figma designs into HyperFrames — frozen assets, brand tokens, editable components, storyboard reconstruction, and Figma Motion timelines translated to GSAP."
---

import { DocsVideo } from "/snippets/docs-video.jsx";

Import the parts of a Figma design that should survive into the project: assets,
brand values, editable components, motion, or storyboard states. HyperFrames
stores the result locally so the render does not depend on Figma.

<DocsVideo
  title="A Figma frame beside the same design imported as working HTML"
  src="https://static.heygen.ai/hyperframes-oss/docs/images/showcase/figma-to-html-demo-v1.mp4"
  poster="https://static.heygen.ai/hyperframes-oss/docs/images/showcase/figma-to-html-demo-v1.jpg"
/>

The same cursor and the same clicks land on both panels. Only the imported side
responds — the field takes text, the button runs its states. One side is pixels,
the other is a component.

## What you can import

| Capability | What you get | Surface |
| --- | --- | --- |
| **Static assets** | A frame/layer rendered to SVG/PNG/JPG/PDF, frozen under `.media/` | `hyperframes figma asset` |
| **Brand tokens** | Figma variables/styles as composition brand variables | `hyperframes figma tokens` or the `/figma` skill via a Figma connector |
| **Components** | A frame as editable HTML with brand-linked colors | `hyperframes figma component` |
| **Motion** | A Figma Motion timeline as an editable, paused GSAP timeline | `/figma` skill (agent, MCP) |
| **Shaders** | A shader fill/effect as a frozen still or clip | `/figma` skill (agent, MCP) |
| **Storyboards** | Scene frames reconstructed as motion — frames read as states, not slides | `/figma` skill (agent; REST assets are enough) |

Assets, tokens, and components use Figma's **REST API** and can run headlessly.
Motion and shader data can come through a compatible **Figma connector**; if
that surface is unavailable, provide a native export instead. Storyboard
reconstruction uses ordinary frame exports plus the agent's analysis.

## One-time setup

Most people only need one connection:

| You want to import… | Set up |
| --- | --- |
| A logo, image, or a whole frame as HTML (assets, components) | A **token** — Step A below |
| Brand colors (tokens) | Either works, but on a non-Enterprise plan the **MCP connector** (Step B) gets you there in one click — the token path needs an Enterprise plan for this specific pull |
| Motion or shaders | A compatible **Figma connector**, or a native export |
| Storyboard frames | A token for frame exports; no connector is required |

Do both if your project needs everything; each is independent, so it doesn't matter which you set up first.

### Step A — Figma token (assets, tokens, components)

Needed for anything you run from the `hyperframes figma` CLI.

<Steps>
  <Step title="Mint a token">
    In Figma: **Settings → Security → Personal access tokens → Generate new token.**
  </Step>
  <Step title="Check these scopes">
    Read-only is all it ever needs — the integration never writes to Figma. **On most accounts (not Figma Enterprise), check exactly these three:**

    - **File content** — Read-only
    - **File metadata** — Read-only
    - **Library content** — Read-only — easy to miss, and without it `tokens` 403s the moment it tries the published-styles fallback

    On a **Figma Enterprise** plan, also check **Variables — Read-only** to pull brand colors directly via `tokens`. Not on Enterprise? Skip it — `tokens` falls back to published styles automatically, or use the MCP connector (Step B) instead, which reaches variables on any plan.
  </Step>
  <Step title="Export it">
    ```bash
    export FIGMA_TOKEN="figd_…"
    ```

    Add the line to your shell profile or the project's `.env` so future
    sessions skip this step. The token can read files that its Figma account
    and scopes allow.
  </Step>
</Steps>

### Step B — Figma connector (motion, shaders, and a token-free path to brand colors)

No token, no scopes to pick — connect it once when your agent asks (a one-click OAuth) and it stays connected.

This is also a convenient way to read the brand values used by a selection when
the REST variables endpoint is unavailable on your plan. Connector
availability and usage limits depend on Figma's current plan and client rules,
so the agent should batch requests and cache the result.

## Import an asset

```bash
hyperframes figma asset 'https://www.figma.com/design/KEY/Title?node-id=1-2'
```

The node renders over REST, lands frozen under `.media/images/`, and the command prints a ready-to-paste `<img>` snippet:

```text
imported image_007 → .media/images/image_007.svg
<img src=".media/images/image_007.svg" alt="image_007" data-figma-id="1:2" />
```

- `--format svg|png|jpg|pdf` (default `svg`). SVG for logos and vectors — scalable and animatable. `--format png --scale 2` for raster fidelity.
- Accepted refs: a full Figma URL with `?node-id=…` (right-click a layer → Copy link) or `fileKey:nodeId` shorthand. Asset and component imports always target a specific node; only `tokens` takes a bare `fileKey`.
- Idempotent: the manifest records `fileKey:nodeId:format:scale:version`, so re-running reuses the file unless the design actually changed in Figma.

## Pull your brand

```bash
hyperframes figma tokens KEY
```

Reads the file's variables (or published style metadata), writes a
`figma-tokens.json` sidecar plus a binding index, and prints entries for the
composition's `data-composition-variables`. Scenes that reference those roles
use the same local values. Run `tokens` again when the Figma file changes.

<Tip>
Import tokens **before** components. That's what lets an imported component's colors link to your brand variables instead of baking duplicate literals.
</Tip>

## Import a component

```bash
hyperframes figma component 'https://www.figma.com/design/KEY/Title?node-id=10-20'
```

The frame's node tree becomes editable HTML at exact Figma geometry, packaged under `compositions/components/<name>/`. Vector and boolean-op nodes that don't map to clean HTML auto-rasterize through the asset path.

Colors bound to a Figma variable resolve against your imported tokens:

- Bound to an **imported** token → emitted as `var(--brand-slug, #0066FF)` — a later brand refresh propagates into the component.
- Bound to a token you **haven't imported** → the literal color is used and the element is flagged `data-figma-unresolved`. The command tells you; run `tokens` on the source (or library) file and re-import to link them.

Matching is by exact Figma ID only — never by hex value — so a coincidentally-shared color can't create a false brand link.

## Motion, shaders, and storyboards

These run through the `/figma` agent skill:

- **Motion** — a Figma Motion timeline (keyframes, easing, repeats) translates structurally into a paused, finite GSAP timeline registered on `window.__timelines`, seekable frame-by-frame like any hand-authored animation, and editable afterward. Tracks that can't translate faithfully fall back to a baked video clip — the agent tells you which path it took and why.
- **Shaders** — Figma's export path doesn't execute shaders, so the default is a native Figma export (PNG or Motion MP4) imported as an asset/clip.
- **Storyboards** — a section of scene frames is decoded, not slideshowed:
  repeated elements become continuity clues and the differences between frames
  become motion or interaction. A connector is not required for this path.

## Provenance and refresh

Every import records where it came from (`fileKey`, `nodeId`, `version`) in `.media/manifest.jsonl`. Nothing in a rendered composition points at Figma — assets are files, tokens are variables, motion is a timeline. When the Figma file moves on, re-running the same import commands re-pulls only what changed.

## Troubleshooting

| Error | Meaning | Fix |
| --- | --- | --- |
| `NO_TOKEN` | `FIGMA_TOKEN` unset | Follow [One-time setup](#one-time-setup) |
| `BAD_TOKEN` | Token invalid, expired, or revoked (Figma returns **403 `Invalid token`** for bad PATs, not 401) | Re-mint the token |
| `FORBIDDEN` (403) | Missing a read scope, or no access to the file | The message names the exact scope Figma wants (e.g. `library_content:read` for the styles fallback) — add it, or check file visibility |
| `REQUIRES_ENTERPRISE` (403) | Variables API needs Figma Enterprise | Not a failure — `tokens` falls back to published styles (which needs the Library content scope above) |
| `RATE_LIMITED` (429) | Figma's per-minute limit | The client retries with backoff automatically (honoring `Retry-After`); if it still surfaces, wait a minute or batch fewer nodes |
| "Render timeout" on batch export | Too many large frames in one `/v1/images` call | Chunk to ~4 ids per call |
| `ref has no node id` | Link points at a file, not a node | Copy the link with `?node-id=…` (right-click layer → Copy link) |

## Related topics

- [Bring a design into a project](/guides/design-tools)
- [Work on the imported project in Studio](/studio)
- [Manage project media](/guides/media)
