Your Figma is half a system and your app isn't live yet
A real case: a Figma file with a few variables, no text styles and fonts set by hand, and a widget that only runs on localhost. How both become one Flash system and a style guide.
Two sources, neither complete
This one comes from a real project. A designer who also writes the code was building an embeddable widget, the kind that sits inside other companies' websites. The design lived in Figma. The product lived on localhost:5173, not deployed anywhere yet. Both were good, and neither was a design system.
The Figma file had a dozen colour variables in a single mode, a colour style for each customer's brand, a few number variables for corners and sizes, and components. It had no text styles at all: every font was set by hand on the layers. The code had a stylesheet with a dozen custom properties, a few dozen hex values typed straight into rules, and a system font stack that was not the font in Figma. The widget renders inside a Shadow DOM, so its whole stylesheet was a CSS string inside a TypeScript file, with the properties declared on the widget's own root class:
export const WIDGET_CSS = /* css */ `
.wd-root {
--wd-ink: #1c2430;
--wd-accent: #2f6fde;
--wd-surface: #ffffff;
--wd-radius: 12px;
font-family: system-ui, sans-serif;
}
`;
Other developers were about to join. They needed one place that says which colours and fonts exist, what each is for, and the variable to paste.
| Figma | The code | |
|---|---|---|
| Colours | Colour variables in one mode, plus customer colour styles | Custom properties plus raw hex values |
| Type | Fonts set on each text layer, no text styles | One system font stack |
| Corners and sizes | Number variables | One radius property |
| Where it runs | figma.com | Only on the developer's machine |
What you do, in order
The whole thing takes an afternoon. Each step below has its own section.
- Connect Genome to the repo and run
scan_workspace. The code becomes the system. - Pair the Flash plugin in Figma and push. The file arrives as a card on [[Sync > Review]].
- On the card, take the stored token where a colour is a duplicate, keep or take each changed value, then Apply.
- Make the calls neither source could make: the fonts, the radius scale, the names. Publish.
- Set the export to
:hostand runpull_from_webin the repo. - Click Build Figma file in the plugin.
- Turn on the share link and send it to the team.
Start from the code, even when it lives in TypeScript
Start with what actually runs. Flash's servers cannot open localhost, and pasting it into the Website field says so: "that's on your computer, scan it with Genome from your editor". Genome is Flash's MCP server for your repo, and it runs on your machine, so it can read the folder.
Connect it once. In the menu next to Publish, open [[Connect a codebase > MCP server]], click Create access token, and copy the Setup prompt for your editor. Then ask your agent to run scan_workspace on the project.
The scan reads the stylesheets in the folder (up to 60 files, skipping demos, tests and build output), the CSS inside /* css */ and css template literals in script files, Tailwind configs and theme modules, theme files first. Flash parses all of it in one pass, so a var() in one file resolves against the file that defines it. For the widget that meant every colour, the radius, the shadow, the spacing and the root font stack, which arrives as font-body.
One more thing happens. When nearly every name shares a first segment, like wd-ink and wd-accent, Flash treats it as a namespace. The tokens become ink and accent, and wd is saved as the system's CSS variable prefix, so every export writes --wd-ink again and the code does not change a line.
Bring in Figma, whatever shape it is in
In [[Sync > Sources]], click Generate pairing code. In Figma, run the Flash plugin, click Pair with Flash and paste the code. Then open the Figma → Flash tab.
The push button names what the file will send, and the line above it lists it. For this file the button read Push variables to Flash, and the line read "Sends this file's variables, color styles and page fonts to Flash, where you review them before anything is applied." A file with styles and no variables gets Push styles to Flash. A file with neither gets Push page colors and fonts to Flash, which sends the colours and fonts used most on the canvas.
What Flash does with a file like this one:
| In the file | In Flash |
|---|---|
| Colour variables in one mode | One value for every theme, light and dark |
| A colour style per customer | One token each, named by its full path, so eight "Accent" styles stay eight tokens |
| Number variables named radius or space | Corner radius and spacing |
| Number variables named size | Left out, and the plugin says so: "4 size variables were left out: Flash has no size tokens yet." |
| Fonts set on the layers, no text styles | font-heading from the family used at the largest sizes, font-body from the one used most at reading sizes, font-mono from a family whose name says Mono |
If you would rather not open the plugin, import the file by URL from the Figma import. It reads the style values, values a library style from a layer that uses it, and reads the fonts off the canvas the same way when the file has no text styles. Library styles no layer in the file uses cannot be read from the file, so the plugin is the better choice for a file built on a team library.
Either way, nothing is applied. The push waits under [[Sync > Review]].
Same colour, two names
This is where the two sources meet, and where they disagree. The code calls a colour brand-night; Figma calls the same colour night. If you started from Figma and scan the code second, ask for scan_workspace with merge, and the code arrives as its own card, labelled with the folder it came from.
The review card says when an incoming colour is one the system already has. Next to the new row it shows the stored swatch and Same color as brand-night, with Use brand-night instead. It also catches a value typed by hand a step off the design file's, as Close to surface. Colours that are only similar on purpose, a raised surface beside the text colour, are left alone. Click Use brand-night instead and the duplicate stays out, in the light and dark themes at once.
Any value that would replace a stored one is your call. The row offers Keep with the stored value: Keep Inter for a font, Keep #2f6fde for a colour. A skipped row dims and says what happens, and Take the new one undoes it.
Click Apply when the card reads right. Nothing is deleted. Tokens the push does not mention stay exactly as they are, including any saved while the card was waiting. If someone changed a token in Flash after the push, the card says "Edited in Flash after this push. Flash's value stays." before you apply.
Then make the calls neither source could make for you. Pick the fonts. Collapse a radius list like 6, 8, 10, 11 and 12 into three steps. Give colours names that say what they are for. Publish.
Back into the code: :host, not :root
A widget in a Shadow DOM cannot rely on variables declared on the host page's :root. They would leak into the page and drift with it. In [[Export > Code package]], set Declare variables on to :host (the Use :host button does it), next to the CSS variable prefix you already have. Copy code follows the same two settings.
Now ask the agent to run pull_from_web. It writes the tokens file with every variable on :host and the wd prefix, ready to adopt into the shadow root beside your own stylesheet. Themes switch with data-theme on the host element. Then run check_violations on the stylesheet. It lists every raw hex still typed into a rule, and suggest_token names the token to use for each one.
Back into Figma
In the plugin's Flash → Figma tab, click Build Figma file. You get the colour variables with Light and Dark modes, and text styles bound to the font variables. Your existing components keep their hard-coded fills until you point them at the new variables. Flash builds the variables; it does not rebind a file it did not draw.
The style guide your team actually opens
In [[Sync > Agents]], turn on the Live sync link with Enable link. The link opens a page anyone on the team can read without an account: colours with what each is for and its CSS variable to copy, every font with a specimen and its role (headings, body or code), the type scale, radius, spacing and shadows. Save as PDF prints it on white for whoever wants paper.
Developers who work with an agent connect it over MCP the same way you did. Their agent reads the same tokens and lints against them, so a new screen starts on the system instead of drifting from it.
When something goes wrong
| What you see | What it means | What to do |
|---|---|---|
| "localhost:5173 · that's on your computer, scan it with Genome from your editor" | Flash's servers cannot reach your machine | Run scan_workspace through Genome |
| The scan finds no tokens | The stylesheet sits in a demo or test folder, which the scan skips, or the theme is a JavaScript object in a file not named like theme.ts | Move the variables into the app's own stylesheet or a tokens.css |
| "4 size variables were left out: Flash has no size tokens yet." | Flash has radius and spacing, not component sizes | Keep sizes in the code, or rename a variable that is really spacing |
| The push button says Push page colors and fonts to Flash | The file has no variables and no styles | Fine for a first pass; name the colours as styles if you want their names to come across |
Tokens arrive as wd-ink next to ink | The system's CSS variable prefix is not wd | Set the prefix, then scan again, or take Use ink instead on the card |
| The variables do nothing inside the widget | They were exported on :root | Set Declare variables on to :host and pull again |