
Two years ago, our SaaS product had one designer, one front-end engineer who cared deeply about consistency, and no design system. We had four shades of primary blue, eleven button styles and a modal that behaved differently on every screen. This is how the two of us shipped a working system anyway: what we built first, what we left out on purpose, and what I would change if I started again tomorrow.
Start with what hurts
We didn’t begin with a grand plan or an audit of every pixel. We began with pain. For two weeks, we kept a shared note of every bug, inconsistency and Slack thread caused by UI drift. At the end, the list made our priorities obvious.
Buttons, form inputs and modals caused more than half of the issues. They were also used on almost every screen, so fixing them once would pay off everywhere. That’s where we started.
Don’t build the system you admire. Build the one your product is asking for.
Tokens before components
Before touching components, we defined tokens: colour, spacing, type, radius and elevation. They were small to build, easy to explain and instantly useful. Engineers could replace hard-coded values in existing screens without waiting for new components.
We kept the first set deliberately short:
Colour. Eight neutrals, one brand colour in four steps, and four semantic colours for success, warning, danger and info.
Spacing. A 4px base with nine steps. Anything outside the scale needed a reason.
Type. Six sizes, two weights and one line-height rule. We cut three font weights nobody could tell apart.
Radius and elevation. Three of each. Most of the product only ever used two.
Within a month, the four blues became one, and nobody missed the others.
The first five components
With tokens in place, we built components in order of pain: button, input, select, modal and toast. For each one, we followed the same simple loop.
Collect every existing version. Screenshots of every variation in the live product, grouped on one page. Seeing them side by side made the case for consolidation without any argument.
Agree on the smallest set of variants. We asked which variations had a real purpose and which were accidents. Most were accidents.
Build design and code together. The designer and the engineer paired on each component, so the file and the code shipped in the same week, with the same names.
Replace, don’t add. A component wasn’t done until the old versions were removed from the product. Otherwise the system would just become one more option.
What we left out
The hardest part of being a small team is saying no to good ideas. We wrote down what we would not do in the first six months, and we stuck to it.
No documentation site. We wrote short usage notes in the design file and in code comments, where people already looked. A site would have been one more thing to maintain.
No theming engine. We had one brand and one product. Theming could wait until we actually needed it.
No component for every edge case. If a pattern appeared only once, it stayed local. It joined the system the third time someone needed it.
No big launch. We released components one at a time, as soon as each one replaced something real.
Saying no kept the system small enough for two people to maintain without burning out. It also kept us honest: everything in the system was there because the product needed it.
Getting people to use it
A system nobody uses is just a well-organised file. Adoption came from making the right thing the easy thing. New components were faster to use than the old patterns, came with sensible defaults and needed fewer decisions.
We also showed our work. Every two weeks, we posted a short update in the product channel with before-and-after screenshots and one number, usually how many old variants we had removed. Visible progress turned curiosity into requests, and requests turned into contributors.
What I’d do differently
Looking back, most of our mistakes came from moving fast in the wrong places.
Name things with engineers from day one. Half our rework came from names that made sense in design and confused everyone in code. One shared naming session at the start would have saved weeks.
Set contribution rules early. For months, every change went through the two of us, which made us the bottleneck. A simple contribution guide would have let the system grow without us.
Track adoption from the start. We only began measuring component usage in month five. Earlier data would have helped us prioritise and made it easier to ask for more time.
Build accessibility in, not on. We retrofitted focus states and contrast checks later. Designing them into the first component would have been cheaper and better.
Small can be enough
Two years on, the system has grown to around forty components and a handful of contributors beyond the original pair. It isn’t perfect, and it doesn’t need to be. It does its job: the product is more consistent, new screens ship faster, and design reviews spend less time on button styles and more on problems that matter.
If you’re a small team waiting for the right moment or the right headcount to start, don’t wait. Start with what hurts, ship one useful piece, and let the system grow from there.


