Extract a reusable design system and theming
Continues from the last build: You held it to a performance budget on a real mid-range phone. It loads fast now, but every screen still hand-rolls its own button, card, and dialog markup with hardcoded hex colors, and the dark mode toggle you bolted on last sprint misses half the surfaces.
It is fast on a real phone now, but the codebase is not proud of it.
What you'll build
A tokens.css file drives every color and spacing decision, four accessible primitives (Button, Field, Card, Dialog) replace the copy-pasted markup across the metrics, events, and segments screens, theming respects prefers-color-scheme with a persisted manual override, and a docs page renders every variant in both themes so regressions are visible at a glance.
See how we teach, before you sign up
You don't just get code dumped on you. Every starter file and every solution is explained line-by-line, in plain English. Here's one real file from this project:
body {
background: #ffffff;
color: #16161a;
}
@media (prefers-color-scheme: dark) {
body {
background: #121214;
color: #f2f2f4;
}
}
.metric-card {
background: #f7f7f8;
border: 1px solid #d9d9de;
border-radius: 10px;
padding: 16px;
}
.button-primary {
background: #2f6fed;
color: white;
border-radius: 10px;
padding: 8px 16px;
border: none;
}
.button-primary:focus {
outline: none;
}
Reading this file
.metric-card { background: #f7f7f8;Hardcoded hex instead of a token, so this card never picks up dark mode even though body does.@media (prefers-color-scheme: dark) { body {Dark mode only exists on body. Every other component was styled once and forgotten..button-primary:focus { outline: none;The classic accessibility bug: focus outline removed and never replaced with anything.border-radius: 10px;A magic number repeated three times in this file alone; it should be one token.
The only theming that exists today: a single background flip with no tokens anywhere else.
That's 1 of 8 explained code blocks in this single project.
The build, milestone by milestone
- 1
Extract design tokens as CSS custom properties
4 guided stepsTokens are the single source of truth. Once color and spacing decisions live in one file, a primitive never needs to know it is light or dark, it just reads a variable, and a theme flip becomes a one-line attribute change instead of a re-render of every component.
- 2
Build the Button primitive with variants
4 guided stepsA single Button primitive means a design decision like "danger buttons get more padding" or "the focus ring is 2px" is made once, in one file, instead of being re-litigated (and inevitably drifting) in every screen that needs a button.
- 3
Build Field and Card primitives with accessible associations
4 guided stepsLabel-to-input association and error announcement are exactly the kind of accessibility detail that is easy to get right once and easy to forget every time it is copy-pasted; putting it inside the primitive means it can never be skipped again.
- 4
Build an accessible Dialog primitive
4 guided stepsA dialog is the single hardest primitive to get right by hand, and the one most likely to be silently broken (no focus trap, no Escape handling, focus lost into the body on close). Building it once, correctly, means every future modal in Pulse inherits that correctness for free.
- 5
Wire ThemeProvider: system preference, manual toggle, no flash
4 guided stepsRespecting the OS setting by default is the accessible baseline; persisting an explicit override respects a deliberate choice someone made. Doing both without a flash of the wrong theme is what makes theming feel like a finished feature instead of a demo.
- 6
Migrate screens and ship a docs page
4 guided stepsA design system that is not actually used everywhere is just an unused folder. The migration is where the payoff shows up: three screens worth of duplicated styling collapse into compositions of four primitives, and the docs page becomes the fastest way for anyone on the team to visually spot a broken token before it ships.
What's inside when you start
You'll walk away with
This is portfolio-grade. Build it free.
Sign up to unlock every milestone step-by-step, the code skeletons, full reference solutions, and checkable tasks, with your progress saved as you build.
Start building