Skip to content

Product design, leadership and the Harness Design series

Harness Design seriesArticle no. 10

Why Flutter took 25 more days: closing the token foundation of the Harness Design System

John Morais, .

A dark desk at night under an amber lamp: a measuring tape runs past the pin marking the estimated end, with a stretch spliced by hand, and an empty chair in the background

The Flutter token rollout in the Prolog app happened on September 24, and the release to the people who use the product shipped this week. React was already live, so the token foundation of the Harness Design System Project is closed on both stacks, with the harness applied and tokens an LLM can consume. Call it agentic ready, call it LLM-readiness, or whatever name you prefer. The most structural part of the design system is ready.

This article tells why Flutter finished about 25 days after the deadline we estimated, and what that changed in the way I plan design system work.

We estimated Flutter by looking at React

On React, building and testing went faster. The Flutter estimate was born from that experience, and that was the original mistake.

Flutter runs on Google's own engine, on top of Dart, and shares nothing with JavaScript. Figma, in Dev Mode, already exports CSS and TypeScript, and on the web the tokens come in through Tailwind without much ceremony. On Flutter there was no equivalent path. The infrastructure that receives the tokens and distributes them to each platform had to be built with Flutter in mind, and the migration of components and screens was done independently from the web.

In practice there were two projects with the same name, and we estimated them as if they were one.

Testing cost more than migrating

On the web, validation relied on a tool that shows the current screen next to the screen with the new tokens. It helped a lot on React and was adapted later for Flutter, but Flutter demanded far more runtime testing, running the app and looking at the result.

Rodolfo, who led the migration in the code, described the difficulty well. The application is big, with many pages and old and new versions living together, and that means a lot of context for an AI to carry at once. He tried to orchestrate the migration in a single workflow and the execution never reached the end. What worked was splitting it into phases.

The review had the same scale problem. One of the tools he built listed all the tokens of both platforms, and the volume reached about 7,000. Reviewing that one by one was unfeasible. Glauber pivoted the method a few times until we decided to go screen by screen in the app, noting where the visual problem was biggest. With that we were able to separate what was worth migrating at that moment from what could pass. The empty states, for example, already needed to be redesigned anyway, so it made no sense to spend time adjusting the old version. The criterion we used was to make the divergence imperceptible to the people who use the app.

Technical debt we hadn't explored yet

Each stack carries its own technical debt, and part of it only shows up when someone goes into the code to make the change. The estimate, on the other hand, is made before going in. On React the gap between what was expected and what was found was small. On Flutter it was big.

Today I treat that debt as uncertainty declared in the estimate, and the math I do has changed. Before, I asked how long a stack takes. Now I ask how much of the stack I have already seen from the inside. If it's little, the deadline has to come with an explicit margin, and that margin has to be communicated to leadership at the start.

Dedication dropped in the middle of the project

The second reason for the delay comes from how the team was organized. The people working on the project had to start new projects, and the time dedicated to the design system dropped to something around four hours a week, when it happened at all.

In a goal-alignment meeting, one person on the team said that, without a well-defined task, four hours a week didn't produce work. Another pointed out that we had been missing deadlines because none of them was realistic. Both comments were right.

Working with AI makes this problem worse. An experiment with agents asks for someone to prepare the context, trigger the execution, let it run for hours and then review. Slicing that into two-hour blocks per week multiplies the cost of getting back in. During the conversation someone did the math: eight hours of work in two-hour weekly slices takes a month, and the same thing fits in one day.

That is what we did. We set aside a whole day dedicated to Flutter to close the token gaps that remained, and the production release shipped this week. I don't have a number to compare that day with the previous weeks, but it was what unblocked the delivery, and it is the clearest lesson of the period.

Another proposal that came out of that same meeting, and that I want to try, is to measure the human cost of the project. The AI's execution is hard to count in hours, but it is possible to record how much time each person had to stop what they were doing in the squad to resolve design system questions. Without that number, the project looks cheap and the team pays the difference.

What I take from this

The first change is to estimate each stack separately, without inheriting the deadline from another. The second is to treat what we don't yet know about the code as a declared risk in the schedule. The third is to reserve whole days for work that depends on long context. And the fourth is to count the cost of whoever leaves their own squad to work on the project, because that cost exists even when nobody records it.

The foundation is closed, and components are the next step

The tokens deliver the base: a more consolidated system, with more variants, revised typography and documentation an LLM can read. They don't yet deliver the result that gives the project its name, which is an AI assembling screens with direction. That gain depends on the components, and the proposal for that stage was presented to our CTO this week. He approved the plan.

The first decision in the plan comes straight from the Flutter lesson. Instead of loose hours during the week, the team will meet in person one whole day a week, focused only on the project and without interruptions, until the end of October. We thought about biweekly meetings, but that would give few working days until then, too few for the scope. We also doubled the hours we had planned before, and the impact on people's other demands was agreed in advance.

The work runs on two fronts at the same time.

The first is a skill, a reusable instruction that Claude Code follows, to evaluate screens. It compares the screen created with Prolog screens that work well, gives a score from 0 to 100% and suggests what to adjust. Screens at 80% or above go ahead without design review. This helps mainly on simple screens, like the ones that follow our pattern of tables, filters and navigation with side panels, which the people in development already create on their own with AI today.

The second is to apply the harness to about 60 components of our design system. There are other components that are not yet in the right design system repository, and they stay for later. For this work we will adapt a command-line tool from Astryx, an external project that has already solved how to prepare a component catalog for AI agents. We decided not to rewrite the components now. Rewriting would force us to test how each one works, and today we have no tests for that. That path remains the ideal one in the medium term, but it would increase the risk of delay.

In the presentation, the CTO made a remark that changed the first front. The score can't be just a percentage, because some errors need to block the screen. Our pattern for showing the details of a table row is a side panel. If someone uses a window that opens in the middle of the screen, it shouldn't lose 10% and move on. It should go back for adjustment, because there is already a ready component for that. The skill now has, besides the score, a list of blockers.

How to measure that percentage on the components is still an open question. We will answer it on the first day of work, and it is around the second that we will know whether AI creates better screens with the harness. For now we have scope, a deadline and this question, declared.