We've always justified design systems with human reasons: consistency, faster onboarding, fewer one-off buttons. All true. But there's a new reason that quietly outweighs the rest — your design system is becoming the API that machines build UI against.
When an AI assistant generates a screen, the quality of its output is bounded almost entirely by the vocabulary you give it. A loose, undocumented pile of components produces loose, inconsistent output. A tight, well-typed, well-named system produces output that looks like your team wrote it. The design system stops being documentation and becomes a constraint surface.
What "good rails" actually look like
If a model (or a junior dev, honestly — same requirements) is going to compose your components correctly without hand-holding, the system has to be legible from the types and names alone.
Names that describe intent, not appearance.
// Weak: the model has to guess when to use which
<BlueButton /> <SmallButton /> <RoundButton />
// Strong: intent is in the name, variants are props
<Button variant="primary" size="sm" />
Props that make illegal states unrepresentable. If a component can be configured into a broken combination, something will eventually configure it that way. Push the constraints into the type system:
// A toast is either transient (auto-dismiss) OR action-required — never both.
type ToastProps =
| { kind: "transient"; durationMs: number }
| { kind: "action"; onAction: () => void; actionLabel: string };
A union like this is worth more than a paragraph of docs, because it's enforced. Neither a human nor a model can pass an onAction to a transient toast.
One obvious way to do each thing. Three different ways to render a modal is three ways to get it subtly wrong. Every redundant path is a fork where generated code can drift from your conventions.
The shift in where you spend effort
Old priority order for a design system:
- Visual polish
- Documentation / Storybook
- Type safety (nice to have)
New priority order:
- Type safety and clear contracts — the machine-legible layer
- Clear, intent-based naming
- Visual polish
- Docs (increasingly, the types are the docs)
This isn't because polish stopped mattering — it's because polish is now the cheap part. What's expensive and high-leverage is the part that lets everything built on top be correct by default.
A concrete test
Want to know if your design system is ready for this world? Try this: hand an AI assistant only your component type definitions (no screenshots, no prose) and ask it to build a settings page. Then look at the output.
- If it composed sensible, on-brand UI from the types alone — your contracts are doing their job.
- If it invented props that don't exist, or reached for raw
<div>s and inline styles — that's a map of exactly where your system is ambiguous or incomplete.
That gap is your design-system backlog now. The components it had to fake are the ones missing a clear contract.
The takeaway
Build your design system as if its primary consumer can't see — because increasingly, one of its primary consumers can't. It reads types, names, and constraints, not Figma frames. The systems that thrive in the next few years won't be the prettiest; they'll be the ones whose rules are so clearly encoded that neither a tired engineer at 5pm nor a model at scale can hold them wrong.
A design system used to be a favor you did for your teammates. Now it's the interface your whole org — humans and machines — programs against. Build it like an API, because that's what it is.
Thanks for reading! Let's stay connected:
- ⭐ GitHub — follow me and star the projects: github.com/parsajiravand
- 💬 Discord — join the frontend best-practices community: discord.gg/d9KRhuAwQ
- 📸 Instagram — frontend best practices, daily: @bestpractice___
- 💼 LinkedIn — linkedin.com/in/parsa-jiravand
- ✉️ Email (work & contract inquiries): bestpractice2026@gmail.com
Top comments (1)
Locking down the component API with discriminated unions is the only way to stop an LLM hallucinating impossible prop combinations. I picked up a book called Ship Your Design System on Amazon a while back, and the chapter on component API design covers exactly this constraint surface concept for AI generation. Are you passing the full TypeScript interfaces into the context window to guide the model, or just relying on the semantic naming?