figma-design-extract — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited figma-design-extract (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Read a Figma node into a design-spec table of exact values mapped to your codebase, before writing any component code. The table is both your build contract and the input to the companion `design-fidelity-verify` skill, which proves the running app matches it.
This skill is the design→code direction (read Figma, produce a spec). It is not a code→Figma generator.
Screenshot-as-truth. A model reads a Figma screenshot as "button, top-right" but cannot see that the radius is 8 not 12, the weight is 500 not 600, or the gap is 12 not 8. A screenshot is a visual reference only. Exact values come from Figma's structured data — variables and metadata — not from pixels. The bar is fidelity to the design's decisions — the right token — not literal pixel coordinates. Skip this and the design drifts the moment you start typing.
Trigger phrases: "implement this Figma screen/component", "build this design", "extract the Figma values", "get the tokens/spacing/colors from Figma", "match the Figma", or a figma.com/design/...node-id=... URL shared to build from.
Scope: any frontend repo (web or mobile). Backend/API repos have no UI to build.
Prerequisite: the Figma MCP server (Dev Mode MCP) connected, so get_variable_defs, get_metadata, get_design_context, and get_screenshot are available.
Get the node from the URL the designer shared, or from your issue tracker / design handoff. The node id is the node-id=NNNN-MMMM part of a Figma URL (the - becomes : in API calls, e.g. 1234:5678).
get_design_context first; if it returns "node not found", search by a stable numeric prefix rather than the frame name (names get renamed and double-spaced).get_metadata on a 40-frame section blows the token budget. Always pass the specific node id.get_design_context(nodeId)Use it for structure only: auto-layout → flex direction / gap, hierarchy, where component boundaries are. Do not copy its absolute pixel positions or inlined values — treat those as hints and confirm them against variables/metadata.
get_design_context. Choose by your setup:disableCodeConnect: true to skip that noise and get the generated structure directly. A reasonable default when no mappings exist; don't stop to set Code Connect up mid-task.get_variable_defs(nodeId) ← the source of truthThis answers "are we even getting the real styles?". It returns the exact color / spacing / radius / typography tokens bound in the selection. For every value:
var(--primary/500) to whatever your repo calls it.get_metadata for the raw number, and flag it for the designer.docs/design-drift.md) and keep using the token name — never hardcode the Figma value to "fix" it. The token package is corrected separately.get_metadata(nodeId) (scoped)Two uses: exact sizes/positions not covered by a variable (fixed dimensions, one-off gaps, icon box sizes), and a fallback when get_design_context is truncated — responses are capped (~20kb/call), so on a large node, take the node map from get_metadata then re-fetch only the child node(s) you need. Keep it node-scoped.
get_screenshot(nodeId)Composition, states, iconography, what-goes-where. Never measure from it. It exists to catch "you built the wrong thing", not "you built it 4px off".
get_variable_defs only returns values bound to a variable. Anything unbound — many gradients, one-off fills — won't appear there. For those, read node.fills via the Figma Plugin API (use_figma) for the authoritative stops/values, and flag the missing binding as a design smell.
Map each Figma component to an existing primitive in your repo before building anything new:
get_design_context can return exact import paths automatically; if not, map manually and treat Code Connect as a future automation, not a blocker.One row per element×property. This is the deliverable — keep it in your working notes; it drives both implementation and verification.
element | property | Figma exact value | repo token / class | source component
-----------------+---------------+------------------------+---------------------------+------------------
Card container | bg | var(--surface/0) | <your white-surface token>| <Card>
Card container | radius | 12 | <your rounded-lg token> | <Card>
Card container | padding | 16 | <your space-4 token> | <Card>
Title | font/size/wt | Heading/M 18 / 600 | <your title-m token> | <Text>
Row gap | gap | 8 | <your space-2 token> | (auto-layout)
CTA | bg | var(--primary/500) | <your primary-500 token> | <Button primary>
CTA | radius | 8 | <your rounded-md token> | <Button>Fill the repo token / class column with your system's names (see below). The point is that every cell on the right is a token reference, not a hardcoded literal.
The mechanism is identical everywhere; only the token syntax changes. These are examples to adapt — use whatever your repo already uses:
var(--primary/500) → bg-primary-500; radius 12 → rounded-xl; gap 8 → gap-2. For light/dark, lean on your config's dark variant (bg-white dark:bg-neutral-900).backgroundColor="primary500", borderRadius="l", spacing="s".background: var(--primary-500), border-radius: var(--radius-md).If your repo has none of these, that's the real finding — surface it; don't invent ad-hoc values.
Adapt to your stack: wherever this skill names Tailwind/NativeWind/Restyle/CSS-vars, substitute your own design-token system. The rule that never changes: a value bound to a Figma variable maps to a named token in your code, never to a hardcoded literal.
Export SVGs/icons from Figma, then optimize them (e.g. SVGO) before committing — never commit raw editor exports. Ensure an explicit viewBox.
"Never hardcode" is a rule the model can forget mid-build. Back it with a deterministic check that doesn't depend on the model's discipline: after building, grep the diff for raw values that should be tokens, and fail if any slip through.
# Flag raw hex / rgb / px / 3-digit font-weight literals in added lines.
git diff --unified=0 | grep -nE '^\+[^+]' \
| grep -iE '#[0-9a-f]{3,8}\b|rgba?\(|[^a-z-][0-9]+px|font-weight:\s*[0-9]{3}' \
&& echo "raw values found — map them to tokens" || echo "clean"Tune the pattern to your stack and allow tokenized exceptions. This pairs with the drift log: a bound value that mismatches goes to the drift log; an unbound raw literal gets tokenized or flagged. Run it in CI to make the guardrail a real gate, not a hope.
The spec table is the input to `design-fidelity-verify`: build the component from the table, then run that skill to prove — by measuring rendered values, not by glancing — that the running app matches every row.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.