The real talk: what’s actually hard about a design system
This is a follow-up to What is a design system, really? While building a design system for the search platform, I expected the difficult part to be coding components. The more I worked on it, the clearer it became that the harder work came earlier.
Before deciding how a Button should look, there is a bigger question to answer: what kind of product are we building, and what should it feel like to use? That question has shaped almost every design-system decision that followed.
Start with the product direction
The most important part of building a design system is understanding the business and the product’s position. What does the product help people do? What should people notice first? Should the experience feel calm, practical, expressive, premium, playful, or urgent?
Consider an editorial media or interior-design site built to showcase work and create a sense of taste. It would need a different visual language from an ecommerce site trying to help people make a quick purchase. Hot colours, crowded promotional blocks, and urgent calls to action may make sense in one context. In the other, they could make the experience feel rushed and pull attention away from the work itself.
This is why tokens and components cannot be chosen in isolation. Colour, typography, spacing, motion, and hierarchy all carry part of the product’s character. A component library should support the way people need to move through the product, rather than imposing a familiar visual style on it.
Once the product direction becomes clearer, tokens have a purpose beyond keeping the UI consistent. A colour token can express restraint or energy. A type scale can make an interface feel editorial or utilitarian. Spacing can make information feel compact and efficient, or give content room to breathe.
The same principle applies to components. A data-heavy internal tool may need tables and dense filters early. A search product may need to spend more care on result cards, empty states, and the actions that help people refine a search. The point is not to predict every component in advance. It is to let repeated, meaningful patterns earn their place in the system.
Skipping this work can create a quiet, expensive problem later. When the product reaches release, the brand may no longer match the position it needs to hold. Correcting that can mean revisiting the visual language, components, and product communication at the same time: work that costs money and effort, and can make future growth harder.
Build incrementally, then choose deliberately
That makes the next step a little simpler. Instead of trying to finish a complete library, add components when the product genuinely needs them. A pattern becomes a component when it has a stable purpose, appears more than once, and would create inconsistency if each screen built it differently.
Building this way keeps the system close to the product. It also makes each new component easier to name, test, document, and maintain, because the team already understands the problem it solves.
AI can make implementation faster. It can help draft code, create variants, or prepare tests and documentation. It cannot decide whether a pattern belongs in the system, which states matter to users, or whether the component fits the product’s character. Those are the decisions the team still needs to make.
Once the team knows which components matter, it can choose how to implement them. Headless UI can be useful here. A tool such as React Aria can handle interaction behaviour and accessibility, including keyboard navigation, focus management, and screen-reader semantics, while the team keeps ownership of the visual language around it.
This can work well when a product needs a distinct look without rebuilding every interaction from zero. It still needs the same product direction from the earlier steps: the visual layer needs clear tokens, states, and usage guidance so that the borrowed behaviour feels like part of the same product.
| Approach | What it gives | What it asks for |
|---|---|---|
| Existing library | Common patterns, quickly | Working within its look and its override rules |
| Headless UI | Behaviour and accessibility, with your own look | More investment in the visual layer |
| From scratch | Full control | Rebuilding interactions and maintaining them |
None of these choices is automatically right or wrong. A familiar compromise appears when a team mixes a component library such as Ant Design with utility-first styling such as Tailwind. Ant Design may provide a table or form quickly, while Tailwind makes custom layouts easy to shape. Over time, the team can end up with two ways to handle spacing, colour, overrides, and responsive behaviour. That can still be a reasonable choice, as long as the team defines the boundaries and understands the maintenance cost.
The goal is not to find a perfect stack. It is to choose the trade-off that supports the product’s direction and the team’s ability to keep the system coherent.
What I am taking away
Four ideas from this work keep coming back:
- A design system works best as a shared reference point that people can actually use.
- Starting small leaves room to use existing tools and build only what the product needs.
- The hardest decisions usually come from understanding the business, the product direction, and how users perceive it.
- Consistency helps people predict how the product will behave and feel, not simply how it will look.
The system can grow with the product. The important thing is that the reasons behind its decisions stay clear enough for the team to revisit as the product changes.
Working on something similar? Let's talk