I skipped design tokens in 2020. The migration took 6 months in 2023
I started a design system with hardcoded values to ship faster. Three years later the move to semantic tokens took more than six months. What I would do on day one.

In mid-2020 I joined a B2B/B2C SaaS team as the only product designer. The UI kit in Figma had little in common with production. I started with an audit: went through the product screen by screen and collected the most used controls in one Figma file, with screenshots and notes.
The audit found up to 3 variations of the same control, hover, focus and error states written separately for each section, and hardcoded CSS colors that blocked any dark mode.

Why I started without tokens
I was the only designer and the product kept shipping. A design system that stops releases for a quarter does not get built, so I built components inside live feature work, and every new feature became a pilot for them.
Tokens would have slowed the first version. I postponed them on purpose and kept hardcoded values, knowing it was design debt. The system reached production faster, and I took the bill for later.
Where the debt showed up
The first sign came in 2021. The product blue lived in code as 3 slightly different values: #2F5BD8, #3A63E0 and #2A52C9. Nobody noticed until a customer asked for a dark mode demo. I changed the primary color in the Figma styles by hand and sent the frontend lead a list of places to fix. There were about 140 of them, and 3 releases later a few buttons were still blue the old way.
Then I estimated the migration to Variables at 2 months. It took more than 6, because every component had to be remapped from a raw value to a role by hand, and every remap needed a check in code.

The bill: 2023
In 2023 Figma introduced Variables. I rebuilt our components from scratch and mapped out 300+ variables, which became version 2.0 of the system. I ran workshops with the frontend lead to match our token structure to the updated stack.
The main change was a semantic layer. Components stopped referencing a primitive like blue-500. They reference a role, for example button-color/primary/default, and the role resolves to a base value like blue-800. Dark mode and white-labeling take a few clicks.


The migration took more than six months. We paired it with a visual refresh of the user dashboard, so I also redesigned navigation and moved the sidebars outside the main canvas, and the token work and the redesign grew into one project.
What I got for it:
- Dark mode became possible. It is technically complete and not rolled out yet.
- A style change goes through the whole product from Figma variables.
- Design and engineering use the same names.
- Code reads without a manual:
button-color/primary/defaultsays what it is.
What I would do on day one
In the retrospective of the case I wrote that I would implement tokens from the start. I still think so. AI tools could also have shortened the migration a lot.
If you have the same constraint, a solo designer and live releases, here is the minimum I would set up before the first component.
- Name styles by role from the first day:
text-primaryandsurface-raisedinstead ofgray-900andgray-100. A role you name today is a token you do not have to invent later. - Bind components to roles only. A primitive inside a component is a bug.
- Keep raw values in one place: one set of colors, one spacing scale, one radius list. In my system the spacing base is a 4px grid for components and 8px for layout blocks, and colors are 5 semantic groups with 10 shades each.
- Write down the trigger. Debt without a date does not get paid. Mine was the Variables release. Yours can be a second brand, a dark mode request or a team of three designers instead of one.
- Keep the migration separate from the redesign. I paired them and the project doubled in length. If the visual refresh cannot wait, plan two releases with two sets of acceptance criteria.
- Run a linter once the team grows. Past 200 components, hunting for detached styles by hand took hours every two weeks. I built AxoLinter, a Figma plugin that flags non-token values and shows token coverage as a percentage. How it works is in the AxoLinter project.

Postponing tokens was the right call for a solo designer with live releases. The interest was 6 months of migration and a partial redesign, so today I would take that loan only with a written trigger date.
