· 11 min read

Design systems are contracts, not libraries

How articulated decisions become the interconnections that hold a system together.

Design systems are contracts, not libraries
Cristian Morales

Cristian Morales

Product Designer

· 11 min read

If you ask most designers and devs what a design system is, they'll describe a documented library of components. The components are the artifacts. The documentation describes them. Together, they form the system.

This is exactly backwards. The documentation, or more precisely, the articulated decisions the documentation records, is the system. The library is one manifestation of the system in a particular tool. If the system is well built, the library can be regenerated. If the library is well built but the system isn't, every change breaks coherence because no one knows what decision each component was encoding.

The unit of thought in a design system isn't the component. It's the contract.

This distinction used to be a craft preference. It's becoming an operational requirement. Agentic systems need structure they can read, rules they can enforce, and decisions they can defer to. None of that is possible when the system lives as visual conventions in human heads. The contracts have to exist as something machines can parse, which means the decisions underneath them have to exist as something humans have actually made and articulated. The pressure agents put on design systems isn't aesthetic. It's epistemic. They need to know what we decided and why, in forms that don't require interpretation.

A design system is a system

It's worth taking the word "system" in "design system" literally for a moment. Donella Meadows defined a system as three things: elements, interconnections, and a purpose. The elements are the visible parts. The interconnections are the relationships between them. The purpose is what the whole arrangement exists to produce. Change the elements without changing the interconnections and you usually still have the same system. Change the interconnections, and you have a different system even if the elements stay the same.

This maps almost perfectly onto design systems work, and this clarifies why so many design systems decay over time. The components and tokens are the elements. The contracts that govern how components compose, how tokens propagate, and how decisions get applied are the interconnections. The articulated purpose, the thing the system exists to produce, is what every contract and every element should be derivable from.

Most teams build only the elements. That's the natural place to start because elements are tangible. You can see a button. You can render a card. You can list tokens in a table. The interconnections are invisible until you look for them. They live in governance documents, in design review conventions, in the tacit knowledge of whoever built the system originally. When a design system feels like it's decaying, what's usually decaying isn't the elements — those are still there. It's the interconnections. The relationships between elements stop being legible, and the system stops behaving like a system.

Meadows makes another point that lands directly on this. The least obvious part of a system, its purpose, is often the most crucial determinant of the system's behavior. And purposes are deduced from behavior, not from rhetoric. A design system whose documentation says its purpose is "consistency and reusability" but whose actual behavior is "every team forks components and ignores the library" doesn't have the purpose its documentation claims. It has whatever purpose its actual behavior reveals. The articulation says one thing; the system does another.

This is the diagnostic move that systems theory gives design systems work. You can audit a design system by looking at what it actually produces, not what it claims to produce. If the contracts don't hold, the elements drift. If the elements drift, the purpose has effectively changed regardless of what the documentation still says.

What contracts actually are

A contract says: when this condition appears in the interface, this is the correct response from the system, and these are the reasons it's correct. The component is the implementation of the contract. The library is the collection of implementations. The documentation is the human-readable description of the contract. But the contract itself is what stays constant across changes in tool, framework, or visual treatment.

Think of a contract less like a spec and more like a recipe. A recipe encodes a relationship between ingredients, technique, and outcome. If you move kitchens, change brands of flour, or switch from gas to induction, the recipe still gets made, better or worse. If you change the recipe you will end with a different dish.

Kevin Muldoon catalogs six mechanisms design systems use to hide complexity: indirection, encapsulation, constraint, semantic encoding, composition, and convention. Each is a different kind of contract. A token is an indirection contract. A component API is encapsulation. A variant set is constraint. A destructive/affirmative distinction is semantic encoding. These coexist in any non-trivial component because contracts compose. The artifact is what's left over when several contracts get implemented together in one form factor.

Contracts are interconnections in Meadows' sense. They're the codified relationships that make the elements function as a system rather than as a collection. When contracts hold, components compose predictably, tokens propagate correctly, and the system produces consistent behavior across the work of many people in many contexts. When contracts break down, the same components produce inconsistent results, the same tokens behave differently in different places, and the system behavior becomes whatever each individual team is doing locally.

The derivation chain

Contracts don't get invented in a vacuum. They get derived from something more foundational. The chain runs all the way back to article one's articulation work.

Articulated purpose produces standards and definitions. What is this product trying to do? Who is it for? What values does it encode? These get articulated into something stateable. A medical product serving patients with high anxiety has a purpose that produces standards like "every interaction should reduce friction" and definitions like "destructive actions require explicit confirmation."

Standards and definitions produce required behavior. Given the standards, what does the system need to do in specific situations? Reducing friction in a medical context produces required behaviors like "primary actions are always visually dominant" and "error states are recoverable in one step." The required behaviors are the operational consequences of the standards.

Required behavior produces contracts. Given the required behavior, what relationships have to hold between elements to produce it consistently? "Primary actions are always visually dominant" becomes a contract about button hierarchy: only one primary action per context, primary actions get the dominant color token, the dominant color token is reserved for this use. The contract codifies the relationship.

Contracts produce components. Given the contract, what artifact implements it in a given tool or context? A Button component with a variant prop that takes "primary" and "secondary" values, where "primary" applies the dominant color token and the system warns if two primaries appear in the same context. The component is what the contract looks like when materialized in code.

