What the token foundation hid: closing Milestone 1 of the Harness Design System

Continuing the first week of exclusive dedication to the project, all the work went into Milestone 1, which we called the technical foundation in tokens. I have already explained in the previous articles why we start there. Tokens are the smallest unit of the system. In an Atomic Design reading, they are the atoms: they come before any component, and everything we build on top inherits what they define. Getting this base right first is not perfectionism. It is the only way not to multiply the problem once AI comes in on top.
The estimate was to finish the tokens in one week. It did not finish in one week. And the reason it did not is what is worth telling.
Tokens looked like the easy part
Creating and organizing tokens, in the abstract, looks like the easy part of the project. Color, typography, spacing, border radius. A small thing.
What we kept discovering is that the problem is not creating the token. It is migrating the system to it safely and updating it in production without breaking what is already running. That stops being a design task and becomes a systems task. Each small token decision opens a range of infrastructure, code, and process decisions that we had not sized. That is why Milestone 1 turned into a sequence of activities much bigger than the initial list, and we realigned almost every day to deal with what kept showing up.
Three of these surprises deserve to be recorded, because they are exactly the kind of thing nobody tells you about.

Typography, which got stuck more than any color
The most emblematic case was typography. And it was the most annoying precisely because it looked trivial.
In Figma, italic is not a separate property. Figma merges weight and style into a single string, such as "Regular Italic" or "Medium Italic", so the weight you choose already carries the italic inside it. But on export, when the code is going to consume it, this has to come out decomposed: on one side the weight, on the other whether it is normal or italic. We had modeled italic inside the weight field, and that produced the wrong token in the output.
We spent a good while trying to solve this inside the variables. Creating a type for normal and italic, mapping weight by weight, size by size. I kept trying, Glauber kept testing, and with each attempt the organization got more confusing instead of cleaner. At some point we stopped to look at how other design systems handle it, like Ant Design and Nitro, and the answer was a bit humbling: they do not tokenize typography as variables. They solve it in the styles.
The decision that closed the matter was to drop the typography variables and consume the Figma text styles directly. The style already carries everything together: font, weight, italic, line height, letter spacing, and that is what React and Flutter now read. I want to be clear that this is not a pretty win. We changed things, undid them, redid them, and in the end we removed something we had built. That broke the export plugin, which had been built on top of the document with all the variables, and forced us to update it.
There was even a naming detail in the middle of this. We used "medium" as the name of a font size, but "medium" is also a weight name. For an LLM reading it, that ambiguity is an invitation to error. We replaced it with "Base", following Tailwind's style (text-base). It sounds like a small thing. Token names matter more than they seem when the reader is a machine, and this had already come up earlier in the project.

Bind, which we could not automate from the outside
In the previous article I left the bind prompt running via Figma Agents, partly working. The continuation of this story is that we tried several paths to automate the bind from the outside: Claude Code via MCP, scripts through Scripter, Figma Agents itself, and none of them delivered enough for scale. Figma Agents got to around 80%, which helps but does not close the job.
What unlocked it was moving the bind into the plugin we had already built internally, instead of leaving it as a loose prompt. There we could put in rules that the prompt struggled to guarantee: a fallback to the closest value when the exact value does not exist (a border radius of 9 becomes 8, not an invention), and, for color, a distance comparison in RGB space to find the correct semantic variable.
The concrete result on the design side is what reassures me most about Milestone 1: with this plugin, we bound almost 100% of the components in the Figma design system file to the correct tokens. It is not the definitive bind architecture for everyone. It is the one that works for our file, with our team, right now.

Where the JSON lives, and why it became a discussion
The last surprise was infrastructure, and it is the one that most connects to what I wrote in "Before AI-first, human-first".
When we exported the token JSON, it came out at roughly 40 thousand tokens in size, too big for an LLM to read directly. Rodolfo wrote a script to reduce it, and Gabriel proposed minifying the file by removing the whitespace: for a machine to parse it, it makes no difference, and the readability problem is only ours.
There was also a debate about where this JSON should live. The easy option was to leave everything in Prolog Cloud, the repository that centralizes the product's context, because any product designer could run the skill and commit without understanding the infrastructure. The problem is that dumping a lot of token files there can get in the way of the LLM's indexing, which already has plenty to handle.
The path we settled on was to keep Prolog Cloud as the source of truth for the tokens and, from a commit there, mirror the file to a separate Design System infrastructure repository, which then cascades the updates to React, Flutter, and Glorp. We accepted more complexity in the pipeline to reduce complexity in use. Glauber, or any designer, runs the skill and commits. They do not need to clone the infrastructure or understand how it works. It is the same kind of trade-off we had already made with governance: the ideal solution on paper loses to the solution the team can operate without drowning.

What we tested, and what came up
With the foundation in place, we tested applying harness to the tokens. The idea was to ask Claude to show visually how it understood each token from the documentation, and to ask it to build test interfaces, such as an alert component, just to see how it applied the tokens in practice.
The results were positive. It became reasonably clear that Claude was understanding the intent of each token: when to use it, when not to, and what goes with what. I will not inflate this beyond what it was. It was an initial test, on a small slice, and the goal was only to get a signal that the schema we wrote produces the right understanding on the other side. It did.

The way we tested was simple: I took the entire harness documentation for the tokens and asked Claude to say what it understood. It was a bit more involved than that, but that was the idea. What I generated was a report with the result.
Below is a summary of the report, with one detail: Glorp is the name of the design system at Prolog.







The honest scope of all this
Here it is worth being direct about what Milestone 1 delivers and what it does not yet deliver.
What it delivers is a scalable, semi-automated token foundation, with governance in both Figma and code, tokens an LLM can consume, and almost all the components in the design file tied to the correct tokens. It is a solid base.
What it does not yet deliver is the result that gives the project its name: an LLM building screens with direction. That return does not come from the token harness. As was already clear before, token harness is different from component harness, and most interface decisions will come from components, not from loose tokens. The token matters when Claude has to create something from scratch, with no ready component to reuse. The real production gain lives in the component harness, which is a later stage. This first part makes that possible; it does not yet harvest its fruit.
What comes next
We closed Milestone 1 and Milestone 2, which was the harness for the tokens themselves, for Prolog Cloud, React, and Flutter. Milestone 3, applying the tokens to the components, is already underway.
I cannot say what the results will be yet. There is the migration of the tokens in the React and Flutter components, which we will tackle with a mapping assisted by AI. There is an idea to also build a harness for the old tokens, to give Claude a comparison reference and increase the accuracy of this migration. There is the open question of whether that minified JSON will be consumed well at scale. And there is the production rollout, with the new and old tokens coexisting for a while. Each of these fronts can work, can fail, or can reveal a problem I have not yet seen. It is the part of the project I can predict least, and probably the most interesting one to document when it happens.



Comments