Contract-first
Contract-first says that every boundary is written down, agreed, and checkable before it is implemented. It is the same disposition dev-hub applies to APIs, applied to the boundary that runs between a design and the code that renders it.
Before it is implemented carries more weight here than it looks. For an interface it means the contracts are established assets that a feature consumes — not deliverables a feature produces. A story that has to design its own button is not working contract-first, however good the button turns out.
The three properties
Section titled “The three properties”A contract has three, and the third is the one that gets skipped.
| Property | In an API | In an interface |
|---|---|---|
| Explicit | An OpenAPI document | A design system and a component library |
| Agreed | Provider and consumer both reviewed it | Design and engineering both reviewed it, and either may propose a change |
| Enforced | Schema validation, contract tests | Tokens generated rather than retyped, lint rules against raw values, a story per state, a contrast check in the suite |
Explicit and agreed are cheap and common. Enforced is what separates a contract from a shared preference, and its absence is why so many design systems quietly stop being true.
The diagnostic is one question: what fails when the contract is breached? If the honest answer is “someone might notice in review”, you have a convention. Conventions decay under deadline; that is not a moral failing of the team, it is what conventions are.
Why an interface has two contracts
Section titled “Why an interface has two contracts”Because two different things are being agreed, by different pairs of people, and collapsing them into one produces a document neither side can use.
The visual contract — the design system — answers what may this interface be made of: colour roles, a type scale, spacing steps, the states every interactive thing must answer for, contrast and focus guarantees. It is agreed between design and engineering, and it is deliberately about no particular screen.
The technical contract — the core component library — answers what may code call: props, states, accessible behaviour, tokens consumed. It is agreed between the library and its consumers, and it is what actually drives user-interface coding.
The direction between them is fixed: the design system decides, the library implements and enforces. A colour chosen inside a component is a fork of the design system, and forks propagate — the next component that needs “something like that” copies it.
What a contract buys
Section titled “What a contract buys”The obvious benefit is consistency, and it is the least interesting one.
Estimability. When the pieces already exist, “two days” is a claim about composition rather than a guess about how long it takes to invent a date picker. This is the benefit teams notice first and attribute to the wrong cause.
Parallelism. A screen can be built against a component contract before the component is finished, the same way a client is built against a mocked API. The contract removes the dependency on something that is not ready yet.
Renegotiation without archaeology. When a contract is explicit, changing it is a conversation about the contract. When it is implicit, changing it means finding every place that assumed it — which is why undocumented interfaces calcify.
A smaller surface of things to get right. This is the real return. Once a button is under contract, no screen decides what a button is, so nobody reviews it, nobody tests it per screen, and nobody gets it subtly wrong on the fifth page.
What belongs in a contract, and what does not
Section titled “What belongs in a contract, and what does not”The recurring mistake is over-specification. A contract that pins the implementation removes the freedom that made it worth having.
| In the contract | Not in the contract |
|---|---|
| The states a component must express | How the loading state is animated |
| The accessible role, name and keyboard model | The DOM structure that achieves it |
| The tokens consumed | The exact CSS |
| The props and their defaults | The internal state management |
| The contrast guarantee | Which of two compliant greys is used |
The test: could the other side change this without breaking me? If yes, it is an implementation detail and it does not belong in the contract, however tempting it is to write it down.
The honest caveat
Section titled “The honest caveat”Every claim above depends on enforcement, and enforcement has a cost that arrives before the benefit does. A design system nobody generates from, a component library that has diverged from production, and a token file edited by hand downstream are all common — and all three are worse than not having them. They carry the maintenance cost and the appearance of rigour without the property that made them worth adopting.
Before adopting the tools, decide what fails the build when the contract is breached. If the answer is nothing, you are buying pictures.
Where it connects
Section titled “Where it connects”- Contracts is this attitude worked out in full, for both contracts and the tokens between them.
- User-first is what produces the content of the contract; without it you write down the wrong agreement precisely.
- Journey-first is what follows once both contracts hold: the risk moves, so the testing does too.
- Keeping them aligned is the failure mode that eats design systems — two catalogues that no longer agree.