Design

Building a Design System from Scratch

December 10, 2024
9 min read
Abdullah Kabli

Building a Design System from Scratch

A design system is the foundation of consistent, scalable product design. At ATK, we've built design systems for startups that grew from MVP to Series A without redesigning from scratch.

This guide shows you how to build a design system that scales with your product.

What is a Design System?

A design system is more than a style guide. It's a complete set of:
- Design tokens: Colors, typography, spacing
- Components: Reusable UI elements
- Patterns: Common UI solutions
- Guidelines: Usage rules and best practices
- Code: Production-ready implementations

Think of it as the "source of truth" for your product's design.

Why Saudi Startups Need Design Systems

1. Bilingual Consistency
Managing EN + AR designs without a system leads to:
- Inconsistent RTL layouts
- Mismatched Arabic typography
- Different component behaviors per language

A design system ensures both languages feel native.

2. Speed to Market
With a design system, you can:
- Build new features 3x faster
- Onboard designers in days (not weeks)
- Maintain consistency across teams
- Reduce design debt

3. Investor Confidence
A polished, consistent product signals:
- Professional execution
- Scalability readiness
- Attention to detail
- Technical maturity

Design System Architecture

Layer 1: Design Tokens
The atomic level—raw values that define your brand.

Color Tokens:
```json
{
"color": {
"brand": {
"primary": "#0E244A",
"secondary": "#0089A7",
"accent": "#22C55E"
},
"neutral": {
"50": "#F9FAFB",
"100": "#F3F4F6",
"900": "#111827"
},
"semantic": {
"success": "#22C55E",
"error": "#EF4444",
"warning": "#F59E0B"
}
}
}
```

Typography Tokens:
```json
{
"font": {
"family": {
"en": "Inter",
"ar": "SaudiWeb"
},
"size": {
"xs": "0.75rem",
"sm": "0.875rem",
"base": "1rem",
"lg": "1.125rem",
"xl": "1.25rem",
"2xl": "1.5rem",
"3xl": "1.875rem",
"4xl": "2.25rem"
},
"weight": {
"regular": 400,
"medium": 500,
"semibold": 600,
"bold": 700
}
}
}
```

Spacing Tokens:
```json
{
"spacing": {
"0": "0",
"1": "0.25rem",
"2": "0.5rem",
"3": "0.75rem",
"4": "1rem",
"6": "1.5rem",
"8": "2rem",
"12": "3rem",
"16": "4rem"
}
}
```

Layer 2: Components
Reusable UI building blocks.

Button Component:
- Variants: Primary, Secondary, Ghost, Danger
- Sizes: Small, Medium, Large
- States: Default, Hover, Active, Disabled, Loading
- Props: icon, fullWidth, loading, disabled

Example (React + Tailwind):
```typescript
interface ButtonProps {
variant?: 'primary' | 'secondary' | 'ghost' | 'danger';
size?: 'sm' | 'md' | 'lg';
loading?: boolean;
disabled?: boolean;
children: React.ReactNode;
onClick?: () => void;
}

export function Button({
variant = 'primary',
size = 'md',
loading = false,
disabled = false,
children,
onClick
}: ButtonProps) {
const baseStyles = 'rounded-xl font-medium transition-all';

const variants = {
primary: 'bg-brand-primary text-white hover:bg-brand-primary-dark',
secondary: 'bg-brand-secondary text-white hover:bg-brand-secondary-dark',
ghost: 'bg-transparent border-2 border-neutral-300 hover:bg-neutral-50',
danger: 'bg-red-600 text-white hover:bg-red-700'
};

const sizes = {
sm: 'px-3 py-1.5 text-sm',
md: 'px-4 py-2 text-base',
lg: 'px-6 py-3 text-lg'
};

return (
className={`${baseStyles} ${variants[variant]} ${sizes[size]}`}
disabled={disabled || loading}
onClick={onClick}
>
{loading ? : children}

);
}
```

Layer 3: Patterns
Common UI solutions for recurring problems.

Common Patterns:
1. Form Layout: Label + Input + Error + Helper text
2. Card Layout: Header + Body + Footer
3. List Item: Icon + Title + Subtitle + Action
4. Empty State: Icon + Title + Description + CTA
5. Loading State: Skeleton or Spinner

Layer 4: Guidelines
Rules for using the system correctly.

