Design systems today
Most design systems a year ago came with one intention. Creating an easier way for a team or organization to define a set of colors, spacing values, type styles, and components so that everyone can build from the same foundation.
The output often resembled Storybook, JavaScript component libraries, or more recently CSS variable systems built on top of shadcn, Base UI, or Tailwind CSS.
A designer could create a component in Figma, define its variables, and an engineer could use Developer Mode to integrate it by copying the generated code or CSS — a shared foundation with reliable styling.
Local intent doesn't scale
Most tooling today is built around local edits. You point at a button, leave a comment, or ask an agent to "make this primary" or "increase the padding." The agent can identify the correct component and modify the code.
Some novel examples of this are Agentation and Cursor's Design Mode.
A single annotation can tell an agent what to change, but it can't teach the agent what that decision means everywhere else in the system. As hundreds or thousands of changes accumulate, those local decisions begin to drift. New variants appear, one-off styles emerge, and the same concept is implemented differently across teams and repositories.
The challenge isn't helping an agent find the right button. It's giving every agent a shared understanding of the product's functional language.
Building production-grade software
Most design systems describe appearance. The existing styling library is organized around visual values that look something like the following:
--red-950 --neutral-700 --blue-600 --space-4
These class names were useful because they describe the implementation directly. Gray-950 is a dark gray. Space-4 is a spacing value. The natural progression was a way to visualize the depth of darkness and weight.
As natural language becomes the primary interface, inspecting individual buttons is no longer enough. Agents can generate plausible interfaces, but they don't know whether those interfaces belong to the design system.
Design systems as compilers
A semantic system starts with a different question. Not: What color should this be? But: What role does this element perform? Instead of asking a designer, engineer, or agent to choose gray-950, the system could expose roles such as:
foreground/supportingsecondary textcontent/contextforeground/selectedselected textcontent/focusforeground/on-actiontext on buttoncontent/emphasisbackground/inverseinverse surfacecontent/contrastA component library gives people reusable parts. A compiler accepts a higher-level description and translates it into implementation.
action="publish"background/action-primarytype · states · themeInstead of writing implementation, a button could express intent:
<Button color="blue" /><Button action="publish" />The system compiles that intent into form — background, type, states, focus, accessibility, theme. When agents can produce an interface in seconds, the scarce part is knowing what the interface should mean and ensuring that meaning survives every generated change.
Reviewing existing systems
Design teams need a system that can analyze component names, props, states, hierarchy, surrounding context, recurring patterns, and design token relationships, then construct a usage graph for every primitive.
Functional meaning cannot always be inferred with certainty. A value used inside a button is likely connected to an action, but its role still depends on the button hierarchy, tone, state, and surrounding surface. Straightforward mappings can be approved in bulk, while ambiguous cases include the evidence behind each recommendation.
blue-600currently represents
- Primary action background
- Informational text
- Focus outline
background/action-primaryforeground/informationalborder/focus
The product does not make every design decision automatically. It gives designers and engineers a structured view of the system already hidden inside the product so that agents can work with it.
Migrate without redesigning
Once the semantic model is approved, the tool rewrites the styling layer and creates a migration pull request. The first migration should preserve the visual output.
--foreground-base: var(--neutral-900); --foreground-selected: var(--neutral-900); --background-inverse: var(--neutral-900);
Existing components are updated to reference the new roles, but those roles still resolve to the current values. This separates two changes that are often incorrectly combined: restructuring the system and redesigning the product. The team can verify that no visual regressions were introduced before changing the expression of individual roles. Over time, primitive aliases can be removed and semantic roles can resolve directly to theme-specific values.
Keeping the system semantic
Every new component, variant, and generated change is an opportunity for the system to fragment again. Instead of treating the migration as a one-time event, the semantic model needs to become part of the design team workflow. For example:
- lint rules that prevent direct primitive usage
- typed semantic roles for component APIs
- updated Tailwind configuration
- Figma variable mappings
- generated documentation
- agent instructions
- compatibility aliases for gradual adoption
When a developer introduces a new component, the system can suggest an existing semantic role before creating another token. When an agent modifies the interface, it validates those changes against the product's functional grammar instead of generating another one-off implementation.
The goal isn't to freeze the design system. It's to ensure every change strengthens the semantic architecture rather than slowly fragmenting it — and to let people and agents describe what they're trying to build, then compile that intent into the correct implementation.