01 · Foundations
Colour tokens
Every colour in this design comes from one of these. Nothing below hard-codes a value. Toggle dark mode in the header to see each token's dark counterpart.
--background
page surface
--card
raised surface
--popover
floating surface
--primary
7.05:1 light · 5.11:1 dark
--secondary
low-emphasis fill
--muted
4.65:1 light · 4.08:1 dark
--accent
hover surface
--destructive
5.60:1 light · 4.92:1 dark
--border
hairlines
--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
Crimson Pro (serif) for headings and long-form text — the writing comes forward. Inter (sans) reserved for UI chrome: buttons, labels, table headers, form controls. JetBrains Mono for code.
Display
48 / 600 / 1.15 / serifHeading one
36 / 600 / 1.2 / serifHeading two
24 / 600 / 1.3 / serifHeading three
20 / 600 / 1.4 / serifHeading four
16 / 600 / 1.5 / serifLead paragraph. Used once, directly beneath a page title. Generous line height and measure for comfortable reading.
18 / 400 / 1.7 / serifBody copy is 16px, not 14px — this design is for reading, not for dense dashboards. Serif keeps the reader in the flow of the text. You can link inline and set inline code without breaking the rhythm.
Small text. Help text beneath a field, timestamps, secondary metadata.
14 / 400 / 1.6 / serifCaption / overline (sans)
12 / 500 / 1.4 / +0.02em / sansA blockquote. Subtle left rule, no background fill, italic serif. Used in documentation, articles, and testimonials — the design is built for long-form content.
Unordered
- Deploy previews per branch
- Automatic TLS certificates
- Rollback to any prior release
Ordered
- Connect your repository
- Choose a build command
- Ship
03 · Foundations
Surface & elevation
Borders separate, shadows float. A surface in the page flow gets a border and no shadow; a surface above the page gets both, because a shadow alone is nearly invisible in dark mode.
border only — cards, panels
shadow-xs — buttons
shadow-md — menus, popovers
shadow-lg — dialogs
Radius ramp — everything derives from --radius: 0.5rem
sm · 4px
md · 6px
lg · 8px
xl · 12px
full · badges, avatars
05 · Primitives
Form controls
All controls are 36px tall to match buttons. The error state changes colour only — the border does not thicken, because a thicker border shifts layout by a pixel.
Lowercase letters, numbers and hyphens.
With a leading icon at 16px, inset 12px.
Enter a valid email address.
Disabled — 50% opacity, muted fill.
Cannot be changed after creation.
Runs in the project root.
Checkbox
Radio group
Switch
Slider
06 · Primitives
Composed form
Individual controls do not show spacing or rhythm. This does. Sibling fields sit gap-4 apart, groups gap-6.
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
68% — uploading assets
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 py-16 rather than the in-app py-8. Note there is no gradient — slate never uses one.
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.