Building SpurUI: A Design System for Speed and Polish
How I designed and built SpurUI — a curated component library focused on developer experience, visual consistency, and production-ready polish.
Design systems are more than component libraries. They’re contracts between design intent and engineering execution. SpurUI was born from a simple frustration: teams were rebuilding the same patterns over and over, each time with slightly different spacing, slightly different interaction timing, and slightly different accessibility coverage.
The Problem
Every product team I’ve worked with has hit the same wall. You start a new feature, reach for a button component, and realize:
- The existing one doesn’t quite fit your use case
- Someone built a “temporary” variant six months ago that’s now load-bearing
- The design specs reference tokens that don’t exist in code
This drift compounds. What starts as a minor inconsistency becomes a maintenance burden that slows down every new feature.
The Approach
SpurUI takes a primitives-first approach. Instead of building opinionated, page-level components, I focused on composable building blocks:
// Composable, not prescriptive<Card layout="compact" hover> <Badge variant="accent">New</Badge> <Text size="lg" weight="medium">Feature Title</Text> <Text size="sm" color="muted">Supporting description</Text></Card>Design Tokens as the Foundation
Every visual decision flows through a token layer. Colors, spacing, typography, shadows — all defined once and consumed everywhere:
:root { --radius-sm: 0.5rem; --radius-md: 0.75rem; --radius-lg: 1rem; --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.05); --duration-fast: 150ms; --ease-out: cubic-bezier(0.22, 1, 0.36, 1);}This means changing the border radius across your entire application is a single-line edit, not a codebase-wide search-and-replace.
Interaction Patterns
I spent significant time on interaction polish — hover states, focus rings, transition timing. These details are what separate “functional” from “feels great”:
const hoverClass = hover ? "transition-all duration-[var(--duration-normal)] ease-[var(--ease-out)] hover:-translate-y-1 hover:shadow-[var(--shadow-lg)]" : "";Outcomes
After rolling SpurUI into two production projects:
- Implementation drift dropped significantly — teams stopped inventing one-off variants
- Design-to-dev handoff accelerated — designers could reference real component names
- Onboarding improved — new engineers could build pages by composing documented primitives
What I Learned
- Start with constraints, not flexibility. The best design systems say “no” more than “yes.” Every escape hatch you add is a future inconsistency.
- Document behavior, not just appearance. How does a card respond to hover? What happens on focus? These interactions matter as much as the visual spec.
- Ship early, iterate often. SpurUI v1 had twelve components. That was enough to prove the model and earn team trust before expanding.
Design systems are living artifacts. They succeed when they make the right thing the easy thing — and SpurUI is my attempt at exactly that.