Building a Design System That Rivals Apple
Building a Design System That Rivals Apple
When I started Studio89, I knew I wanted a professional, cohesive design system. What I didn't know was how deep the rabbit hole goes. Here's how I built a complete design system from scratch—and the non-obvious lessons I learned along the way.
The Problem
My portfolio had grown organically:
- Colors chosen ad-hoc per project
- Inconsistent button styles
- Manual class string building
- No validation or enforcement
- 117+ violations scattered across the codebase
It looked okay, but it didn't look professional.
The Vision
I wanted a system that:
- Rivals Apple, Vercel, and Stripe in quality
- Maintains 100% consistency
- Prevents violations automatically
- Works for both global UI and project-specific contexts
- Scales from mobile to desktop seamlessly
The 6-Color System
The Insight
Most design systems use one primary color. But I had a unique challenge: global UI (navigation, footer) needed to stay consistent, while project pages needed distinct category identities.
Solution: 6 colors total
- 1 Primary: Electric Lime (#CCFF00) for global UI
- 5 Categories: Purple (AI), Cyan (Code), Orange (Hardware), Red (Art), Pink (Design)
This separation prevents color confusion and maintains clear visual hierarchy.
Why OKLCH?
I integrated with an existing depth system that uses OKLCH color space. Benefits:
- Perceptually uniform (unlike RGB/HEX)
- Better for gradients and shadows
- Future-proof color specification
All 6 colors available in both HEX and OKLCH.
Component Patterns
The Factory Pattern
Instead of manual class strings, I built a factory:
// ❌ Before: Easy to mess up
<button className="button button-category button-category-ai">
// ✅ After: Impossible to mess up
<button className={HouseStyle.button.category('AI')}>The factory guarantees complete class combinations. No more incomplete patterns.
Tags vs Badges
Here's a subtle but important distinction I discovered:
Badges (for classification):
- Pill-shaped, UPPERCASE
- 15% opacity backgrounds
- More prominent
Tags (for keywords):
- Rounded corners, normal case
- 10% opacity backgrounds
- More subtle, hover glows
Different visual weight for different purposes. See them side-by-side on the tag test page.
Automation That Saves Time
Pre-Commit Validation
Built a validation script that runs on every commit:
pnpm validate:house-styleIt catches:
- Incomplete class patterns
- Inline style overrides
- Manual class building
- Deprecated functions
Result: 0 violations can slip through to production.
The Script
// Detects incomplete patterns
pattern: /className="([^"]*\bbadge\b(?!\s+badge-(primary|category))[^"]*)"/g;
message: "Incomplete badge class - missing pattern modifier";Scans 115+ files in seconds. Blocks commits if violations found.
Non-Obvious Lessons
1. Audit Before Fixing
I started updating pages one-by-one. Then I found 117+ violations buried in the codebase.
Lesson: Stop. Audit EVERYTHING first. Fix systematically. Prevent rework.
2. Test Pages Are Reference Implementations
I created test pages (button-test, badge-test, etc.) early. They became the source of truth for correct implementation.
When production pages looked different, I knew immediately: test page is right, production page is wrong.
Lesson: Build reference implementations first. Compare everything against them.
3. Separate Archive from Worklist
My task file grew to 1,100+ lines with history, decisions, and rationale. Valuable, but hard to navigate.
Solution:
- v1 (archive): Complete history, decisions, lessons learned
- v2 (worklist): Clean 255-line list of remaining tasks
Both serve important purposes. Archive for context, worklist for execution.
4. Document Decisions
When someone asks "why did you do it this way?", having documented rationale saves hours of explanation.
Example: Why factory pattern over utility classes? Documented in v1 with full reasoning.
5. Non-Linear Execution Is Faster
My phases went: 1-5 → 6 (partial) → 10 (audit) → 10.5 (comparison) → back to 6.
Why jump around? Found violations during phase 6. Better to fix ALL issues once than discover them page-by-page.
Result: Less total work, higher quality.
The Numbers
Coverage:
- 115 files scanned
- 0 critical errors
- 100% compliance
Performance:
- < 15KB CSS overhead
- 60fps animations
- Zero console errors
Accessibility:
- WCAG AA compliant
- 13.7:1 contrast (AAA) for Electric Lime
- Keyboard navigation throughout
Explore The System
Test Pages:
- Buttons - Primary, secondary, category patterns
- Cards - Base and category-accent cards
- Badges - Classification labels
- Tags - Keyword tags (NEW!)
- Inputs - Form elements
- Shadows - Depth and glow effects
- Animations - Timing and easing
Project Page:
- Design System Details - Full technical breakdown
What's Next
The system is production-ready, but there's always room for improvement:
- Additional patterns (modals, dropdowns, tooltips)
- Storybook integration for component documentation
- Visual regression testing
- Component usage analytics
- Expanded animation library
Takeaway
Building a design system is hard. But the payoff is worth it:
- Professional, cohesive appearance
- Faster development (factory pattern)
- Zero violations (automation)
- Clear documentation
- Maintainable codebase
If you're building a portfolio or product, invest in your design system early. Your future self will thank you.
Want to learn more? Check out the full project page or explore the test pages to see every pattern in action.