A spec an engineer can build from 7 min live
The test of a handoff is not whether it looks thorough. It is whether an engineer who has never spoken to you can build the screen correctly and know when they are done. That means the spec names token names rather than hex values, so a colour change later does not silently detach; component and variant names from the real system, not descriptions of appearance; spacing in scale steps, not measured pixels; every state enumerated - empty, loading, partial, error, offline and both string extremes; interaction and focus behaviour, including keyboard order; responsive rules stated as breakpoint intent rather than pixel-perfect mocks at three widths; and accessibility written as acceptance criteria - contrast pairs, target sizes, reading order, focus visibility. The first four are usually there. The last four are what go missing, and they are the ones that come back as bugs.
LiveWhy token names beat hex values, every time4 min▶
A hex value in a handoff note is a fact about today. A token name is an instruction about forever. The difference shows up six months later when the surface colour changes: everything referencing colour.surface.raised moves, and everything that was sampled by eye and typed in by hand stays behind. Those hand-typed values are invisible in a screenshot and invisible in a Figma inspection - the only way to find them is to look at the code or ask.
- Same for spacing. "24px" is a measurement. "space-3" is a decision that stays consistent when the scale is retuned.
- Same for type. "20px semibold" is a description. "text.title.m" is the third rung of the 1.25 scale from b6 and cannot drift off it.
- Same for components. "the grey button" is an appearance. "Button/secondary" is a contract, and if the design needs something the variant cannot do, that is a system conversation rather than a one-off override.
The habit to build: when you cannot name a token for something you drew, you have either found a genuine gap in the system or drawn something off-system. Both are worth knowing before an engineer discovers it for you.
Self-studyTwo handoff notes for the same card4 min read▶
Same Cadence shared-summary card. The first note describes how it looks. The second one can be built and accepted.
"Summary card with a light plum background and rounded corners, roughly 24px of padding. Title in a slightly larger semibold, then the AI note in small grey underneath, then the body. Share button bottom right in the brand colour. Should look good on mobile too."
"Component: Card/summary. Surface colour.surface.raised, radius radius-m, padding space-4 all sides, internal stack gap space-3. Title: text.title.m, colour.text.primary, 2 lines max then ellipsis. Disclosure line: text.body.s, colour.text.secondary, sits ABOVE the body in both DOM and visual order. Body: text.body.m, colour.text.primary. Action: Button/primary, label "Share summary", 44x44 minimum hit target, sits after the body in reading order. States required: empty (no summaries), loading (skeleton, no spinner), partial (transcript still processing - show what exists plus the low-confidence banner), error (send failed - message plus retry), offline (read-only, Share disabled with reason). String extremes: title at 4 and at 90 characters, both drawn. Responsive intent: below the medium breakpoint the action becomes full-width and moves below the body, and the disclosure line stays above the body. Acceptance criteria: every text and background pair passes WCAG 2.2 SC 1.4.3 at its computed size and weight; the button boundary passes SC 1.4.11 at 3:1; every interactive target meets SC 2.5.8 at 24x24 CSS px minimum; focus is visible on every interactive element; tab order is title, disclosure, body links, Share."
The second note is four times longer and roughly forty times cheaper, because every line in it is either buildable or checkable. Notice that nothing in it is a picture. A mock shows one state at one width - the spec is what covers the other fifteen.
How AI actually reaches your design system 8 min live
"AI can read our design system" is a sentence that hides five different mechanisms with five different gates. Knowing which one you are on decides whether token automation is realistic for your team or a demo you saw once. The single most important constraint: the Figma variables REST API is Enterprise-only - you must have a Full seat in an Enterprise org - so below Enterprise the selection-scoped MCP call is the only route to your tokens. The second most important: Figma Code Connect's framework-specific parsers lose updates and support from 2026-08-17, after which template files are the only maintained path. Both are dates and seat tiers, not opinions, so put them in your plan rather than your hopes.
| Route | What it carries | Gate | Failure mode |
|---|---|---|---|
| Figma Code Connect | The bridge between your codebase and Dev Mode, so a Figma component maps to the real component in code | Dev or Full seat on Organization or Enterprise | Framework-specific parsers lose updates and support from 2026-08-17. After that, template files are the only maintained path - plan the migration, do not discover it |
| Figma MCP server | Remote https://mcp.figma.com/mcp or desktop http://127.0.0.1:3845/mcp. get_design_context (which replaced get_code), get_variable_defs for the variables and styles in the selection, get_code_connect_map, get_code_connect_suggestions, and remote-only search_design_system |
Figma seat plus an MCP-capable client | get_variable_defs is scoped to the selection. It answers "what tokens are in this frame", never "what is our whole token set", so it is a handoff tool rather than a sync |
| Figma variables REST API | Programmatic access to variables - the route people assume exists when they plan token automation | Enterprise only - a Full seat in an Enterprise org | Below Enterprise it simply is not available, and the selection-scoped MCP call is your only token route. This is the constraint that kills most token-automation plans |
| v0 (Vercel) | Production Next.js / React / TypeScript / Tailwind / shadcn code. Design Systems 2.0 stores your system as a skill naming where the source lives and which components, props and tokens are safe to use, written to a v0.json |
Paid plan for real use - Free is limited, and Figma import needs a paid plan | Once GitHub is connected, in Vercel's own words "it becomes the source of truth for your project". That is a genuine handoff, and it means the design file stops being the source of truth |
| Figma Make | A working prototype, a downloadable code zip, a one-way GitHub push, and paste-back into Figma Design | Code editing needs a Full seat on a paid plan | Both bridges are lossy. The GitHub push is one-way and edits made in GitHub get overwritten on the next push, and pasted-back output produces layers that "aren't automatically tied to your design system" |
LiveChoosing a route without lying to yourself4 min▶
Three honest questions, in order, and the answer falls out.
- Are you on Enterprise? If yes, the variables REST API is available and real token automation is on the table. If no, stop planning a sync. You are on selection-scoped
get_variable_defsthrough MCP, which is excellent for handing one frame's tokens to an engineer or an assistant and useless as a pipeline. - Does a real component library already exist in code? If yes, Code Connect is the highest-value route because it makes Dev Mode point at the actual component - and you now have the 2026-08-17 parser deadline on your roadmap. If no code library exists, Code Connect has nothing to connect to and v0's Design Systems 2.0 skill is the more realistic way to tell a generator what is safe to use.
- Is the output going to production or to a conversation? v0 with GitHub connected is a production handoff and the repo becomes the source of truth. Figma Make is in-Figma prototyping with two lossy bridges, so treat its output as an argument, not an artifact.
The common mistake is picking a route by which demo was most impressive. Pick by seat tier and by whether code already exists, then design your handoff around what that route can actually carry.
Self-studyWhat "AI reads our system" does not mean3 min read▶
Every one of these routes moves a description of your system, and a description is not enforcement. Three things stay yours:
- Nothing here prevents an off-system value. A generator handed your token list can still emit a hand-typed colour, and the result looks identical in a screenshot. The only way to catch it is to inspect the built code or measure the built screen, which is Part 3.
- Selection scope is a real limit, not a beta.
get_variable_defsreturning the variables and styles in a selection is the design of the tool. Handing it a frame with three tokens and concluding your system has three tokens is a category error people make weekly. - Source-of-truth is a decision, and one of these routes makes it for you. When v0 has GitHub connected and the repo is the source of truth, your Figma file becomes documentation. That can be the right call - it just has to be a call, made out loud, rather than something you notice a month later.
Reviewing what actually shipped 6 min live
The design-to-shipped gap is the drain every previous session empties into. A mock is a claim; the built screen is the product. So run the five checks from b5 on the built screen, in a browser, not on the file you approved - because computed values are what users get. The rounding, the inherited line-height, the token that was almost right, the padding that got typed in by hand: none of those exist in the mock and all of them exist in the browser.
LiveWhat to look at in the inspector4 min▶
You do not need to write code for this. Open the built screen, open the browser inspector, and read four things - all of them computed, all of them arguable-free.
- Real contrast ratios. Not the pair you specified, the pair that rendered. Opacity, overlays, inherited colours and a background image behind text all change the answer. Check at the computed font size and weight, because size and weight decide whether you owe 4.5:1 or 3:1.
- Real spacing values. Read the computed padding, margin and gap. Anything not on your scale step is a defect even if it looks fine, because it means a value was typed rather than referenced.
- Real font sizes. Count the distinct computed sizes on the page. If your scale has four rungs and the built screen has seven values, three of them came from somewhere you did not decide.
- Focus order. Put the mouse away and press Tab through the whole screen. Watch where the focus ring goes and whether you can always see it. This is the check that finds reading-order bugs the eye cannot.
Self-studyFiling a difference as a defect, not a preference3 min read▶
The reason design feedback gets deprioritised is that most of it arrives as taste. Rewrite it as a failed criterion and it enters the same queue as every other bug. The shape:
- Where - the screen, the component, the state. "Shared summary card, offline state."
- Expected, in spec language - "disclosure line at text.body.s in colour.text.secondary, above the body in DOM order."
- Actual, as a measurement - "13px, computed #B9A9B6 on #FFFFFF, ratio 2.1:1, and it comes after the body in the DOM."
- The criterion it fails - "WCAG 2.2 SC 1.4.3 requires 4.5:1 at this size and weight." Cite the acceptance criterion you wrote in Part 1, which is exactly why you wrote it.
Two habits make this land. Separate the measurable list from the judgement list and send them as two different messages - a defect list gets fixed, a taste list gets discussed, and mixing them turns the whole thing into a discussion. And never file a difference you did not measure, because one wrong number in a list of ten costs you the other nine.
Self-studyUsing an AI reviewer here, honestly3 min read▶
An assistant looking at a screenshot or a chunk of code is genuinely useful at this step and genuinely unreliable in specific, predictable ways. Use it as a suspect generator, never as the measurement.
- It is good at spotting missing states, naming what looks off-system, drafting the defect list from your notes, and reminding you which criteria you have not checked yet.
- It hallucinates ratios. Asked for a contrast ratio it will produce a confident number that is often wrong. Ratios come from the inspector or a contrast tool, and this is the same failure mode you saw in b5.
- It cannot see provenance. Looking at a rendered screen it has no way to know whether a colour came from a token or was typed in by hand. Those look identical, and the difference is the entire point of the handoff.
- It reads the mock as reality. Hand it a design file export and it reports on the design, not the build. The whole argument of this session is that those are different documents.
So the working split: the assistant proposes the list of things to check, you measure, and only measured items get filed.
Spec the Cadence summary, then verify it ★ 22 min · everyone runs it
Two halves. First you write the shared-summary spec using the anatomy from Part 1 - tokens, components, spacing steps, states, interaction, responsive intent, acceptance criteria. Then you verify a built result the way Part 3 says to. The lab below runs with all five levers on, which is 100 out of 100: this is what acceptance looks like - 100 with nothing measurably broken. Every value in that score is computed from the rendered screen, which is precisely the standard you are asking your engineer to hit.
Write the header. Component name, variant, surface token, radius token, padding and gap in scale steps. If you cannot name a token, mark it as a system gap now rather than shipping an override.
Enumerate the states. Empty, loading, partial, error, offline, plus the longest and shortest plausible strings from b8. Six rows minimum. This is the section that is always missing.
Write the interaction and responsive rules. Tab order, focus visibility, what happens on escape. Responsive stated as intent - what reflows, what moves, what stays - rather than three exact mocks.
Write the acceptance criteria. Contrast pairs by criterion number, minimum target size, reading order matching visual order, focus visible everywhere. These are the lines you will quote when you file defects.
Now verify. Run the lab with all five levers on, read the rows at 100, then Tab through the rendered screen and check the focus ring. Anything you cannot see is a defect you can file with a criterion attached.
Try it yourself - this week ◐ 35-45 min total
- Write the full Cadence shared-summary spec using the Part 1 anatomy. Enumerate all six states and both string extremes, and write the accessibility section as criteria with success-criterion numbers, not as a note asking someone to be careful.
- Find out which route your team is actually on. Check your Figma plan and seat: is the variables REST API available to you, or are you on selection-scoped
get_variable_defsthrough MCP? Then check whether anything you own depends on Code Connect's framework-specific parsers before 2026-08-17. - Open one screen you shipped in a browser inspector and measure four things: worst real contrast ratio, every computed spacing value that is off your scale, the count of distinct font sizes, and the Tab order. Write the numbers down.
- Turn that measurement list into a defect list in the four-part shape - where, expected in spec language, actual as a measurement, criterion failed - and keep the taste items in a separate note. Bring both to b10.
Official sources covered
This session covers handoff quality and the documented behaviour of the routes AI takes into a design system - not how to build the component, which stays with engineering. Seat tiers, tool names and deadlines were read from official documentation and are the kind of thing that moves, so re-check before you build a plan on them. This page covers:
Three questions before you go 🎯 ◐ 90 seconds
1 · Your team is on a Figma Professional plan and wants to automate token sync. What is actually available to you?
The variables REST API requires a Full seat in an Enterprise org, so below Enterprise the selection-scoped MCP call is the only token route - excellent for handing one frame's tokens over, useless as a pipeline. Worth pairing with the other date in this session: Code Connect's framework-specific parsers lose updates and support from 2026-08-17, after which template files are the only maintained path.
2 · Why run the five checks on the built screen rather than on the approved mock?
The mock is a claim about one state at one width using drawn values. The browser reports what rendered: inherited line-heights, overlays and opacity changing a contrast pair, a padding that was typed rather than referenced. A screenshot cannot distinguish a token from a hand-typed value that happens to match, which is the whole reason acceptance happens in the browser.
3 · You ask an AI reviewer to check the built screen. What must you not take from it?
It flags suspects well and drafts lists well. It hallucinates ratios with total confidence, and it cannot see provenance at all - a token and a hand-typed value are identical on a rendered screen. So the assistant proposes what to check, you measure it, and only measured items get filed. One wrong number costs you the credibility of the whole list.