Design Systems From Scratch: A Practical Guide
If you have ever opened a Figma file, copied a hex color into three different components, and then realized each component ended up a slightly different shade of blue, you already know why design systems exist. They are not bureaucracy. They are the only way to keep a product from drifting apart over six months of feature work.
This article is a practical look at what a design system actually is, why you almost certainly need one even if your team is two people, and how to build the smallest useful version in a week. I am not going to sell you a 200-page design system framework. I am going to show you what to ship on Monday and what to add on Friday.
What a design system is, in one sentence
A design system is a small, opinionated set of decisions about how your product looks and behaves, captured in a way both designers and engineers can use. Tokens, components, rules, and a little bit of philosophy. That is the whole thing.
The point is not to look professional. The point is to stop arguing about whether this button should be 12px or 14px tall for the 47th time this quarter. Decisions are made once. They are remembered in code. Everyone moves on to harder problems.
The three layers: tokens, components, patterns
Most design systems have three layers. I will explain each one with the question it answers.
Layer 1: Design tokens
Tokens are the atoms. They answer the question "what colors, spacings, and font sizes exist in our product?" A token is just a named value. For example:
--color-brand-primary: #ff8a3d--space-3: 1.5rem--radius-md: 8px--font-size-body: 16px
The win is consistency. If your marketing site, your admin panel, and your mobile app all pull from the same token list, the moment you change --color-brand-primary, every screen on every platform updates. You do not have to email anyone. You do not have to write a changelog. You commit the change, you ship, you are done.
Start with maybe 20 tokens. Spacing scale, a small color palette (one primary, one accent, a few grays, a success and a danger), and a font size scale. Resist the urge to be exhaustive. You can add tokens later. You cannot un-add 200 of them without a lot of pain.
Layer 2: Components
Components are the molecules. They are the buttons, the cards, the form fields, the dialogs. Each one is built from tokens, not from raw values.
Save changes
The HTML above is not interesting. The CSS is where the work lives:
.btn {
padding: var(--space-2) var(--space-4);
border-radius: var(--radius-md);
font-size: var(--font-size-body);
border: 1px solid transparent;
cursor: pointer;
}
.btn.primary {
background: var(--color-brand-primary);
color: white;
}When you change --color-brand-primary, every primary button in the app changes. That is the design system doing its job.
For a small product, you can get away with maybe 10 to 15 components. Button, input, select, card, modal, toast, table, tag, breadcrumb, pagination. Anything beyond that, build it once when you need it, then promote it to a component when you find yourself copying it.
Layer 3: Patterns
Patterns are the recipes. They are answers to questions like "how do I show the user an error?" or "what does an empty state look like?" or "how do I confirm a destructive action?"
Patterns are usually written as a paragraph of prose and a screenshot, not as code. They explain intent. They exist so a new designer joining the team does not have to invent the error toast from scratch.
You do not need a formal pattern library. A short Notion page with five screenshots and three sentences under each is plenty. The point is that the answers exist somewhere, and someone can find them.
The minimum viable design system, built in a week
Here is what to ship. Monday through Friday. Five days, one person, no committee.
Day 1: Pick the tokens
Open your product. Look at every screen. Write down every color, every spacing, every font size. If you find yourself writing the same value twice, that is a token. If you find yourself writing four slightly different values for the same thing, that is a bug you have not fixed yet.
End the day with a list of maybe 20 tokens. Put them in a CSS file. Do not get fancy. No JSON export from Figma, no Style Dictionary pipeline. A single tokens.css file is fine.
Day 2: Refactor one screen
Pick the most-used screen. Rewrite its CSS to use the tokens. Delete every raw hex code, every padding: 13px that should have been padding: var(--space-2). You will find places where you have three different shades of gray that should all be --color-text-muted. Make those calls now.
Day 3: Build the components
Pull the button, the input, the card out of that one screen into a shared component file. Use them in three different places to make sure they are not overfitted to a single use case. They will look weird on the third page. Tweak the component, not the page.
Day 4: Document the patterns
Write a one-page document. Five questions, five answers. "How do I show success?" "How do I show error?" "How do I confirm a delete?" "What does an empty state look like?" "What does loading look like?" Five sentences, five screenshots. Done.
Day 5: Roll it out
Apply the tokens and components to the rest of the product. You will not finish. That is fine. The point is to make the system real, used, and owned. A design system that exists in a Figma file but is not in the codebase is fiction. A design system in the codebase, even if only half the product uses it, is real.
Common traps to avoid
I have watched three companies build design systems. They all hit the same three walls.
Trap 1: Building for a year before shipping. If the system is not in the product, it does not exist. Ship on day 5. Refine forever.
Trap 2: Trying to be generic. A design system that works for any company works for no company. Your tokens are opinionated. Your components are opinionated. That is the point. Saying "we use the same button as everyone else" is not a design system. It is a default.
Trap 3: Treating it as a one-time project. Design systems are gardens. They grow. They need weeding. Every quarter, look at the three components that have drifted the most, and tighten them.
How to know it is working
You will know your design system is working the day a junior designer ships a screen that looks consistent with the rest of the product on their first try, without asking anyone. That is the test. If that is happening, the system is alive. If it is not, go back to day 1.
That is the whole game. Tokens. Components. Patterns. Ship in a week. Iterate forever.
Frequently asked questions
Do I need Figma to have a design system?
No. The design system lives in the code. Figma is a tool for designing screens; the system is the shared decisions. You can have a perfectly good design system in a single CSS file and a Notion page, without ever opening Figma.
What is the smallest team that benefits from a design system?
Two people. The moment you have a second person writing code, you have two people who need to agree on what a button looks like. A 20-token CSS file solves that problem in 20 minutes.
Should I use a UI library like Material or Tailwind?
Use them as a starting point, not as your design system. Tailwind is great for prototyping; the moment you find yourself using the same 5 utility classes in 30 places, extract them into a component. Material is fine if your product is a tool, less so if it is a brand.
Related articles
← More in Frontend Craft