Blog post

AI Made UI Drift Cheaper

Why AI does not break product coherence by itself, but makes local UI deviation cheap enough that drift appears faster than many teams can review it.

AI Made UI Drift Cheaper

The first sign was not a broken screen.

The table rendered. The form submitted. The empty state was readable. The side panel did what it was supposed to do.

The problem appeared when those screens sat next to one another.

The product had begun to speak in several slightly different dialects. Forms validated differently. Actions that meant the same thing looked unrelated. Empty states changed tone, spacing, and hierarchy. A “quick” local variant became another branch that future work had to remember.

Nothing had failed loudly enough to stop a release. The interface was failing as a system.

Why the defect was easy to accept

UI drift rarely arrives as a deliberate redesign. It arrives as a sequence of reasonable local decisions.

A developer needs a new table action. An agent sees a nearby button and produces a plausible variation. A settings flow needs one extra condition. The generated implementation introduces a new field arrangement. A screen needs an empty state, so the fastest available copy and spacing pattern gets adapted.

Each change is defensible in isolation.

That is what made the failure difficult to see. Review asked whether the screen worked. It asked whether the component was accessible. It asked whether the tests passed. Those are necessary questions, but they do not ask whether the new screen has changed the product’s interaction contract.

The drift stayed below the threshold of an incident because every individual deviation was small.

AI changed the cost of saying “just one more variant”

Before AI-assisted UI work, implementation cost supplied a weak but useful brake. A new variant was possible, but it took enough time to make the difference worth defending.

That friction forced a question: is this a real product distinction, or am I avoiding reuse because reuse is less convenient?

Generated code weakens that question. A local exception can appear almost for free. The product surface can therefore expand faster than the team’s ability to decide which patterns are authoritative.

This is not an argument that generated components are inherently poor. It is an argument about economics. When production gets cheaper, deviation gets cheaper too.

A model working with incomplete context will usually optimise for the request in front of it. If the canonical pattern is difficult to find, weakly named, or surrounded by several competing examples, the locally reasonable answer is to invent another one.

The model is not violating the design system. The system has failed to make its authority legible.

The diagnosis is coherence leakage

The useful unit of review is not a component. It is the repeated interaction a component teaches.

A button can be correct while making an action look secondary on one screen and primary on another. A form can validate properly while placing errors in a different relationship to their fields. A loading state can be technically accurate while teaching a different expectation about whether the product is waiting, saving, or unavailable.

These are small leaks in the product’s language.

They accumulate into a cost users feel as hesitation. The product becomes less predictable. Engineers inherit more choices. Agents see more examples and become more likely to copy a deviation. The exception becomes evidence for the next exception.

That is the loop worth breaking.

Component authority is more than a library

A design system is often described as a catalogue of reusable parts. For AI-assisted work, that is incomplete. The important question is whether the system has authority.

An authoritative pattern has at least four properties:

  • it is easy to discover from the task being performed;
  • its name describes the decision it owns, not only its visual shape;
  • its boundaries make the intended reuse obvious;
  • deviations require a reason that survives review.

The last point matters. “This was faster” is an implementation explanation, not a product reason.

The outer review loop should ask what changed in the interaction model, which existing pattern was considered, and whether the new variant deserves to become authoritative. Visual comparison helps, but the review also needs to inspect semantics, states, copy, keyboard behaviour, and failure paths.

A generated screen is not complete when it renders. It is complete when its relationship to the product’s existing language is explainable.

The safeguard is a detection habit

I would now treat these as warning signals:

  • a new component has no named predecessor or deliberate reason for being different;
  • two screens solve the same interaction with different states or terminology;
  • review discusses pixels but not the contract the interaction teaches;
  • an agent prompt says “make it look like the app” because the app has no single authoritative example;
  • a local variant is copied into a second feature before anyone decides whether it is canonical.

The answer is not to stop generating UI. It is to make the outer loop stronger than the local optimiser: searchable patterns, bounded primitives, explicit deviations, and review that can reject coherence leakage even when the implementation is correct.

AI did not break my UI.

It made the cost of being locally reasonable lower than the cost of staying coherent. That is why drift now appears sooner, and why the earliest useful question is not “does this screen work?”

It is: what existing product rule does this screen reuse, extend, or intentionally replace?

Continue exploring

Follow the same line of thought through themes, tags, or a broader local search across the archive.

Keep following the thread.