This is the chain. Articulation → standards → behavior → contracts → components. Each layer derives from the one below it. When a designer can trace a component back through this chain to articulated purpose, the component is anchored. When the chain breaks anywhere, the component starts drifting toward arbitrary preference, because nothing further down the chain is constraining it.

The chain also explains why building components first produces systems that decay. If you start at the top, with components, you're building elements without interconnections that derive from purpose. The components might be beautifully crafted, but they're not anchored to anything more fundamental than themselves. When the team grows, when the product evolves, when the context shifts, the components have no defense against drift because the chain underneath them was never built. Building from articulation downward produces durable systems. Building from components upward produces libraries.

Where HCI and atomic design fit

The vocabulary the field has developed for organizing components has its own place in the chain. It doesn't replace the derivation logic, but it gives teams tools for keeping the chain coherent at the levels where humans need to navigate it.

Human-computer interaction provides the vocabulary for what kinds of interactions the elements participate in. The interaction loop between user and system has two foundational primitives: input (how the user communicates intent) and feedback (how the system returns information). These aren't visual categories. A button and a textual link are both input primitives wearing different clothes. A toast and an inline error are both feedback primitives differing in persistence and placement. HCI literature has named these patterns for decades, and they remain the cleanest way to describe what interface elements fundamentally do at the level of the user's experience.

Structure isn't usually packaged with input and feedback as a third primitive category in HCI literature, but it does real work in design systems and probably deserves a name. Layout, spatial organization, and hierarchical grouping aren't input or feedback — they're how the relationships between inputs and feedback get organized for the user. A stack tells the user "these belong together." A divider says "these are different." A grid says "these are equivalent and scannable." Structure externalizes relationships into space so the user doesn't have to think about them (see UX laws). It earns a category alongside input and feedback when you're trying to organize a real design system, even if HCI proper treats it as something adjacent.

Atomic design is an abstraction of this. Brad Frost gave the field an easy to understand analogy for scale-aware hierarchy — atoms, molecules, organisms, templates, pages — that lets teams talk about how primitive interactions combine into compound ones at increasing complexity. The same pattern shows up everywhere in technical work. Assembly abstracts machine code into mnemonics. C abstracts assembly into structured constructs. Python abstracts C into something humans read fast. Each layer is an abstraction that makes the work tractable at the scale a real product requires. Atomic design does the same thing for interface work. A team has a hierarchy that scales with combination depth.

Frost anchored his atoms to HTML elements — form labels, inputs, buttons. Those aren't arbitrary visual choices. They're the semantic vocabulary the web developed to express HCI primitives as markup. The chain was always there in his original framing. The hierarchy makes sense because each level corresponds to a meaningful scale of combination, anchored at the bottom by what users actually do with interfaces.

Most components are compounds

Once you have HCI primitives at the bottom and atomic design's scale-aware vocabulary above them, the structure of any real component library becomes legible. Pure primitives are rare. Almost everything in a working system is a compound made by combining inputs, feedback, and structure in specific proportions, held together by contracts.

A list item is a feedback primitive. It says "this element exists in a collection." Add a checkbox and it becomes feedback plus input: it still asserts existence, and now it also enables selection. The contract holds the two primitives in a stable relationship — the checkbox state describes the item, the item provides the context for what the checkbox is selecting. The compound exists because the contract exists. Without the contract, you'd have two unrelated elements next to each other.

A search field is input plus continuous feedback. The input primitive accepts a query. The feedback primitive returns results in real time. The contract specifies how they relate: the feedback must update as the input changes, the input must remain editable while feedback is rendering, the relationship between query and results must be debounced to a specific timing. Three contracts inside one compound, each codifying a specific interconnection between the primitives.

Take away the contracts and you have elements next to each other with no specified relationship. The compounds become incoherent. This is why building components without their contracts produces libraries that decay. The components exist, but the relationships that made them function as a system don't.

The system is the contracts

Components are local solutions in particular tools at particular moments. Frameworks change. Visual fashion changes. Tools get replaced. If your system is built at the level of components, every one of those changes forces a rebuild, and the institutional knowledge gets lost in the migration.

If your system is built at the level of contracts, the components become disposable. When the framework changes, you rebuild the components but the contracts hold. When the visual language updates, you re-skin the components but the contracts hold. When you move from web to native to whatever comes next, the contracts hold and the implementations get rewritten. The thing that persists, the thing that's actually the system, is the codified set of relationships between elements that produce the behavior the system exists to produce.

Herbert Simon argued that organizational systems exist to conserve the scarcest resource: human attention. Kevin Muldoon names what a design system does in those terms: force multiplication. Every team that adopts a contract stops spending attention on the decision the contract encodes. The components are the snapshot of that contract for a particular tool. Tools change, components get rewritten, but the decision the team stopped re-deriving doesn't come back. That's the real persistence. Not the artifact. The reallocation of attention away from a problem that's already been solved.

The library is the snapshot. The contracts are the system. The components are artifacts when the contracts get implemented in a particular tool. Once you see this, the system stops being a folder of components and starts being the reasoning that produces them. The components get easy. The reasoning is what was hard all along.

It was hard because we were doing it for humans to read. Now we have to do it for machines to enforce. Agents working inside a design system can't infer intent from visual coherence the way an experienced designer can. They need the decisions encoded as rules they can follow, constraints they can respect, and contracts they can verify. The contracts have to become executable. That's where the next layer of this work begins.