--- name: figma description: Import Figma content into a HyperFrames composition — rendered assets, brand tokens, components, storyboard sections → reconstructed motion (frames read as states, not slides) (REST/CLI), Figma Motion animations (MCP), and shaders (MCP source / native export). Use when the user pastes a figma.com link or asks to bring a Figma design, frame, logo, brand, or animation into a video/composition. --- # Figma → HyperFrames Bring the user's Figma work into a composition. **Split by capability** (design spec §2): | Phase | What | Transport | Surface | | ----- | ------------------- | ---------------------------- | ----------------------------- | | 1 | Static assets | REST | `hyperframes figma asset` | | 2 | Brand tokens/styles | REST | `hyperframes figma tokens` | | 3 | Components → HTML | REST | `hyperframes figma component` | | 4 | Motion → GSAP | **MCP only** | you, via `get_motion_context` | | 5 | Shaders | **MCP only** / manual export | you | REST is used wherever it can be (usable at volume, headless); MCP only where Figma exposes no REST equivalent (motion, shaders). Every path freezes assets locally so renders stay deterministic. Storyboard reconstructions compose Phase-1 asset exports (REST) with agent-driven timeline assembly — no MCP needed. Existing frozen assets, manifest records, and bindings are unaffected by routing changes — the split only changes which credential the next import uses. ## Auth — two credentials, scoped **Preflight — before the first CLI call, check a token exists**: shell env (`[ -n "$FIGMA_TOKEN" ]`) **or** the project `.env` (the CLI auto-loads it — a `.env` entry counts as configured). If neither, do NOT run the command to harvest the error — walk the user through the one-time setup first, then stop and wait: 1. figma.com/settings → **Security** → **Personal access tokens** → Generate new token. 2. Scopes — read-only is all this integration ever needs (it never writes to Figma): **File content: Read-only** + **File metadata: Read-only**. Optionally **Variables: Read-only** for brand variables — that scope only works on Figma Enterprise; without it `tokens` degrades to published styles automatically (expected behavior, not an error — say so). 3. `export FIGMA_TOKEN="figd_…"` — and suggest persisting it (shell profile or project `.env`) so no future session repeats this. While onboarding, also set expectations in one breath: every import lands as a **local frozen file with recorded provenance** — renders never call Figma, re-running a command re-imports only what changed in Figma, and one token works for assets, brand tokens, and components across every file their Figma account can view. - **Phases 4–5 (motion/shaders):** the Figma MCP connector (one-click OAuth), a separate credential from the token. If MCP tools error unauthenticated, tell the user to connect the Figma connector and stop. - Say exactly which credential a failing phase needs — never present the split as broken. - `BAD_TOKEN` (401) mid-flow → the token is expired/revoked; re-mint. `FORBIDDEN` (403) → missing read scope or no access to that file — check scopes + file visibility. `REQUIRES_ENTERPRISE` (403 on variables) → not a failure: styles fallback already ran. **Rate-limit awareness (spec §2.1):** MCP on a Starter plan is 6 tool calls/**month** (figma plan matrix as of 2026-07 — re-verify if quotas look off) — batch with `recursive:true` on the parent node, skip verification screenshots unless asked, and cache raw MCP responses so re-derivation never spends a second call. REST is per-minute (10+/min, per-endpoint buckets) — fine at volume, back off on 429. ## Routing Parse the user's figma link with `parseFigmaRef` (URL, `fileKey:nodeId`, bare `fileKey`). Then by intent: - "use this layer / logo / image" → **Asset** (CLI) - "pull my brand / colors / tokens" → **Tokens** (CLI) - "build a scene from this frame" → **Component** (CLI) - "import this animation / motion" → **Motion** (MCP, below) - a storyboard section / filmstrip of scene frames → **Storyboard** (below) - shader fill/effect → **Shaders** (below) **Narrate every step for the user** — before each command say what you're about to pull from Figma; after it, say where the artifact landed (the frozen path / sidecar / component dir), what changed in the composition, and the immediate next action (preview, add printed variables, re-import to link bindings). The user should never have to ask "did it work?" or "now what?". ## Assets (Phase 1 — CLI) ```bash hyperframes figma asset '' [--format svg|png|jpg|pdf] [--scale 2] [--description "..."] [--entity "..."] ``` Renders over REST, sanitizes SVG, freezes under `.media/images/`, appends the manifest with provenance, regenerates `.media/index.md` (the shared media-use inventory), prints an `` snippet. Idempotent per `fileKey:nodeId:format:scale:version`. Prefer SVG for vectors/logos (scalable, animatable), PNG `--scale 2` for raster fidelity. **Always pass `--description ""`** (it becomes the index row + ``); add `--entity ""` for named brand marks so media-use `resolve --entity` finds them later (entity hits match across image/icon). ## Tokens (Phase 2 — CLI) ```bash hyperframes figma tokens ``` Imports variables as composition brand-variable entries + `figma-tokens.json` sidecar + binding-index records (`.media/figma-bindings.jsonl`). Variables are Enterprise-gated upstream: on other plans the command degrades to published-style metadata (values resolve at component-import time). Add the printed entries to the composition's `data-composition-variables`. **Import tokens before components** when both are wanted — that's what lets component colors link to brand variables instead of baking duplicates. ## Components (Phase 3 — CLI) ```bash hyperframes figma component '' ``` Node tree → editable HTML at exact figma geometry, packaged as a registry item under `compositions/components//`. Vectors/boolean-ops auto-rasterize via Phase-1 export. Binding pass (spec §7.1, exact-ID only — never value matching): - Fill bound to an **imported** token → `var(--slug, #literal)` — brand refresh propagates. - Bound to an **unknown** token → literal + `data-figma-unresolved` flag. The command tells you; offer the user: run `tokens` on the source (or library) file, then re-import the component to link them. Ask **once** per unknown library which file it is — never guess, never match by hex. ## Motion (Phase 4 — MCP, the headline) **Usage beacon:** MCP phases have no CLI touchpoint, so fire the skill beacon at start and finish (anonymous, consent-gated, never fails): `npx hyperframes events --skill=figma-motion` when you begin, `npx hyperframes events --skill=figma-motion --event=skill_completed --outcome=success|error` when done. Same for shaders (`figma-shaders`) and storyboards (`figma-storyboard`). No REST equivalent exists. You drive the MCP tools, then hand output to the pure helpers in `@hyperframes/core/figma`: 1. `get_motion_context(fileKey, nodeId)` — use `recursive:true` on the parent frame (one call for the whole scene, not one per element). Save the raw JSON next to the project (`.media/figma-cache/`) so retranslation is free. 2. Normalize into a `MotionDoc`: per animated property a `MotionTrack` { property (motion.dev name), values, times (0..1), ease[] (named or `[x1,y1,x2,y2]` bezier), duration, repeat }. Selector = the element's stable id (`#` from Phase-3 output or the authored scene). 3. `motionToGsap(doc)` → `emitTimelineScript(spec)` → inject as a `