Skip to main content

figma-shared-design

Project-specific facts for reading the "Firefox_for_Developers" Figma file — the file key, Home page node IDs and the light/dark twin offset, how to get dark-mode token values, where variable bindings really come from, the traps in get_design_context / get_variable_defs / spilled MCP output, and what to do when the Figma server is unreachable (stop, don't guess). Load this alongside figma-design-to-code whenever a task involves implementing, measuring, or checking anything against the Figma design, or adding a color token that needs a dark value.

Source facts

Repository
mozilla/webdevs.firefox.com
Last source activity
September 16, 2026 at 14:46
Detected SKILL.md language
English
Stars
1
Forks
1

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
figma-shared-design
description
Project-specific facts for reading the "Firefox_for_Developers" Figma file — the file key, Home page node IDs and the light/dark twin offset, how to get dark-mode token values, where variable bindings really come from, the traps in get_design_context / get_variable_defs / spilled MCP output, and what to do when the Figma server is unreachable (stop, don't guess). Load this alongside figma-design-to-code whenever a task involves implementing, measuring, or checking anything against the Figma design, or adding a color token that needs a dark value.
# Working with the Firefox_for_Developers file Load the `figma-design-to-code` skill before calling `get_design_context`. This skill adds the project-specific detail that skill has no way to know. ## If you cannot reach Figma, stop **No Figma access means no answer. Stop and say so — do not substitute a guess.** The server needs OAuth and a non-interactive session cannot run that flow, so the failure is usually "the `figma` MCP server is not authorized" rather than a missing node. Report that the task is blocked, say it needs authorizing via `claude mcp` or `/mcp` in an interactive session, and end the turn there. This applies whenever the design is the source of truth for the answer: implementing a frame, measuring spacing, checking something against the design, or getting a dark-mode value. Finish any genuinely independent part of the request first, then stop on the part that needs Figma. What not to do instead, all of which has happened: - Don't reason from the code to a cause that sounds plausible and fix that. A defect you can argue for from the CSS alone is not evidence about what the design specifies, and "the columns are inconsistent with each other" does not establish which one is wrong. - Don't ship the change with a caveat attached. A hedged guess still lands in the file, still has to be reviewed, and is harder to spot than no change at all. The caveat does not make it safe. - Don't derive the value from tokens, type metrics or a screenshot and present the arithmetic as a measurement. Deriving a number is not reading one. - Don't treat a browser screenshot as a substitute. It shows what the code does, never what the design asks for, so it cannot settle a mismatch between them. A wrong value that looks measured is worse than an unanswered question: it reads as verified to the next person, and the reasoning that produced it is persuasive enough to survive review. "I could not check this" is the correct deliverable when you could not check it. - File key: `JFIeIEWeVOsoEZzMFKupmh` — the `Firefox_for_Developers` file, at `https://www.figma.com/design/JFIeIEWeVOsoEZzMFKupmh/Firefox_for_Developers`. The light Home page is node `42:1742`, the dark equivalent `42:3623`. Node `42:1079` is the whole "Final Pages" canvas and is too large to fetch in one call — target individual frames. Its light and dark twins are the same frame offset by roughly 11000 in `y`, so a light frame at `y=0` pairs with a dark one at `y≈10988`. - **When an oversized MCP result is spilled to a file, it is a JSON array of `{type, text}` — not the XML you would have seen inline.** Every quote in it is backslash-escaped, so grepping for `name="Forms"` matches nothing and the frame looks absent when it is right there. Don't conclude from an empty grep that the node doesn't exist. Parse it rather than pattern-matching the raw bytes: ```bash python3 -c 'import json,sys; print(json.load(open(sys.argv[1]))[0]["text"])' "$F" | grep 'name="Forms"' ``` The same goes for any tool output saved to disk — check whether you are reading the payload or its JSON encoding before trusting a negative result. - Returned React/Tailwind is a _reference_. Translate it into Astro with tokens; never paste it, and never install Tailwind. - The generated code uses absolute positioning. Rebuild layouts properly with grid rather than transcribing offsets, and expect small height differences from the Figma frame as a result. - **A component's own node says nothing about where it sits on the page.** `get_design_context` on an instance returns it in isolation, so the margins around it are simply absent from the output — and absent reads as zero, not as unknown. Before styling a component's outer spacing, call `get_metadata` on the parent frame and derive the offsets from the child's `x`/`y`/`width` against the parent's width. On the 1440-wide Home frame the Header instance is at `x=16, y=20, width=1408`: a 16 page gutter and 20 above the header, neither of which appears anywhere in the Header node itself. - The gutter belongs inside the page cap, not outside it. `.wrapper` is capped at `--page-max-width` (90rem) so `--gutter` is carved out of it, leaving `--content-max-width` (88rem). Capping at 88rem _and_ padding would inset the content twice. - If a measured value has no token, that is a signal, not a rounding problem. The spacing scale is 0/8/12/16/24/32/40/80, so a 20 is positional — write the literal `1.25rem` with a comment. Never snap to the nearest token to make a value look tokenised. - **A component's variable bindings come from its component set, not from a page that happens to use it.** The Buttons set (`43:6818`) binds the mode-dependent Purple / Dark Purple / Midnight Purple, so button fills shift with the color scheme; the dark Home frame separately binds `Purple Fixed` for unrelated artwork, and reading that as the button's color is how the styles ended up wrongly pinned to one palette. - `get_variable_defs` resolves variables in **one** mode — whichever the queried node sits in — and the output gives no hint which. Light and dark values therefore look indistinguishable in isolation: call it on both twins and diff them before deciding a value is mode-independent. - Download image and SVG assets into `src/assets/` and commit them. Figma's asset URLs expire after about 7 days. - Icons and logos exported from Figma may have hardcoded fills. Swap them for `currentColor` so they follow the color scheme — the Firefox wordmark shipped with the light-mode heading color baked in. ## Color tokens Get dark values from the dark Home panel (node `42:3623`) via `get_variable_defs`. Never invent them. See "Design tokens" in `AGENTS.md` for how those values are then written — every color token uses `light-dark()`, and there is no parallel palette of fixed colors.
View on GitHub