Igniteui Angular Figma To App
IgniteUI/igniteui-angular
Builds Angular views from Figma designs with Ignite UI for Angular, supporting Indigo.Design kits, third-party kits, and plain frames.
Converts a working code prototype into a structured Figma file with one frame per interaction state, mapped to your design system and annotated with transitions.
$ npx skills add alima-max/prototype-to-figma-skill --skill prototype-to-figma -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install alima-max/prototype-to-figma-skill prototype-to-figma --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
Claude Code skills documentation · loads skills from .claude/skills/
Install the "prototype-to-figma" agent skill from https://github.com/alima-max/prototype-to-figma-skill/tree/main into .claude/skills/prototype-to-figma/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "prototype-to-figma", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add alima-max/prototype-to-figma-skill --skill prototype-to-figma -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install alima-max/prototype-to-figma-skill prototype-to-figma --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "prototype-to-figma" agent skill from https://github.com/alima-max/prototype-to-figma-skill/tree/main into .agents/skills/prototype-to-figma/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "prototype-to-figma", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add alima-max/prototype-to-figma-skill --skill prototype-to-figma -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install alima-max/prototype-to-figma-skill prototype-to-figma --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "prototype-to-figma" agent skill from https://github.com/alima-max/prototype-to-figma-skill/tree/main into .cursor/skills/prototype-to-figma/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "prototype-to-figma", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add alima-max/prototype-to-figma-skill --skill prototype-to-figma -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install alima-max/prototype-to-figma-skill prototype-to-figma --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "prototype-to-figma" agent skill from https://github.com/alima-max/prototype-to-figma-skill/tree/main into .gemini/skills/prototype-to-figma/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "prototype-to-figma", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install alima-max/prototype-to-figma-skill prototype-to-figmaInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add alima-max/prototype-to-figma-skill --skill prototype-to-figma -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "prototype-to-figma" agent skill from https://github.com/alima-max/prototype-to-figma-skill/tree/main into .github/skills/prototype-to-figma/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "prototype-to-figma", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add alima-max/prototype-to-figma-skill --skill prototype-to-figma -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install alima-max/prototype-to-figma-skill prototype-to-figma --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "prototype-to-figma" agent skill from https://github.com/alima-max/prototype-to-figma-skill/tree/main into .opencode/skills/prototype-to-figma/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "prototype-to-figma", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
prototype-to-figmaConverts a working code prototype into a structured Figma file with one frame per interaction state, mapped to your design system and annotated with transitions.
The skill takes a running prototype and produces a Figma file that product managers, designers and engineers can review without running any code. It has two goals: exact visual match with the rendered prototype, and a result that uses your design system, with captured elements reconciled to component instances, bound variables and text styles wherever the system is published to Figma. Every state transition is annotated on its node.
Its first rule is to capture headlessly. A separate headless Chrome process driven by Playwright renders the app and serializes the DOM straight to Figma, so nothing opens on screen and the designer stays in the terminal. The skill rejects both rebuilding the layout by hand from source code and capturing through a visible browser tab. Five non-negotiable rules govern the run.
The skill works across Figma MCP clients and adapts its output format to what the connected client supports. A figma-patterns.md file ships alongside it in the repository, together with a README and the licence file.
6 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 6e2e1be. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
npxFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npx, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Prototype to Figma loads about 7.8k tokens when it runs. Until then it costs about 218 tokens; SKILL.md has 3,831 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from alima-max/prototype-to-figma-skill at commit 6e2e1be, republished under its MIT licence (© alima-max). 3,831 words, ~7,751 tokens.
.claude/skills/prototype-to-figma/SKILL.md (or your agent's skills folder). This skill also uses 3 other files; get the full folder from GitHub.This skill takes a working Claude Code prototype and produces a structured Figma file that cross-functional partners can review asynchronously. The output has two equal goals:
This skill works across all Figma MCP clients. The output format adapts to what your client supports — see Client Compatibility below.
True 1:1 requires rendering the code — but rendering does NOT require a visible browser. Use a headless browser (Playwright) so the whole run stays in the terminal: no window, no tab. That is the point for the target user — designers working exclusively in code who must not be pulled out of the IDE.
Three options; only one is right:
open "<url>#figmacapture=…", the in-app preview, or the GUI Figma
extension. Correct fidelity, but it pops windows/tabs and drags the designer out of the terminal
(and the bare extension gives no DS instances)."Headless" = a separate Chrome process launched with --headless: no window, no tab, nothing on
screen. It does NOT attach to the designer's open browser and does NOT require Chrome to be
open — only installed. It spins up invisibly, renders the localhost page in memory, serializes
to Figma, and exits. The designer never leaves the terminal and sees nothing happen in their browser.
The capture (headless, terminal-only):
generate_figma_design capture script
(navigate to the LOCAL dev URL → strip CSP → inject capture.js → window.figma.captureForDesign( { captureId, endpoint, selector:'body' })). Prefer the machine's already-installed Chrome
(puppeteer-core, or Playwright with channel:'chrome', or raw CDP) so there's no download and
no MCP — Chrome need only be installed, not open. Only if no Chrome/Chromium is found, fall
back to a one-time bundled-Chromium download (npx playwright install chromium / full
puppeteer). Never launch a new visible instance, never attach to the user's live browser,
never use open "<url>#figmacapture=…" or the in-app preview — all of those put a window/tab on
screen.generate_figma_design (fileKey + captureId) until completed. You get a fully-layered 1:1
base (frames / text / vectors) with tokens bound (bindVariables=true).Then reconcile to the DS + annotate (use_figma, Rule 2): swap repeated captured elements for DS
component instances, bind variables / text styles where the DS is actually published to Figma,
and attach Dev Mode annotations + flow arrows. This is the cheap, surgical layer — it touches a
handful of components, not the whole page.
Requirements / honesty: needs (a) a headless browser — ideally the machine's installed Chrome driven headless (no download, no MCP required); a bundled Chromium download is the fallback — and (b) a runnable dev server. No Playwright MCP is required; a headless Chrome runtime is. If there's genuinely no browser at all, say so and stop — do not fall back to a visible tab, and do not hand-build from source and call it 1:1 (it won't be). If the design system isn't published to Figma as components/variables, reconciliation is limited to what exists — flag that DS gap, don't swap in a foreign library's components.
Do not call figma.createComponent() or figma.createComponentSet(). These pollute the
design system with components that don't belong there.
When a prototype element has no component of any kind in the DS (see Rule 2 for the bar):
build it from primitives (figma.createFrame(), figma.createRectangle(), figma.createText()),
add a DS Drift annotation explaining what was missing, and list it in the Phase 6 summary.
The capture (Rule 0) gives parity; this rule makes the file design-system-native. It applies as you reconcile each captured element — the captured node tells you where, how big, and how it looks, but the structure should come from the DS wherever a match exists. Walk the captured frame and reconcile every element to the linked library:
fontSize/fontName.The rule in one line: prefer the component / color variable / number variable / text style over any literal whenever a match exists. Raw hex, ad-hoc numbers, and shadow-primitives are drift — not parity — even when they look right. Phase 2 discovers the components, variables, and styles; Phase 4 swaps and binds them onto the captured base.
Every visible element must appear in the Figma output — DS instance or primitive. Skipping elements because you couldn't find a DS match is the most common cause of incomplete outputs.
Annotations are what make this output useful for review. A frame with no annotations is just a static image. But annotating every tap target creates noise that buries the actual flow.
Annotate using node.annotations = [...] on the actual layer — this surfaces in Figma Dev Mode
on the correct element. Never create floating text boxes or separate annotation frames as a
substitute. If the native API fails, fall back to figma-patterns.md Section 11.
Two categories only:
Annotate (Interaction):
Do not annotate:
Target: 2–4 Interaction annotations per frame. A reviewer should be able to read all annotations on a frame in under 30 seconds and understand the complete flow.
Every element with a DS Drift note from Phase 2 must have a DS Drift annotation.
| Tier | Inspect | Write | Code Connect | Output |
|---|---|---|---|---|
| Full | ✅ | ✅ | ✅ | Figma file with DS components, native annotations, Code Connect links |
| Write | ✅ or ❌ | ✅ | ❌ | Figma file with native annotations |
| Inspect-only | ✅ | ❌ | ❌ | Prototype Spec Document (markdown) |
| None | ❌ | ❌ | ❌ | Prototype Spec Document from code analysis alone |
| Client | Inspect | Write | Code Connect |
|---|---|---|---|
| Claude Code / Desktop / Cursor / VS Code / Copilot CLI / Augment / Factory | ✅ | ✅ | ✅ |
| Android Studio / Gemini CLI / Kiro / Amazon Q / Openhands | ✅ | ❌ | ❌ |
| Replit | ❌ | ✅ | ❌ |
Inspect: get_design_context (primary), get_metadata (structure overview),
search_design_system (components + variables), get_variable_defs (exact token values),
get_screenshot (only if user explicitly requests a visual preview).
Capture (primary path — Rule 0): generate_figma_design driven by a headless browser —
ideally the machine's installed Chrome run headless (puppeteer-core / Playwright
channel:'chrome' / CDP; no download, no MCP), bundled Chromium only as a fallback — against the
local dev server. Renders + serializes 1:1 to Figma with no visible window/tab. NEVER the
open-a-tab flow or the in-app preview (visible), and never attach to the user's open browser.
Write: use_figma (reconcile captured nodes to DS instances + variables, annotate, assemble
the flow), whoami, create_new_file.
Code Connect: get_code_connect_map, get_code_connect_suggestions,
get_context_for_code_connect, send_code_connect_mappings.
File: Extract fileKey from a user-provided URL (figma.com/design/:fileKey/...). If no
URL is given, call whoami then create_new_file — never block on a missing URL.
Capabilities: Attempt get_metadata to confirm Inspect tools. Check tool list for
use_figma (Write) and get_code_connect_map (Code Connect). Announce what you have.
Route: Write tools available → Phases 1–6. Write tools unavailable → Phases 1–3, then Prototype Spec Document.
Read all prototype source files before touching Figma.
Component inventory — for every UI component, record: name, props/variants in use, visual structure (what's inside it), and whether it is interactive. This list is the completeness checklist for Phase 4.
Interaction flows — for each flow, map: trigger → state change → before/after states → branching paths (success / error / edge cases). Include state count.
Layout structure — note what's fixed vs. scrollable, what persists across states (nav,
header), and the viewport dimensions. For the phone/device frame: if the prototype wraps screens
in a .phone, .device-frame, or similar shell, extract only the content dimensions and
use those for Figma frame size — do not recreate the shell as a wrapper frame in Figma.
Source read (for inventory + structure, NOT for pixel values) — read the CSS modules,
Tailwind config, and inline styles to understand each element's structure, variants, and which
are interactive. Do not treat source CSS values as the pixel source of truth: responsive/
computed CSS (grid fr, clamp(), min/max, vw, transforms, theme scopes) resolves to
formulas, not pixels. The pixel source of truth is the computed measurement from the running
app (Rule 0 / Phase 4). Use source reading only to know what to measure and match to the DS.
Skip if the prototype has ≤ 2 flows. Proceed directly to Phase 2 with all flows.
For 3+ flows, present a categorized flow list with state counts, ask "which flows and how much detail (happy path / all states)?", and wait for a reply before proceeding. Confirm the interpretation explicitly before starting Phase 2.
Do a full discovery pass against the linked library first, then map every element. Do not start building until this table exists. The default is instance, not primitive (Rule 2).
2a. Enumerate the library once, up front. Before searching per component, pull the catalog so you know what exists:
search_design_system(fileKey, includeComponents=true) with broad queries, plus
category sweeps ("input", "navigation", "feedback", "card", "badge", "avatar", "table") to
surface the full set — not just the names your code happens to use.search_design_system(..., includeVariables=true) and get_variable_defs for
color, spacing, radius, and border-width tokens. Record the keys.search_design_system / get_variable_defs. These are what body copy, labels,
and headings must bind to — not hardcoded hex + ad-hoc fontSize.2b. Match each inventory element (try in order before declaring "no match"):
search_design_system(fileKey, query="ComponentName", includeComponents=true)Card.Header)For found components: call get_context_for_code_connect to get exact variant prop names
before setting properties in Phase 4.
When a component exists but the exact variant does not: do not drop to a primitive. Instantiate the component and override the differing property per-instance (fill, text, size), then add a DS Drift annotation for the missing variant. Only elements with no matching component at all become primitives.
Build the mapping table — every row needs a build approach and drift note:
| Code component | DS match | Key | Build approach | Drift note |
|---|---|---|---|---|
<Button variant="primary"> | Button | abc123 | Import + setProperties | ✅ Clean match |
<Badge tone="success"> | Badge | ghi789 | Import + per-instance fill override | ⚠️ No success variant — override fill |
<CustomCard> | — | — | Primitives | ⚠️ No DS match — searched: Card, Panel, Tile |
<DataTable sortable> | Table | def456 | Import + setProperties | ⚠️ No sortable variant in Figma |
Also record, for each element, which text style and color/spacing/radius/border-width variables it should bind to in Phase 4. Any row with ⚠️ must get a DS Drift annotation in Phase 4. A row that says "Primitives" is only valid if 2b found nothing — not because a variant was missing.
2c. Resolve themed / runtime-remapped CSS-variable tokens — never trust the raw var().
When colors, spacing, or radii come from CSS custom properties (var(--token-…)) that a runtime
theme provider remaps — e.g. a ThemeScope / data-theme / class-based provider that changes
what --token-color-purple-100 resolves to per brand or per light/dark scheme — the raw CSS
value is not the rendered value. Reading the stylesheet alone yields the variable name or its
top-of-file default, not what the user actually sees in that themed context. This is a silent
parity killer: the most common symptom is a themed surface (a dark footer, an inverted hero)
rendering blank/white in Figma because its fill was never resolved and set.
Resolve the rendered value, then bind it — three steps, in order:
getComputedStyle / an inspect tool → background-color, color, gap,
border-radius, …) so the theme remap collapses to a concrete rgb() / px. If no running
app is available, resolve the variable chain manually through the active theme's mode, not the
:root default.search_design_system
with includeVariables=true, get_variable_defs) for a variable whose resolved value equals
it under the corresponding mode/theme. If found, bind the variable (Phase 4 §3.2) so the
node stays theme-aware — this is always preferred over a literal.Never leave a themed token unresolved (raw var() name, :root default, or an unset fill). "I
read it from the CSS" is not sufficient when a theme scope sits between the token and the pixel.
Page: "[Feature Name] — Prototype Flows"
Section: "Flow 1: [Flow Name]"
Frame: "1.1 — [State description]" ← left-to-right within a flow
Frame: "1.2 — [State description]"
Frame: "1.3a — Success"
Frame: "1.3b — Error" ← branches stacked vertically
Section: "Flow 2: [Flow Name]"
...Frame size: match the CSS-measured viewport (e.g., 390×844 mobile, 1440×900 desktop). For scrollable states, set frame height to full content height — never clip at viewport height. Add a fold marker line at the viewport height. ~200px gaps between frames, ~400px between sections.
Step 1 — Capture headlessly (Rule 0). Make sure the dev server is running (start it in the
background if needed) and resolve the route URLs from the codebase. For each route/state, call
generate_figma_design (fileKey) to get a captureId + the capture script, then run the headless
Playwright variant of that script against the LOCAL dev URL — navigate, strip CSP, inject
capture.js, window.figma.captureForDesign({...}). No open, no visible tab, no in-app
preview. Poll generate_figma_design(fileKey, captureId) until completed. Result: a fully
layered 1:1 base per state, sent browser→Figma directly.
Step 2 — Reconcile to the DS (Rule 2). Walk each captured frame and, for every element with a Phase 2 match, swap it for a DS component instance (override to match the captured pixels), bind color + number variables and text styles where the DS is published to Figma. Elements with no match stay as the captured node, flagged DS Drift. This is the cheap surgical layer — a handful of components, not the whole page. If the DS isn't in Figma at all, keep the capture as-is and flag it.
Step 3 — Assemble + annotate (Phase 5). Arrange the state frames into the flow, add arrows, and attach Dev Mode annotations.
If there's no headless browser or no dev server: stop and tell the user what's missing. Do NOT fall back to a visible tab, and do NOT hand-build from source and label it 1:1.
Placement: scan the target page with get_metadata first. If matching frames/sections exist
for this feature, insert beside them. If not, create a named section:
[Prototype] <feature name>. Never place frames at an arbitrary far-Y without reporting
coordinates and a deep-link in the Phase 6 summary.
DS component instances — see figma-patterns.md Section 3 for importComponentByKeyAsync
setProperties.Primitives — see figma-patterns.md Section 4. Use the computed measured values (Rule 0)
for all dimensions, radii, and colors.
Fixed-size square/circle containers (avatars, number badges, icon chips): set both axes
to fixed sizing — never let auto-layout hug. A hugging container collapses to the width of its
glyph, so a 32×32 avatar renders 32px tall but ~10px wide. Use primaryAxisSizingMode = 'FIXED'
and counterAxisSizingMode = 'FIXED' after resize(size, size), or skip auto-layout and center
the child manually. See figma-patterns.md Section 4.1.
DS variable + text-style binding — for every fill, radius, spacing, and border-width
where a variable key was found in Phase 2, bind it instead of hardcoding. Bind body/label/heading
text to the library text style instead of setting raw fontSize/fontName. The variables API
lives under figma.variables.* (NOT the figma global), and setBoundVariableForPaint takes a
paint and returns a new one you must reassign:
// Color fill → variable. setBoundVariableForPaint returns a NEW paint — reassign node.fills.
const colorVar = await figma.variables.importVariableByKeyAsync(colorVarKey);
let fills = node.fills;
if (fills && fills !== figma.mixed && fills.length && fills[0].type === 'SOLID') {
fills = [...fills]; // copy — assigning into the live array is a no-op
fills[0] = figma.variables.setBoundVariableForPaint(fills[0], 'color', colorVar);
node.fills = fills; // reassign — required
}
// Scalar fields (radius / border-width / spacing) → node.setBoundVariable
const radiusVar = await figma.variables.importVariableByKeyAsync(radiusVarKey);
node.setBoundVariable('cornerRadius', radiusVar); // fallback: pass radiusVar.id
const borderVar = await figma.variables.importVariableByKeyAsync(borderWidthVarKey);
node.setBoundVariable('strokeWeight', borderVar); // not a raw strokeWeight
// Typography → library text style (styles use figma.importStyleByKeyAsync, NOT the variables API)
const textStyle = await figma.importStyleByKeyAsync(textStyleKey);
await textNode.setTextStyleIdAsync(textStyle.id); // font/size/weight/lineHeight; fill stays separate⚠
figma.importVariableByKeyAsync(...)(no.variables) andnode.setBoundVariableForPaint('fills', 0, ...)THROW in the Figma MCP runtime — use the forms above. Cache imports (one per key), then bind.
Page and surface backgrounds must bind to the surface/wash color variable too — never a raw page-background hex. Fall back to raw CSS values only when Phase 2 found no DS variable or text style for that role (and note it as drift).
Annotations — attach to nodes during build, not after
Set up two annotation categories once at the start of your first use_figma call:
let interactionCat = null, dsDriftCat = null;
try {
const existing = await figma.annotations.getAnnotationCategoriesAsync();
interactionCat = existing.find(c => c.label === 'Interaction')
?? await figma.annotations.addAnnotationCategoryAsync({ label: 'Interaction', color: 'blue' });
dsDriftCat = existing.find(c => c.label === 'DS Drift')
?? await figma.annotations.addAnnotationCategoryAsync({ label: 'DS Drift', color: 'orange' });
} catch(e) { /* native API unavailable — use layer name fallback below */ }As you build each node, annotate it immediately — do not defer annotation to a separate pass. Keeping the node reference in scope is the only reliable way to attach to the right layer:
// Interaction annotation — on the node itself, right after creating it
const ctaButton = figma.createFrame(); // ...build it...
ctaButton.name = 'CTA: Submit';
ctaButton.annotations = [{
label: 'Tap → submits form; on 200 navigates to success screen; on 4xx shows inline error',
...(interactionCat ? { categoryId: interactionCat.id } : {})
}];
// DS Drift annotation — on any primitive or mismatched DS component
const customCard = figma.createFrame(); // ...build it...
customCard.name = 'Card: Goal (primitive)';
customCard.annotations = [{
label: 'DS Drift: no Card/Goal component found in library (searched: Card, Panel, Tile). DS gap for design team.',
...(dsDriftCat ? { categoryId: dsDriftCat.id } : {})
}];
// Fallback if native API failed: encode in layer name
if (!interactionCat) ctaButton.name += ' [Interaction: tap → submit form]';
if (!dsDriftCat) customCard.name += ' [DS Drift: no Card/Goal in DS]';Annotation checklist per frame:
Completeness check: before moving to the next frame, verify every row from the Phase 2 mapping table that belongs in this frame is present in the layer tree.
One frame at the top of the page:
6a. Completeness check — via get_metadata on the output, verify:
<svg> (logo, icons, decorative blobs) the output
must contain VECTOR nodes for them. A frame with 0 vectors means every inline SVG was dropped
(wrong/placeholder logo, empty footer, blob-less card art) — go back and add them via
createNodeFromSvg.Fix anything missing with a follow-up use_figma call before presenting.
6b. Code Connect (optional) — get_code_connect_suggestions → review → send_code_connect_mappings.
6c. Present to user:
When Write tools are unavailable, produce a structured markdown document using the template in
figma-patterns.md Section 12.
Instance first, primitive last. The value of this skill is not rebuilding by hand. If the DS has a component — even without the exact variant — use it with an override. Bind typography, color, spacing, radius, and border-width to DS styles and variables. A pixel-accurate frame made of primitives that shadow real components is still a failed run.
Render, then serialize — headlessly. True 1:1 comes from a headless browser rendering the code and serializing the result to Figma, not from an LLM re-deriving layout from source (lossy on any real page) and not from a visible capture (pulls the designer out of the terminal). Headless = same fidelity, invisible, terminal-native. The model's job is the DS + annotation layer on top, not reproducing the pixels by hand.
Annotate on the node, not the canvas. node.annotations = [...] is what surfaces in Dev
Mode. Floating text boxes and separate annotation frames are noise, not annotations.
Name everything. "Frame 47" is useless. "2.3a — Save success with toast" tells a reviewer exactly where they are.
Annotate flows, not tap targets. The goal is for a reviewer to read all annotations on a frame in under 30 seconds and understand the complete flow. Annotate the state transition, not the mechanism — one annotation on the amount picker row beats four identical annotations on each chip inside it.
Be explicit about DS gaps. List every primitive in the summary so the design team knows what components are missing from the DS. This turns unmatched elements from a silent failure into actionable signal.
See figma-patterns.md for Plugin API patterns — frame creation, component importing,
primitive helpers, addNoDsMatchBadge, auto-layout, text nodes, annotation setup, and the
Prototype Spec Document template. Read this before your first use_figma call.
(Write-tier clients only.)
© alima-max, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 3 other files in the repository root of alima-max/prototype-to-figma-skill.
Open the folder on GitHubat commit 6e2e1be
Prototype to Figma next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Prototype to Figma this skillalima-max/prototype-to-figma-skill | 140 | — | ~7.8k | Automated safety check: Pass | MIT | |
| Igniteui Angular Figma To AppIgniteUI/igniteui-angular | 599 | — | ~6.4k | Automated safety check: Pass | MIT | |
| Cc DesignZeroZ-lab/cc-design | 827 | — | ~2.2k | Automated safety check: Notes | None | |
| Visual Stylecalesthio/OpenMontage | 65k | — | ~1.5k | Automated safety check: Pass | AGPL-3.0 | |
| Website Design Taste Extractorsenlindesign/taste-skill | 381 | — | ~5.3k | Automated safety check: Pass | None | |
| Refero Designreferodesign/refero_skill | 295 | — | ~5.3k | Automated safety check: Pass | MIT |
IgniteUI/igniteui-angular
Builds Angular views from Figma designs with Ignite UI for Angular, supporting Indigo.Design kits, third-party kits, and plain frames.
ZeroZ-lab/cc-design
High-fidelity HTML design and prototype creation. An agent skill from ZeroZ-lab/cc-design.
calesthio/OpenMontage
Create, extract, and apply portable visual design systems via visual-style.md files.
senlindesign/taste-skill
Reverse-engineers a website's design from its URL into a Markdown and JSON pair holding concrete tokens and the trade-offs behind the look.
referodesign/refero_skill
Primary/default skill for UI design, product design, web design, landing pages, dashboards, product screens, redesigns, visual polish, frontend/CSS styling, design systems, components, responsive…
avelikiy/great_cto
Analyzes a screenshot, website or Figma file and writes a `design.md` with its token system, component inventory and reconstruction notes, or an `element.md` for one element.
Works with
Converts a working code prototype into a structured Figma file with one frame per interaction state, mapped to your design system and annotated with transitions. The skill takes a running prototype and produces a Figma file that product managers, designers and engineers can review without running any code. It has two goals: exact visual match with the rendered prototype, and a result that uses your design system, with captured elements reconciled to component instances, bound variables and text styles wherever the system is published to Figma.
Prototype to Figma fits situations like: turning a code prototype into Figma frames for design review; breaking an interaction flow into separate state-by-state frames; generating design specs from a prototype for engineering handoff; gathering asynchronous feedback from non-technical stakeholders on a prototype.
Run `npx skills add alima-max/prototype-to-figma-skill --skill prototype-to-figma -a claude-code`. Or copy the skill folder (the alima-max/prototype-to-figma-skill repository) into .claude/skills/prototype-to-figma in your project. Claude Code loads it when a task matches its description.
Run `npx skills add alima-max/prototype-to-figma-skill --skill prototype-to-figma -a codex`. Or copy the skill folder (the alima-max/prototype-to-figma-skill repository) into .agents/skills/prototype-to-figma in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add alima-max/prototype-to-figma-skill --skill prototype-to-figma -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/prototype-to-figma, .gemini/skills/prototype-to-figma, .github/skills/prototype-to-figma and .opencode/skills/prototype-to-figma in your project.
Going by SKILL.md and its folder, Prototype to Figma needs the command-line tools its instructions call (npx). Our summary lists: A Figma MCP client connected to your Figma file; Playwright with headless Chrome for rendering.
SKILL.md contains no URLs. Its commands use npx, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Prototype to Figma is published under the MIT licence (from the LICENSE file in the skill folder). It allows redistribution, so the full SKILL.md is shown on this page.
About 7.8k tokens (SKILL.md is roughly 31k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Prototype to Figma: Igniteui Angular Figma To App (IgniteUI/igniteui-angular, 599 stars), Cc Design (ZeroZ-lab/cc-design, 827 stars), Visual Style (calesthio/OpenMontage, 65k stars) and Website Design Taste Extractor (senlindesign/taste-skill, 381 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
alima-max (a GitHub user) maintains it in alima-max/prototype-to-figma-skill, which has 140 GitHub stars. The repository was last updated on July 28, 2026.
Source: alima-max/prototype-to-figma-skill on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.