Skip to content
Journal

Engineering

Design Systems Are How You Tame AI Code

Headshot of Grace Nakamura
Grace Nakamura
March 5, 2025 · 3 min read

Half the frontend code written at this studio now starts life in an AI assistant. I am not confessing anything scandalous; that is simply where the industry is in early 2025. The interesting question is why the quality of that code varies so wildly between our projects, and the answer has almost nothing to do with prompting skill.

It has to do with whether the project has a real design system. Not a Figma library with the word "system" in the title. A codified, tokenized, lintable system that a machine can be pointed at. AI code generation did not make design systems less important. It quietly made them the most important artifact in the codebase.

Plausible is the failure mode

Here is what happens on a project without strong rails. You ask the assistant for a card component. It produces a lovely card with p-4, a hex color it invented, a border radius it guessed, and a shadow from its training data's idea of tasteful. Every value is plausible. None of them is yours. Multiply by fifty components and you have a codebase with a hundred shades of gray and spacing that follows no rhythm, produced faster than any human team could have made the same mess.

The old constraint on inconsistency was typing speed. That constraint is gone. The only remaining constraint is the system.

Tokens are a contract a machine can read

On systemized projects, the experience is completely different, because the assistant has a vocabulary to work within and a linter that rejects everything outside it. Three layers do the work:

  • Tokens as the single source of truth, in code, with semantic names. The assistant is instructed to use them and, more importantly, cannot merge anything that does not.
  • A component inventory the tool is told about. Context files listing our primitives mean the assistant composes <Stack> and <Text> instead of freelancing new divs. Reuse goes up dramatically when the machine knows what exists.
  • Lint rules as the enforcement layer, because instructions are suggestions but CI is policy.

The enforcement piece matters most. We run rules that flag any raw color, spacing, or font value in components:

// eslint: no raw design values in components
"no-restricted-syntax": [
  "error",
  {
    "selector": "Literal[value=/#[0-9a-fA-F]{3,8}/]",
    "message": "Raw hex color. Use a design token."
  }
]

It is a crude rule and it catches an astonishing amount of machine-generated drift. The assistant learns nothing, but the pull request does.

Review altitude has to change

The second adjustment is human. When code arrived at typing speed, review could afford to inspect everything. At generation speed, reviewers drown unless they change altitude: stop line-editing syntax the linter already policed and start reviewing the things machines are worst at. Does this component duplicate one we already have? Does the state live in the right place? Is the accessibility real or decorative? Did the assistant produce four hundred lines where the system offers a forty-line composition?

Our rule of thumb for reviewing generated code: trust the formatting, verify the architecture, and be openly suspicious of anything that looks impressively complete. Completeness is what these tools fake best.

The strategic point

For clients, here is the takeaway. Companies keep asking whether AI means they no longer need to invest in design systems, since the machine can just make components on demand. It is exactly backwards. The machine making components on demand is the reason you need the system. Generation without governance is entropy with good manners.

A design system used to be how a team scaled consistency across people. Now it is how a team scales consistency across people and machines, and the machines outnumber us already.

Building something this could apply to?

We take on a small number of flagship projects each quarter.

Start a project