Default
shadcn done carefully. Neutral greys, near-black actions, one blue for links, Geist throughout.
- Light by default
- 35 colours · 14 type steps
- Inspired by shadcn/ui
The same generated app in every design. Scroll inside the window to see the whole page.
What it is
shadcn/ui done carefully. Neutral greys on white, near-black actions and one blue kept for links and focus. Geist for everything, with Geist Mono for code and ids. Controls have 8px corners and cards 12px, and depth is a hairline first and a 1px shadow second. Light and dark are equally its own, so it opens in the visitor's system theme.
Maintained by @agentic-studio in the open registry.
Best for
Anything where the interface should get out of the way: internal tools, dashboards and developer products. Also any project that pastes components from the shadcn/ui docs and expects them to land unmodified.
Trade-offs
- Plain on purpose. A neutral system will never be the reason someone remembers your product. It is the reason they can use it.
- Two token names,
mutedandaccent, mean something different here than in an upstream shadcn theme. This registry's shared token contract claims them first. The bridge is documented and the fix is one class each. - Dark mode doubles what you check. Every colour you add needs a value in both palettes, and contrast has to hold in both.
Tokens
Generated from this design’s design.yaml, and shipped as CSS variables plus a Tailwind theme. Templates may use these names and nothing else.
Colours
Every colour token in design.yaml, grouped the way the system documents them. These are the light palette's values. The dark palette uses the same names with its own values, and tokens.css ships both.
Brand and accent
accent
#2563eb
accent-1
#2563eb
accent-2
#0d9488
accent-3
#d97706
accent-4
#db2777
accent-5
#7c3aed
accent-6
#65a30d
accent-hover
#1d4ed8
accent-soft
#eff6ff
primary
#171717
Surface
canvas
#ffffff
hairline
#e5e5e5
surface-card
#f5f5f5
surface-dark
#171717
surface-dark-elevated
#262626
surface-soft
#fafafa
surface-solid
#ffffff
surface-strong
#ebebeb
Text
body
#404040
body-strong
#262626
ink
#0a0a0a
muted
#666666
muted-soft
#8f8f8f
on-accent
#ffffff
on-dark
#fafafa
on-primary
#fafafa
Semantic
error
#c81e1e
success
#15803d
warning
#b45309
Other
danger
#c81e1e
danger-soft
#fdecec
error-soft
#fdecec
primary-hover
#2b2b2b
success-soft
#e8f7ee
warning-soft
#fdf3e1
Type scale
Each token rendered at its real size, weight, line height and tracking. Specimens fall back to this site's typeface when the design's own face is not installed locally, so read the numbers, not the letterforms.
Ship faster
- Token
- display-xl
- Values
- 4.5rem · 72px · 600 · lh 1 · ls -0.04em
Ship faster
- Token
- display-lg
- Values
- 3.5rem · 56px · 600 · lh 1.05 · ls -0.035em
Ship faster
- Token
- display-md
- Values
- 2.5rem · 40px · 600 · lh 1.1 · ls -0.03em
Ship faster
- Token
- display-sm
- Values
- 2rem · 32px · 600 · lh 1.15 · ls -0.025em
Ship faster
- Token
- title-lg
- Values
- 1.5rem · 24px · 600 · lh 1.3 · ls -0.02em
Ship faster
- Token
- body-lg
- Values
- 1.125rem · 18px · 400 · lh 1.6 · ls -0.005em
Ship faster
- Token
- title-md
- Values
- 1.125rem · 18px · 600 · lh 1.4 · ls -0.01em
Ship faster
- Token
- body-md
- Values
- 1rem · 16px · 400 · lh 1.6 · ls 0
Ship faster
- Token
- title-sm
- Values
- 1rem · 16px · 600 · lh 1.4 · ls -0.005em
Ship faster
- Token
- body-sm
- Values
- 0.875rem · 14px · 400 · lh 1.55 · ls 0
Ship faster
- Token
- button
- Values
- 0.875rem · 14px · 500 · lh 1 · ls 0
Ship faster
- Token
- nav-link
- Values
- 0.875rem · 14px · 500 · lh 1.4 · ls 0
Ship faster
- Token
- caption
- Values
- 0.8125rem · 13px · 500 · lh 1.4 · ls 0
SHIP FASTER
- Token
- caption-uppercase
- Values
- 0.75rem · 12px · 500 · lh 1.4 · ls 0.08em
Typefaces
The families the generated Tailwind theme points at. A licensed face is named here even when the substitute below is what actually renders.
- DisplayGeist, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif
- BodyGeist, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif
- MonoGeist Mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace
Spacing scale
Drawn at true size. These are the only gaps and paddings a generated repo is allowed to use.
- xxs0.25rem · 4px
- xs0.5rem · 8px
- sm0.75rem · 12px
- md1rem · 16px
- lg1.5rem · 24px
- xl2rem · 32px
- xxl3rem · 48px
- section6rem · 96px
Radius scale
Sample shapes at true corner radius. Buttons and inputs sit at the small end of this scale, feature cards at the large end.
- xs0.25rem · 4px
- sm0.375rem · 6px
- md0.5rem · 8px
- lg0.75rem · 12px
- xl1rem · 16px
- full9999px
- pill9999px
Elevation
Shadow tokens on a neutral card, at true blur and spread.
- insetinset 0 1px 0 0 rgb(255 255 255 / 0.12)
- lift0 4px 12px -2px rgb(0 0 0 / 0.08), 0 2px 4px -2px rgb(0 0 0 / 0.06)
- overlay0 12px 32px -8px rgb(0 0 0 / 0.16), 0 4px 8px -4px rgb(0 0 0 / 0.08)
- ring0 0 0 3px rgb(115 115 115 / 0.25)
- soft0 1px 3px 0 rgb(0 0 0 / 0.08), 0 1px 2px -1px rgb(0 0 0 / 0.08)
- xs0 1px 2px 0 rgb(0 0 0 / 0.05)
DESIGN.md
Ships in your repo as DESIGN.md. The designer agent reads it before it may introduce a new visual pattern. This is the briefing, not a page about the briefing.
Default is shadcn/ui done carefully. Neutral greys on white, near-black actions, and one blue kept for links and focus. Geist sets every word. Structure comes from hairlines, and a shadow is only ever 1px of lift. It is the design you get when you choose nothing, so it has to be the most correct one.
Read this before you add a screen, a component or a colour. The tokens live in
src/app/globals.css, the faces in src/app/fonts.ts, the kit in
src/components/ui/.
At a glance
| Theme | Light and dark, drawn equally. Opens in the visitor's system setting. |
| Type | Geist for headings, body and buttons. Geist Mono for code, ids and numbers in tables. |
| Colour | Neutral greys, near-black primary, one blue accent for links, focus and the accent badge. |
| Shape | 8px controls, 12px cards and dialogs, 6px badges, pills only for avatars and switches. |
| Depth | A hairline first. shadow-xs under buttons, inputs and cards; shadow-overlay only on things that float. |
| Signature | A faint 48px grid behind the hero that fades out, and a soft wash of the accent at the top of the page. |
Principles
- The content is the loudest thing. Greys carry the interface; colour is information (a link, a status, a chart series), never decoration.
- One action colour.
primaryis near-black in light and near-white in dark. There is no second brand colour to reach for. - Lines before shadows. A card is a hairline and a 1px shadow. If it needs more to stand out, the layout is wrong.
- Tokens only. No hex, no
bg-gray-100, notext-[#333]. Every value is a token, so the whole app can be regenerated onto another design. - Both themes, every time. Anything you add must read in light and dark.
Colour
Palette
| Token | Light | Dark | Role |
|---|---|---|---|
canvas (--background) | #ffffff | #0a0a0a | The page floor |
surface-soft | #fafafa | #111111 | Section bands, sidebars, table heads |
surface-card (--muted) | #f5f5f5 | #1c1c1c | Tinted fills: inactive tabs, hover rows, code |
surface-strong | #ebebeb | #2e2e2e | Pressed fills, progress tracks |
surface-solid (--popover) | #ffffff | #171717 | Menus, selects, toasts: always opaque |
card | #ffffff | #141414 | The card fill (white on white, held by its line) |
hairline (--border) | #e5e5e5 | white at 10% | Every border and divider |
ink (--foreground) | #0a0a0a | #fafafa | Headings and primary text |
body-strong | #262626 | #e5e5e5 | Emphasised body text |
body | #404040 | #d1d1d1 | Running text |
muted (--muted-foreground) | #666666 | #a1a1a1 | Secondary text, captions |
muted-soft | #8f8f8f | #7a7a7a | Placeholders, disabled text, icons at rest |
primary | #171717 | #ededed | The action colour |
accent (--accent-fill) | #2563eb | #60a5fa | Links, focus, the accent badge |
accent-soft | #eff6ff | #13213d | The tint an accent label sits on |
danger (--destructive) | #c81e1e | #f26d6d | Destructive actions and errors |
success, warning and error each come with a -soft tint for the back of a
badge or an alert: green #15803d, amber #b45309 and red #c81e1e in light,
lifted to #4ade80, #fbbf24 and #f87171 in dark.
How colour is used
- Blue means "you can follow this" or "this has focus". Do not use it for emphasis in running text or as a section background.
- Status colour appears only where there is a status: a badge, an alert, a form error. Never as decoration.
- A tinted section is
bg-surface-softwith a hairline above and below. Nothing on this page is ever a coloured band.
Charts
accent-1 to accent-6 (also chart-1 to chart-6) are six series colours
ordered so neighbours stay distinguishable: blue, teal, amber, pink, violet,
lime. Each is lifted in dark so a 2px line still reads on #0a0a0a. Assign them
in order; never let colour be the only way to tell two series apart.
Dark mode
The palette is declared twice in src/app/globals.css: light on :root, dark
under @media (prefers-color-scheme: dark) and again on .dark, where the
class wins in both directions. @theme inline points every utility at those
variables, so bg-canvas is one class that follows the mode.
src/lib/design.ts sets the theme a first visit opens in: system here. The
theme menu in the header offers light, dark and system and remembers the choice.
Type
Faces
- Geist (display and body): a neutral grotesque that reads at 13px and holds its shape at 72px.
- Geist Mono: code, ids, keyboard hints and tabular numbers.
Both load through next/font/google in src/app/fonts.ts: downloaded at build
time and served from this app. Change a face there and here, together.
Scale
| Token | Size | Line | Tracking | Weight | Use |
|---|---|---|---|---|---|
text-display-xl | 72px | 1 | -0.04em | 600 | The hero headline, desktop |
text-display-lg | 56px | 1.05 | -0.035em | 600 | The hero headline, tablet |
text-display-md | 40px | 1.1 | -0.03em | 600 | Section headlines, the hero on phones |
text-display-sm | 32px | 1.15 | -0.025em | 600 | Section headlines on phones, big numbers |
text-title-lg | 24px | 1.3 | -0.02em | 600 | Page titles in the app |
text-title-md | 18px | 1.4 | -0.01em | 600 | Card titles |
text-title-sm | 16px | 1.4 | -0.005em | 600 | Small headings, table titles |
text-body-lg | 18px | 1.6 | -0.005em | 400 | Lead paragraphs |
text-body-md | 16px | 1.6 | 0 | 400 | Running text |
text-body-sm | 14px | 1.55 | 0 | 400 | Interface copy, table cells |
text-caption | 13px | 1.4 | 0 | 500 | Metadata, helper text |
text-caption-uppercase | 12px | 1.4 | 0.08em | 500 | Eyebrows above headings |
text-button | 14px | 1 | 0 | 500 | Buttons |
text-nav-link | 14px | 1.4 | 0 | 500 | Header and footer links |
Rules: one h1 per page. Display sizes are for marketing pages; the app tops
out at text-title-lg. Set numbers that line up in columns with tabular-nums.
Space and layout
- Spacing tokens:
xxs4px,xs8px,sm12px,md16px,lg24px,xl32px,xxl48px,section96px (the gap between landing sections). - Content sits in
max-w-content(1280px) withpx-mdon phones andpx-lgfromsmup. Reading text stops atmax-w-measure(672px). - Use the scale. A gap that is not on it is a gap that will drift.
Shape and depth
| Token | Value | Where |
|---|---|---|
rounded-xs | 4px | Checkboxes, keyboard hints |
rounded-sm | 6px | Badges, menu items |
rounded-md | 8px | Buttons, inputs, selects |
rounded-lg | 12px | Cards, dialogs, popovers |
rounded-xl | 16px | The product picture on the landing page |
rounded-pill | full | Avatars, switches, progress bars |
Depth: shadow-xs (1px) under buttons, inputs and cards; shadow-soft on a
hovered card; shadow-lift on sticky bars; shadow-overlay on menus, dialogs,
sheets and toasts. In dark the same names are deeper and quieter, because a
light shadow on a dark page reads as a glow.
Components
Every component lives in src/components/ui/ and is written against the
tokens above. Import from there; never restyle a kit component inline to make
a one-off.
| Component | In Default |
|---|---|
Button | 8px corners, 14px medium label. primary near-black with a 1px shadow; secondary a grey fill; outline white with a line and a shadow; ghost fills grey on hover; danger red; link blue with an underline on hover. Sizes sm 32px, md 40px, lg 48px, icon 40px square. |
Badge | 6px corners, 13px medium text on a tinted back with a hairline. uppercase switches to the tracked eyebrow style. |
Card | default white with a hairline and shadow-xs; soft a grey band with a hairline; strong a darker fill; outline line only; dark the inverted panel. Padding sm 16px, md 24px, lg 32px. |
Input, Textarea, Select | 40px tall, 8px corners, white field with the input line and a 1px shadow. Focus: the line turns to the ring colour with a 3px soft halo. Invalid: red line, set through aria-invalid. |
Checkbox, RadioGroup, Switch | Near-black when on, a hairline box when off. The switch is a pill. |
Tabs | A grey track with a white raised tab for the active item. |
Accordion | Rows split by hairlines, a chevron that turns. |
Dialog, AlertDialog, Sheet | Solid panels, 12px corners, shadow-overlay, over a dark scrim at 60%. |
DropdownMenu, Popover, Select content, Tooltip | Solid surface, hairline, 12px corners, shadow-overlay. Tooltips invert: near-black with white text. |
Table | Hairline rows, a soft header band, body text at 14px. |
Alert | A tinted panel with a hairline and an icon in the status colour. |
Avatar, Progress, Skeleton, Spinner, Separator, Kbd, Breadcrumb, Pagination, Field, Label, Toaster | Quiet and neutral, all in the tokens above. |
The landing page
The landing page is the same in every design; the design decides how it looks.
Its sections carry data-slot hooks (listed at the top of
src/components/marketing/section-heading.tsx) that globals.css may style.
Default uses three of them:
hero-backdrop: a faint 48px grid of--grid-linewith a soft--washof the accent at the top, masked so it fades out before the fold.product-preview: the drawn app window floats onshadow-overlay.stat-value: tabular numbers, so the figures line up.
Everything else is type, space and the kit.
Signed-in screens
The dashboard, settings and sign-in pages use the same kit: a surface-soft
sidebar split from the page by a hairline, white cards with shadow-xs, and
tables with a soft header. Sign-in is a single white card on the canvas.
Do and don't
Do
- Use
bg-canvas,bg-surface-softandbg-cardfor every surface. - Keep blue for links, focus and the one accent badge per view.
- Put a hairline between regions before you reach for a shadow.
- Use
Buttonfor every action andCardfor every panel. - Set ids, keys and code in
font-mono. - Check every new screen in light and dark.
- Use
tabular-numson numbers that line up. - Keep one
primarybutton per view.
Don't
- Don't write a hex value,
rgb(), or a Tailwind palette class outsideglobals.css. - Don't add a second brand colour or a gradient.
- Don't put coloured text on a coloured band.
- Don't use shadows larger than
shadow-xson anything that does not float. - Don't use
rounded-pillon buttons or inputs. - Don't set body text below 14px or headlines above 72px.
- Don't style a kit component inline to make a variant; add the variant to the kit.
- Don't use
bg-mutedorbg-accentfrom a pasted shadcn snippet (see below).
Working in this design
Pasting from shadcn/ui. The token layer carries shadcn's variable names, so
most snippets render unmodified. Two utility names mean something else here:
bg-muted becomes bg-surface-card, and bg-accent / text-accent-foreground
(a hover surface upstream) become bg-surface-card / text-ink. Here muted
is a text colour and accent is the blue.
Adding a token. Add it to all three palette blocks in globals.css (light,
the dark media query, .dark), map it in @theme inline, and document it in
the palette table above. Check contrast in both modes.
Adding a component. Check the kit first: most needs are a variant of
Button, Card or Badge, or a composition on the page. A new component gets
its own file in src/components/ui/, token classes only, a data-slot, and a
row in the Components table here. The designer subagent owns this.
Build a repo in Default
The builder opens with Default picked. Pick your batteries and the design is applied to every template before the zip is built.
