
2026-09-15
Nural Choudhury
Design systems architecture is the set of structural decisions that let a design system keep working as an organisation grows: how tokens layer, how components are organised and configured, and how the code that implements them is housed, built, and shipped.
Design systems covers what a design system is, Atomic Design, and governance from first principles. This page picks up from there, scaling design system infrastructure: token hierarchies, component API design, repository and framework strategy, distribution, and documentation architecture.
a system that still holds together when the token count doubles, three more teams start consuming it, and the team that built it isn’t the team shipping the next feature.
once a design system already exists and has to serve more than one team, product, or platform. Before that point, start with Design systems, not here.
the token hierarchy. Component APIs, repository shape, and distribution all assume the tokens underneath are already layered correctly, and each of those decisions inherits whatever confusion sits in the tokens.
The layered token vocabulary now standard across most systems, primitive values underneath semantic meaning underneath component-specific overrides, traces largely to work published by Nathan Curtis and the EightShapes consultancy, who named the split between global and alias tokens that most teams still use under different labels.
Style Dictionary, an open-source tool released by Amazon, did the same for tooling: define a token once, then transform it into CSS, iOS, and Android outputs from a single source.
Large public systems, among them Salesforce’s Lightning Design System, Adobe’s Spectrum, and Shopify’s Polaris, then demonstrated the layered approach at production scale and made the pattern visible outside any one company.

Tokens are organised in three layers. A primitive token holds a raw value. A semantic token borrows a primitive and adds meaning. A component token borrows a semantic token and scopes it to one component. Design systems explain what a token is; this is how the layers stack once a system has more than a handful.
| Layer | Holds | Example | Who changes it |
|---|---|---|---|
| Primitive | A raw value, no meaning attached | color.blue.500: #0066CC | Whoever owns the palette |
| Semantic | A primitive with meaning assigned | color.brand.primary: {color.blue.500} | Whoever owns brand decisions |
| Component | A semantic token scoped to one component | button.background.default: {color.brand.primary} | Whoever owns that component |
Changing colour.brand.primary cascades to every component built on it. Changing button.background.default touches only buttons. That asymmetry is the point: decide which layer a change belongs to before making it, not after something breaks that wasn’t meant to be touched.
Keep names predictable and semantic, colour.text.primary over colour.dark-grey and once picked, stable. A token nobody can rename without breaking six other systems is doing its job.
Four models compete for how components get grouped. Atomic design groups by compositional complexity, atoms into molecules into organisms; Design systems covers that hierarchy in full, so it is not repeated here. Category, tier, and domain models solve different problems, and most real systems combine at least two.
| Model | Groups by | Fits best when |
|---|---|---|
| Atomic | Compositional complexity, atoms through pages | The interface genuinely composes in that progression |
| Category | Function: forms, navigation, data display, feedback | Teams know what they need before they know the specific component |
| Tier | Stability: core, extended, experimental, deprecated | Governance and production-readiness expectations matter most |
| Domain | Product area: core, e-commerce, content, admin | The organisation runs genuinely distinct product lines |
Most mature systems layer two, a tier sitting over an atomic or category split, so a component is both core and a molecule at once. Pick the model the teams already use to talk about the interface. A model nobody recognises adds a translation step every time someone searches for a component.
An API is the contract a component keeps with whoever consumes it, and props, variants, slots, and composition each trade flexibility for consistency in different ways.
| Pattern | What it does | Trade-off |
|---|---|---|
| Props | Configures behaviour and appearance directly | Flexible, but an unconstrained set multiplies invalid combinations |
| Variants | Bundles a tested combination behind one name | Removes a decision, but someone still has to choose and maintain the set |
| Slots | Injects content into a fixed structure | Composition without prop complexity, at the cost of hiding the internal layout |
| Composition | Lets the consumer combine smaller components directly | Maximum flexibility, weakest guarantee that the result stays consistent |
Design toward the common case first. The default must be the correct choice, and the escape hatch must require a deliberate step, not a shortcut that happens to work. Accessibility conformance for what these APIs render is covered in Accessibility standards; this page covers only the shape of the configuration, not whether the output passes.
Where the code lives, which frameworks it targets, and how styles apply are three separate decisions, and conflating them under one heading is a common mistake.
| Repository shape | How it works | Fits when |
|---|---|---|
| Monorepo | All system code in one repository, one version of truth | Teams ship together and want atomic cross-component changes |
| Multi-repo | Separate repositories per package or platform | Teams ship independently and need clear, enforced ownership boundaries |
A hybrid monorepo for the core, with separate repos for platform-specific extensions, is a common middle ground. Choose based on how the teams ship, not on which structure looks tidiest on a diagram.
| Framework strategy | Approach | Trade-off |
|---|---|---|
| Framework-agnostic core | Web-standard components wrapped per framework | One source of truth, but wrapper overhead and real limits on custom elements |
| Framework-specific | A native implementation per framework | Idiomatic in each framework, at the cost of multiplying what gets maintained |
| Primary with adapters | One framework built in full, thin adapters for the rest | Concentrates effort, but non-primary frameworks get a second-class experience |
| Styling approach | How it works | Trade-off |
|---|---|---|
| CSS-in-JS | Styles written in JavaScript, scoped to the component | Strong encapsulation, runtime and bundle cost |
| CSS Modules | Scoped CSS with build-time class generation | Standard syntax and no runtime cost, more files to track |
| Utility CSS | Predefined utility classes composed in markup | Fast to build, verbose markup |
| Tokens as custom properties | Token values become CSS variables, consumed everywhere | Native and runtime-themeable, less structured than a full token system |
Distribution decides where consumers meet the system: an npm package for teams that already build with one, a CDN build for anyone without a build step, a Figma library for designers, and a documentation site as the shared reference all three point back to. Design documentation covers how that documentation process and ownership work; here it is one distribution channel among several, not the whole system.