Example Guidelines:
- Spacing: Always use multiples of 4px (0.25rem)
- Colors: Never use hex values directly—use tokens
- Typography: Use semantic headings (h1-h6)
- Accessibility: Maintain 4.5:1 contrast ratio
- RTL: Test all components in Arabic

Building Your First Component Library

Step 1: Choose Your Stack

For Web:
- React: Most popular, great ecosystem
- Vue: Simpler learning curve
- Svelte: Smallest bundle size

For Mobile:
- React Native: Cross-platform, one codebase
- Flutter: Fast performance, beautiful UI
- Native: Best performance, platform-specific

Our Recommendation:
- Web: Next.js + Tailwind + shadcn/ui
- Mobile: React Native + NativeWind

Step 2: Set Up Your Project

```bash

Create Next.js project
npx create-next-app@latest design-system

Install dependencies
npm install tailwindcss-animate class-variance-authority clsx tailwind-merge

Install shadcn/ui
npx shadcn@latest init
```

Step 3: Define Your Tokens

Create `tailwind.config.ts`:
```typescript
export default {
theme: {
extend: {
colors: {
brand: {
primary: '#0E244A',
secondary: '#0089A7',
},
},
fontFamily: {
en: ['Inter', 'sans-serif'],
ar: ['SaudiWeb', 'sans-serif'],
},
},
},
};
```

Step 4: Build Core Components

Start with these 10 components:
1. Button
2. Input
3. Card
4. Badge
5. Alert
6. Modal
7. Dropdown
8. Tabs
9. Accordion
10. Toast

Step 5: Document Everything

Use Storybook for component documentation:
```bash
npx storybook@latest init
```

Create stories for each component:
```typescript
// Button.stories.tsx
export default {
title: 'Components/Button',
component: Button,
};

export const Primary = {
args: {
variant: 'primary',
children: 'Click me',
},
};

export const Loading = {
args: {
variant: 'primary',
loading: true,
children: 'Loading...',
},
};
```

Bilingual Design System Considerations

1. Typography
- English: Inter (variable font)
- Arabic: SaudiWeb or Tajawal
- Fallback: System fonts

2. Spacing
- LTR: margin-left, padding-right
- RTL: margin-right, padding-left
- Solution: Use logical properties (margin-inline-start)

3. Icons
- Directional icons: Flip for RTL (arrows, chevrons)
- Non-directional: Keep same (checkmarks, close)
- Solution: Use `transform: scaleX(-1)` for RTL

4. Layouts
- Flexbox: Use `flex-direction: row-reverse` for RTL
- Grid: Use `direction: rtl` on container
- Absolute positioning: Swap left/right values

Design System Maintenance

Version Control
Use semantic versioning:
- Major: Breaking changes (v2.0.0)
- Minor: New features (v1.1.0)
- Patch: Bug fixes (v1.0.1)

Change Log
Document all changes:
```markdown

[1.2.0] - 2025-01-15

Added
- New Toast component
- Arabic font support

Changed
- Button hover states
- Input focus styles

Fixed
- RTL layout issues in Card
- Badge text overflow
```

Governance
Establish clear rules:
- Who can contribute: All designers + developers
- Review process: 2 approvals required
- Testing requirements: Unit tests + visual regression
- Documentation: Required for all components

Tools & Resources

Design Tools
- Figma: Best for design systems
- Sketch: Good alternative
- Adobe XD: Less popular now

Development Tools
- Storybook: Component documentation
- Chromatic: Visual testing
- Style Dictionary: Token management
- Turborepo: Monorepo management

Testing Tools
- Jest: Unit testing
- Testing Library: Component testing
- Percy: Visual regression testing
- Axe: Accessibility testing

Common Mistakes to Avoid

Starting too big: Build 5 components, not 50
No documentation: Components without docs are useless
Ignoring accessibility: WCAG 2.1 AA is minimum
Hardcoded values: Always use tokens
No RTL testing: Test Arabic layouts from day one
Over-engineering: Keep it simple and practical

ATK's Design System Approach

At ATK, we build design systems that:
- Start small: 10-15 core components
- Scale gradually: Add components as needed
- Stay documented: Storybook + usage guidelines
- Support bilingual: EN + AR from day one
- Remain accessible: WCAG 2.1 AA compliant

Need help building your design system? [Let's talk](https://atkabli.com/en/contact).

---

ATK — Licensed Freelance Product Studio
Building scalable design systems for Saudi startups.

Ready to Build Your Product?

Let's discuss your project and turn your vision into reality.