Building a Design System from Scratch
A practical guide to creating a consistent, scalable design system for your team.
Why Build a Design System?
Every mature product team eventually faces the same challenge: inconsistency. Buttons look different across pages, spacing varies between components, and colour values drift over time. A design system solves this by creating a single source of truth for your UI.
A design system is not just a component library — it's a shared language between design and engineering.
Core Principles
Before writing any code, establish the principles that will guide your system:
- Consistency — every component should feel like it belongs
- Composability — small primitives combine into complex UIs
- Accessibility — built-in from day one, not bolted on later
- Documentation — if it's not documented, it doesn't exist
Setting Up Your Token System
Design tokens are the foundation. They define the raw values that flow through every component.
const tokens = {
color: {
primary: {
50: "#eff6ff",
500: "#3b82f6",
900: "#1e3a5f",
},
neutral: {
0: "#ffffff",
100: "#f5f5f5",
900: "#171717",
},
},
spacing: {
xs: "0.25rem",
sm: "0.5rem",
md: "1rem",
lg: "1.5rem",
xl: "2rem",
},
radius: {
sm: "0.25rem",
md: "0.5rem",
lg: "1rem",
full: "9999px",
},
};Building Your First Component
Start with something simple — a Button. It should support variants, sizes, and composability.
interface ButtonProps {
variant?: "primary" | "secondary" | "ghost";
size?: "sm" | "md" | "lg";
children: React.ReactNode;
}
function Button({ variant = "primary", size = "md", children }: ButtonProps) {
return (
<button className={cn(baseStyles, variantStyles[variant], sizeStyles[size])}>
{children}
</button>
);
}The key insight is that every prop maps cleanly to a set of tokens. This keeps the API predictable and the output consistent.
Lessons Learned
After building design systems at multiple companies, here's what I wish I'd known from the start:
- Start small — launch with 5-10 components, not 50
- Version everything — breaking changes in a design system break every consuming app
- Invest in tooling — automated visual regression tests save enormous effort
- Get buy-in early — a design system nobody uses is just a side project
The best design system is the one your team actually adopts. Focus on developer experience and you'll win adoption naturally.
Enjoyed this post?
Subscribe to get new posts delivered to your inbox.