01 · Foundations
Colour tokens
Every colour in this design comes from one of these. Nothing below hard-codes a value. The green, blue, gold and red are the reference product's own values, held exactly — which is why three of the ratios printed here fall short in light mode; see the contrast waiver in DESIGN.md. Toggle dark mode in the header to see each token's dark counterpart.
--background
page surface
--card
raised surface
--popover
floating surface
--primary
2.09:1 light · 8.05:1 dark
--secondary
low-emphasis fill
--muted
4.18:1 light · 5.27:1 dark
--accent
hover surface
--destructive
3.30:1 light · 5.09:1 dark
--border
2px edges
--input
control border
--ring
focus ring
--sidebar
nav surface
Chart series — use in order
chart-1
chart-2
chart-3
chart-4
chart-5
02 · Foundations
Typography
One rounded face carries everything — headings, body and every button label. The stack is "Baloo 2", "Arial Rounded MT Bold", "Trebuchet MS", sans-serif. Baloo 2 is vendored into theme.css as base64 woff2, so the roundness this design leans on is there on every device rather than only on the ones that happen to have a rounded face installed.
Learn something today
display · 48 / 700 / 1.1 / -0.02em
Make learning stick
h1 · 36 / 700 / 1.15 / -0.02em
Your streak, day 14
h2 · 24 / 700 / 1.25 / -0.01em
Unit 3 · Past tense
h3 · 20 / 700 / 1.35 / 0
Practice weak skills
h4 · 16 / 700 / 1.4 / 0
Short lessons, repeated often, beat long ones done once. This design is built around that rhythm: one clear action per screen, and visible progress after every one of them.
lead · 18 / 500 / 1.6 / 0
Body text is compact at 14px, which keeps a lesson screen dense enough to hold a full exercise without scrolling. The rounded face does the softening that the tight size would otherwise cost. Links are clearly marked with colour and an underline, never colour alone.
body · 14 / 400 / 1.6 / 0 — the default
Small text for hints, streak counts, and the line under a lesson title. Still fully legible.
small · 13 / 400 / 1.5 / 0
"Fifteen minutes a day for a year beats a weekend of cramming. The interface should make the fifteen minutes the easy thing to do."
blockquote · italic · primary border
Install the package with npm install @learn/ui and get started immediately.
inline code · mono · muted background
- One clear action per screen, sized for a thumb
- Progress is visible after every completed step
- A rounded display face keeps the density friendly
ul · check icon markers
- Pick a track and set a daily goal you will actually hit
- Work one unit at a time; the app decides what to review
- Come back tomorrow — the streak is the whole mechanic
ol · standard numbering
03 · Foundations
Surface & elevation
Soft shadows and generous border radii create depth without heaviness. Cards float gently above the background.
Shadow ramp
shadow-sm
Subtle lift
shadow-md
Cards, dropdowns
shadow-lg
Modals, dialogs
Border radius ramp
sm · 8px
md · 10px
lg · 12px
xl · 16px
2xl · 20px
Card on background
Example card
Cards use white backgrounds with soft shadows and generous rounded corners. The border adds definition without being harsh.
05 · Primitives
Form controls
Generous padding and friendly rounded corners make form inputs approachable. Clear states guide users through interactions.
Please enter a valid email address
Checkbox
Radio group
Switch
Slider
Value: 60%
06 · Primitives
Composed form
A realistic form showing spacing, rhythm, validation, and field grouping.
Create your account
Get started with a free account. No credit card required.
07 · Data display
Card
Border, no shadow — a card sits in the page, not above it. Padding is p-6, or p-4 for compact variants.
Basic card
Header, content, footer. The default container for everything.
Content sits at 14px with a 1.6 line height. Card titles use the h3 scale so they do not compete with the page title.
With header action
The action is a ghost icon button, aligned to the title baseline.
Media card
Media is flush to the card edge. The card clips it with overflow-hidden.
Stat cards
Requests
1.28M
12.4% vs last week
p95 latency
184ms
8.1% vs last week
Error rate
0.03%
Within the 0.1% budget
Build minutes
412
of 1,000 included
08 · Data display
Table
Rows are 44px. Numeric columns are right-aligned with tabular-nums — always. Header is bg-muted/50 with uppercase caption type.
| Deployment | Status | Author | Duration | |||
|---|---|---|---|---|---|---|
| acme-web-8f21ba9 | Ready | RKRina Kaur | 4 min ago | 1m 04s | ||
| acme-web-3c90d17 | Building | TOTomás Ortiz | 22 min ago | — | ||
| acme-web-71b0e42 | Failed | RKRina Kaur | 1 hr ago | 0m 38s | ||
| acme-web-d4419aa | Ready | JWJoan Weller | 3 hr ago | 1m 12s | ||
| acme-web-0ae7c31 | Cancelled | TOTomás Ortiz | Yesterday | 0m 09s |
1 of 5 rows selected
09 · Data display
List & feed
Three list shapes that carry most of an application: a settings list, an activity feed, and a description list.
Notifications
Deployment failures
Email me when a production deploy fails.
Weekly digest
Usage and performance summary each Monday.
Product updates
Occasional news about new features.
Activity
Rina Kaur promoted 8f21ba9 to production
4 minutes ago
Tomás Ortiz opened #412 Cache invalidation
22 minutes ago
Joan Weller added the eu-central-1 region
3 hours ago
Automatic rollback triggered by health check
Yesterday at 23:41
Build details
- Commit
- 8f21ba9
- Branch
- main
- Node
- 22.11.0
- Output size
- 4.2 MB
- Duration
- 1m 04s
10 · Data display
Badge & status
Status colours signal state. They are never used decoratively, and never to distinguish categories in navigation.
Badge variants
Status pills
Counters
11 · Data display
Avatar
Initials on bg-muted are the fallback. No generated colours per user — that reintroduces uncontrolled colour into the palette.
Sizes
With image
With status
Group
12 · Data display
Data visualisation
Chart series are used in order: a two-series chart uses chart-1 and chart-2, never chart-1 and chart-4. Gridlines are border, labels are muted-foreground.
Requests by region
Last 7 days
p95 latency
Area chart, single series
Sparklines
14 · Navigation
Tabs & segmented control
Tabs are underline style, not shadcn's default filled pill — a filled tab bar competes with buttons for attention. The segmented control keeps the filled treatment, because it is a control.
Horizontal tabs
The active panel renders below the bar with no additional container. A tab panel that adds its own border doubles the rule already drawn by the tab bar.
Segmented control
Vertical tabs
Vertical tabs use the sidebar item treatment rather than an underline, because a vertical rule reads as a container edge.
17 · Feedback
Alert & callout
Intent is carried by the icon and a /10 tinted background — not by a heavy coloured left bar, which fights the card border for the same job.
Preview deployments are enabled
Every pull request gets its own URL. Previews are deleted 30 days after the branch is merged.
Domain verified
acme.com is now serving from the production deployment.
Build failed
Module not found: @acme/ui-tokens. Check that the package is listed in dependencies.
View build log18 · Overlays
Dialog, sheet & popover
All shown inline rather than as real overlays. Floating surfaces get both a shadow and a border — in dark mode a shadow against a dark background is nearly invisible, so the border is what keeps the edge legible.
Dialog
Add a custom domain
Point your domain at Acme and we will issue a certificate automatically.
Alert dialog — destructive
Delete acme-web?
This removes all deployments, logs, and environment variables. It cannot be undone.
Popover
Build minutes
Time spent compiling, across all projects in this workspace.
412 / 1,000
Tooltip
Sheet / drawer
Environment variables
Applied at build and at runtime.
19 · Feedback
Progress & loading
Progress bar
Uploading assets
Lessons complete this quest
Quest points earned — under 60%, so no stroke
Daily XP goal — complete, no track visible
24% — quota used
Spinner
Progress ring
Skeleton
20 · Feedback
Toast & notification
Popover surface, shadow-lg, stacked bottom-right in a real application. Every toast is dismissible; destructive ones do not auto-dismiss.
Settings saved
Changes apply to the next deployment.
Deployment promoted
8f21ba9 is now live on acme.com.
Could not reach the build server
Retrying in 30 seconds.
21 · Feedback
Empty, error & loading states
Empty states are the one place a heading may be centred. The icon sits in a muted circle rather than floating, so it reads as deliberate rather than as a missing image.
No projects yet
Import a repository to get your first deployment running in about a minute.
No results for “rollbck”
Check the spelling, or search across all workspaces instead.
Could not load deployments
The API returned a 503. This is usually temporary.
22 · Composed
Application page header
Breadcrumb, title, description, actions, tabs. This is the top of nearly every in-app page, and getting it consistent is most of what makes an application feel coherent.
acme-web
HealthyMarketing site and documentation. Deploys from main to acme.com.
23 · Composed
Marketing hero
Marketing bands use generous vertical spacing. Backgrounds are flat token fills — this design gets its energy from the green and the lift, not from gradients.
Ship every branch
without thinking about it.
Connect a repository and get a URL for every commit, a certificate for every domain, and a rollback that takes one click.
Free for personal projects. No card required.
$ acme deploy --prod
✓ Building… 1m 04s
✓ Uploading 128 files
✓ Certificate issued for acme.com
→ https://acme.com
24 · Composed
Feature grid
Instant previews
Every pull request gets a URL before the reviewer opens it.
Certificates handled
TLS issued and renewed automatically for every domain you add.
One-click rollback
Every deployment stays addressable. Promote any of them back to production.
Analytics built in
Real user metrics per route, without adding a third-party script.
Edge by default
Static assets served from 40 regions with no configuration.
Team permissions
Per-project roles, SSO, and an audit log of every promotion.
25 · Composed
Pricing table
The recommended tier is marked with a border and a badge — not with a different background colour, which would introduce a second accent surface.
Hobby
For personal projects and experiments.
$0/month
- Unlimited static deployments
- 100 build minutes
- Community support
Pro
For teams shipping to production.
$24/user/month
- Everything in Hobby
- 1,000 build minutes
- Password-protected previews
- Email support, 1 business day
Enterprise
For organisations with compliance requirements.
Custom
- Everything in Pro
- SAML SSO and SCIM
- Audit log export
- 99.99% uptime SLA
26 · Composed
Testimonial
We moved eleven services across in an afternoon. The part I did not expect was that our review cycle got faster — every PR having a real URL removed an entire round of “can you screenshot it”.
“Rollback used to be a meeting. Now it is a button, and I have stopped dreading Friday releases.”
“The audit log alone got it through our security review. That never happens.”
27 · Composed
Call to action band
The one inverted surface in the design. It works because it is used once per page — a second inverted band would stop reading as emphasis.
Deploy your first project today.
Connect a repository and be live in under a minute. Free for personal projects.
29 · Utility
Icon set
Lucide, inline SVG, 16px in controls and 20px standalone, stroke width 2 (1.5 above 24px). Never an emoji, never a filled glyph icon — the stroke weight is what keeps the set coherent.
30 · Utility
Motion & interaction
One duration for everything interactive. Colour and opacity animate; layout and position do not.
| State | Treatment | Timing |
|---|---|---|
| Default | Base token colours | — |
| Hover | Surface shifts to bg-accent, or fill drops to /90. No transform. | 150ms |
| Focus | ring-2 ring-ring ring-offset-2, on :focus-visible only | instant |
| Active | Fill drops to /80. No scale. | 150ms |
| Disabled | opacity-50 pointer-events-none. Never a colour change. | — |
| Overlay entry | Fade plus 4px rise | 200ms |
| Reduced motion | All durations collapse to ~0 — handled in theme.css | 0.01ms |
Try it — tab through these
The ring uses ring-offset-background so it stays visible on both page and card surfaces.