Back to work
AI-assisted workDesign SystemsHuman owned systems

Build a System that Rocks a Little

Drift, design systems, and what AI-assisted implementation needs to succeed

Gemini generated image of a human hand on the left, reaching out towards a robot hand on the right

I’ve worked on several early-stage products where the only things that existed were a logo, a brand name, and maybe a couple of colors alongside the Problem to Be Solved For. But once, and so far only once, I’ve worked on an early-stage product with a Problem to Be Solved For and no brand identity at all.

That sort of lack isn’t always a serious deficiency; you can pick a neutral direction and see how it goes. This time, though, the brand was coming. It just wasn’t ready yet, and the launch date wasn’t going to wait for it. So the plan was straightforward: build with generic, out-of-the-box components and adapt them once the brand was finished.

To save us pain in the future, I built the design system to be “repainted”: the brand would be a swappable layer rather than baked into every component. You may not be surprised to hear me say it could have gone better. But perhaps not for the reason you’d expect. The system stood. The process went wrong because “later” kept drifting.

Drift can apply to many things

Drift is the gap between the system as designed and the product as shipped

Even as we built toward the initial vision, features and changes added up, and so did the engineering load. Refinement and branding dropped down the priority list and stayed there. Every sprint had something more urgent than improving the user interface, and each of those things was more urgent in isolation.

So the gap widened. The design system didn’t make the work hard, and no one was making bad calls. But a system built to work at speed doesn’t produce speed if the people who’d use it are pointed somewhere else.

This is the type of failure I think is more common than not. We can perfect component architecture and token naming; we can design for AI-driven agents creating the code. The hard part is the conditions these artifacts live in. A perfectly designed system that no one has the capacity to use produces exactly the same product as no system at all.

The second drift showed up when we got into the weeds of new features and pixel tweaking. New components appeared in wireframes that didn’t match the library or the patterns we’d established. Each one was reasonable on its own, some may even have merited entry into the library. That’s what makes this drift insidious: no one was generating wrong components on purpose; they were solving immediate problems. The cost doesn’t become visible until you go to change something, or add to the library, and something breaks.

We caught this drift in the seams: during QA, during development, usually when we tried to change something. It worked, but it came later in the process than it should have. When change was hardest.

A flexible system is a sustainable system

The current system is a few things working together.

There are multiple markdown specification files: platform-specific ones, one for accessibility, one for general best practices. They cover naming conventions, handoff expectations, and intended interactions; not just what a thing looks like, but how it’s meant to behave and what to call it.

There’s a Figma library, maintained by people, built on the conventions of Material and the Human Interface Guidelines rather than in opposition to them. The library and the wireframes inform the front-end component library, which is what our developers actually build the product from.

Perfection is brittle

There’s also a markdown skill whose entire job is identifying drift, a set of instructions an agent can load when checking work against the system. I wrote it because drift is a permanent condition, not something you can stop entirely. A system that doesn’t plan for its own violation isn’t complete — or if it is, it isn’t likely to survive.

Think of a tall building, or a long bridge span. These structures are designed to move under load. Rigidity is a weakness; a structure that can’t flex will fail at its weakest point.

Design systems work the same way. You need a system that can grow, react, and occasionally accommodate something from outside the library. What you can’t accept is drift that goes unrecorded. The rule isn’t “nothing outside the library.” The rule is “nothing outside the library that isn’t written down somewhere” — in the library, in Storybook, in a ticket. Undocumented drift is debt. Documented drift is a decision.

Catching it

We use an AI-powered QAT checker alongside human review at multiple stages, with the goal of keeping the shipped experience as close to the designed one as we can.

Things still get through. They did before, and they do now. Anyone promising you a process that catches everything is selling the process and not the results. The useful question is never whether drift escapes; it’s how often, and whether you find out before it compounds.

The working division of labor

Give the pixel-spotting to the agent designed for it, which has endless patience for the kind of comparison a person struggles with after twenty minutes.

Give component code generation to the agent with effectively infinite reference material, paired with a human who knows what good looks like and can tell when the plausible answer is the wrong one.

Keep for people the judgment that isn’t automatable: when to bend the system, and when bending it now prevents a break later. That call requires knowing why the rule exists, and knowing why is not the same as knowing what.

How we got out

Part of it was advocacy. Someone has to say out loud that the gap is real – so I did. It did help that no one was totally happy with the user interface, even though the features worked as intended.

But complaining doesn’t survive the next quarter’s pressure. What made it stick was turning the problem into something schedulable.

“The UI needs polish” is not a ticket. It has no size, no owner, and no finish line, so it loses to every piece of work that has all three. So we created UI polish tickets: individually scoped, owned by us, prioritized by us, and shared with PMs so they could flow into sprints like anything else.

That changed it from a project requiring a heroic push into something that got a little better every sprint.

Where it stands

That system is still running, and there’s a visual change on the near horizon.

The difference is that this time we have documentation that holds, a process that survived contact with reality, and real experience with AI-assisted front-end implementation and what it takes to support it properly. My honest expectation: it will cost a fraction of what the last one did.

The thing most teams get wrong about all of this is treating it as set-and-forget: build the system, adopt the tooling, and expect the work to shrink. What you’re building with a design system isn’t a finished artifact. It’s something with enough give to survive being wrong, and enough structure to tell you when it is.