Start with the token hierarchy before anything else. Decide the primitive, semantic, and component layers, and name them so a new hire can guess the next name correctly.
Pick one organisational model as primary, even when blending in a second. A component library with no chosen model is not more flexible; it is unsearchable.
Design component APIs for the case that will happen a hundred times, not the case that will happen once. An escape hatch must exist for the rare case, but it must cost more effort to reach than the default path.
Choose the repository shape based on how teams currently ship, not on what looks cleanest on a whiteboard. If teams already release independently, a monorepo will not change that; it will just make the independence harder to see.
Match the framework and styling strategy to the technology the organisation is running, not the one it would prefer to be running. Distribution follows where consumers already work, not the fewest channels you can get away with maintaining.

Take a system built by one team for one product, now needed by two more teams across a different platform. The existing tokens are flat, one file of hex values, no primitive or semantic split.
Start by extracting primitives from what already exists: every colour, spacing, and font value in current use, deduplicated. Layer semantic tokens on top, naming them for what they mean, colour.text.error, not what they look like. Only then add component tokens for the handful of components under active dispute.
With the hierarchy in place, look at what the two new teams need from the components. If they need different content inside the same structure, that is a slot. If they need a different but bounded set of looks, that is a variant. Resist adding a prop for anything more specific than that; a prop added for one team’s edge case becomes the whole team’s maintenance burden within a year.
Repository shape follows last, once the token and component decisions are settled. If the three teams release together, a monorepo with clear package boundaries keeps the token cascade atomic. If they release on separate schedules, split the packages and version them independently, and accept that the tokens will sometimes be a version behind in one product.

The token layer goes wrong first. Add enough intermediate names, colour.surface.elevated.subtle.hover and nobody can find the value they need without opening the source file and reading the resolved output. I have watched teams add a new semantic token for every edge case rather than reuse an existing one, and within a year the semantic layer is bigger than the primitive layer it was meant to simplify. A token hierarchy earns its abstraction only if someone can still find the right token in under a minute.
Component APIs go wrong in the opposite direction. A component with enough props to reconfigure its structure, not just its appearance, is no longer a component. It is a template that happens to ship as one. If a consumer can use props to rebuild the component from scratch, the API has stopped doing its job: making the right thing easier than the wrong thing.
The repository choice goes wrong when it is made for the wrong reason. A monorepo chosen because it looks tidier on a diagram- one repository, one version, one story- ignores how the teams involved ship. Teams that release independently don’t become more coordinated just because their code lives in the same folder. Instead, they start fighting over the same CI pipeline.
a design system is the product, the tokens, components, and documentation a team ships and consumes. Architecture is the set of structural decisions, hierarchy, organisation, repository shape, that determine whether that product survives growth. Design systems cover the first; this page covers the second.
tokens. A component built before the token hierarchy exists gets rebuilt once the hierarchy arrives, because its hardcoded values have nowhere correct to plug in.
three: primitive, semantic, and component, covers almost every organisation. A fourth layer, usually for multi-brand theming, is worth adding only once a specific brand or platform that needs it can be named, not in anticipation of one.
monorepo, for almost everyone starting. Multi-repo earns its overhead once teams are genuinely releasing on independent schedules, not before.
when a second framework stops being a one-off request and becomes a standing requirement from a team that is not going away. Building framework-agnostic for a framework you might need someday costs more than waiting until the need is real.
| Fact | Detail |
|---|---|
| Token tooling | Style Dictionary, an open source tool originally released by Amazon, transforms one token source into CSS, iOS, and Android outputs |
| Versioning standard | Semantic Versioning, major.minor.patch, is the public specification most design systems use to signal breaking changes |
| Monorepo tooling | Turborepo, Nx, and Lerna are the common tools mature systems use to manage build and dependency complexity in a monorepo |
| Component documentation | Storybook is a widely adopted component development and documentation environment |
| Public reference systems | Salesforce’s Lightning Design System, Adobe’s Spectrum, and Shopify’s Polaris are public examples of token-layered, multi-platform systems |

A design system is a governed set of reusable components, patterns and rules that a team uses to build consistent digital products at scale, and it is neither a static style guide nor a component library on its own.
Read it
Design documentation earns its keep when it removes a decision from a developer’s inbox, not when it is complete.
Read it
Digital accessibility is the practice of building products people can use, whatever their permanent, temporary, or situational disability, measured against a published standard rather than opinion.
Read it
An interface pattern is a solution to a recurring design problem, refined through enough use elsewhere that the person encountering it doesn’t have to figure out how to use it.
Read it