Midnight
Pure black, white grotesque type, 1px hairlines, and one magenta cloud behind the product.
- Dark by default
- 35 colours · 14 type steps
- Inspired by liveblocks.io
The same generated app in every design. Scroll inside the window to see the whole page.
What it is
Midnight is drawn on pure black. One grotesque sets every word in white and warm greys, 1px hairlines replace every shadow, and corners stay between 4px and 12px. The main button is plain white, and violet is kept for links, focus and eyebrows. The product picture floats on a grainy magenta cloud, and quotes sit on white comment cards. The light palette keeps the same rules on paper white, with a black main button, black quote cards and a black closing panel.
Maintained by @agentic-studio in the open registry.
Best for
Developer tools, APIs, realtime and infrastructure products that want to look precise and calm at night. Teams whose product UI is the hero and who will put a real screenshot on the stage.
Trade-offs
- Pure black with white type is very high contrast. Long reading pages need the body grey and the 42rem measure, or they glare.
- With no shadows, every surface needs a hairline to exist. Dense screens can turn busy with lines.
- A white main button and one rationed violet leave no room for a loud brand colour. A brand that needs one will fight the system.
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 dark palette's values. The light palette uses the same names with its own values, and tokens.css ships both.
Brand and accent
accent
#9f8dfc
accent-1
#9f8dfc
accent-2
#00c1d6
accent-3
#f76e99
accent-4
#f5b94f
accent-5
#2f6bff
accent-6
#edecee
accent-hover
#bcb0fe
accent-soft
#231b3a
primary
#ffffff
Surface
canvas
#000000
hairline
#272626
surface-card
#111111
surface-dark
#000000
surface-dark-elevated
#111111
surface-soft
#0a0a0a
surface-solid
#141313
surface-strong
#1f1e1e
Text
body
#c4c1c1
body-strong
#edecee
ink
#ffffff
muted
#918d8d
muted-soft
#6e6a6a
on-accent
#000000
on-dark
#ffffff
on-primary
#000000
Semantic
error
#ff6166
success
#6cefce
warning
#f5b94f
Other
danger
#ff6166
danger-soft
#2a0e14
error-soft
#2a0e14
primary-hover
#e4e3e3
success-soft
#0b221c
warning-soft
#261c0a
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
- 4rem · 64px · 500 · lh 1.05 · ls -0.02em
Ship faster
- Token
- display-lg
- Values
- 3.25rem · 52px · 500 · lh 1.08 · ls -0.02em
Ship faster
- Token
- display-md
- Values
- 2.5rem · 40px · 500 · lh 1.1 · ls -0.02em
Ship faster
- Token
- display-sm
- Values
- 2rem · 32px · 500 · lh 1.15 · ls -0.015em
Ship faster
- Token
- title-lg
- Values
- 1.5rem · 24px · 500 · lh 1.25 · ls -0.01em
Ship faster
- Token
- body-lg
- Values
- 1.25rem · 20px · 400 · lh 1.4 · ls 0.004em
Ship faster
- Token
- title-md
- Values
- 1.25rem · 20px · 500 · lh 1.35 · ls -0.005em
Ship faster
- Token
- body-md
- Values
- 1rem · 16px · 400 · lh 1.5 · ls 0.006em
Ship faster
- Token
- title-sm
- Values
- 1rem · 16px · 500 · lh 1.4 · ls 0
Ship faster
- Token
- body-sm
- Values
- 0.875rem · 14px · 400 · lh 1.45 · ls 0.004em
Ship faster
- Token
- button
- Values
- 0.875rem · 14px · 500 · lh 1 · ls 0.005em
Ship faster
- Token
- nav-link
- Values
- 0.875rem · 14px · 500 · lh 1.43 · ls 0
Ship faster
- Token
- caption
- Values
- 0.75rem · 12px · 500 · lh 1.4 · ls 0.01em
SHIP FASTER
- Token
- caption-uppercase
- Values
- 0.75rem · 12px · 500 · lh 1.33 · ls 0.04em
Typefaces
The families the generated Tailwind theme points at. A licensed face is named here even when the substitute below is what actually renders.
- DisplaySchibsted Grotesk, ui-sans-serif, system-ui, sans-serif
- BodySchibsted Grotesk, ui-sans-serif, system-ui, sans-serif
- MonoJetBrains Mono, ui-monospace, SFMono-Regular, Menlo, 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
- section6.5rem · 104px
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.125rem · 2px
- sm0.25rem · 4px
- md0.375rem · 6px
- lg0.5rem · 8px
- xl0.75rem · 12px
- full9999px
- pill9999px
Elevation
Shadow tokens on a neutral card, at true blur and spread.
- insetinset 0 1px 0 0 rgb(255 255 255 / 0.06)
- lift0 0 #0000
- overlay0 16px 48px -12px rgb(0 0 0 / 0.9)
- ring0 0 0 3px rgb(159 141 252 / 0.28)
- soft0 0 #0000
- xs0 0 #0000
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.
Midnight is a dark system drawn on pure black. White grotesque type and warm grey body copy sit on the void, 1px hairlines replace every shadow, and corners stay between 4px and 12px. The main button is plain white, violet is kept for links, focus and eyebrows, and the product picture floats on a grainy magenta cloud.
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 | Dark native on pure black (#000). Light keeps the rules on paper (#faf9f9), with a black main button, black quote cards and a black closing panel. |
| Type | Schibsted Grotesk at 400 and 500 for every word, headings at 500 with -0.02em tracking. JetBrains Mono for eyebrows, labels, table heads, keys and code. |
| Colour | White and warm greys on black, one rationed violet (#9f8dfc) for links, focus and eyebrows, and magenta only in the hero cloud and the closing horizon. |
| Shape | 4px controls and badges, 8px cards, menus and the product window, 12px dialogs and stages. Pills only on avatars, switches and progress. |
| Depth | Flat. A lightness step plus a 1px hairline makes elevation. Only menus, dialogs, sheets and toasts cast a shadow. |
| Signature | A grainy magenta cloud stage behind a flat black product window, under an announcement bar whose hairline brightens from grey to violet. |
Principles
- Draw on the void. Every surface is the canvas or one lightness step above it, edged with a 1px hairline.
- One white button per view. Every other action is outline, ghost or an arrow link.
- Violet means live: links, focus, eyebrows, the active tab, progress. It never fills a button.
- Every product picture sits on a stage: the magenta cloud in the hero, a dot grid with a small plume below it.
- Two families. The grotesque speaks; the mono labels.
Colour
Palette
| Token | Light | Dark | Role |
|---|---|---|---|
canvas (--background) | #faf9f9 | #000000 | The page floor |
surface-soft | #f4f2f2 | #0a0a0a | Section bands, sidebars, table heads |
surface-card (--muted) | #ffffff | #111111 | Tinted fills: inactive tabs, hover rows, code |
surface-strong | #ebe8e8 | #1f1e1e | Pressed fills, progress tracks |
surface-solid (--popover) | #ffffff | #141313 | Menus, selects, toasts: always opaque |
card | #ffffff | #111111 | The card fill |
surface-dark | #0a0909 | #000000 | The inverted panel |
hairline (--border) | #e7e4e4 | #272626 | Every border and divider |
ink (--foreground) | #0a0909 | #ffffff | Headings and primary text |
body-strong | #1f1d1d | #edecee | Emphasised body text |
body | #3f3b3b | #c4c1c1 | Running text |
muted (--muted-foreground) | #6b6767 | #918d8d | Secondary text, captions |
muted-soft | #8c8888 | #6e6a6a | Placeholders, disabled text, icons at rest |
primary | #0a0909 | #ffffff | The action colour |
accent (--accent-fill) | #6249e8 | #9f8dfc | The saturated accent: links, the accent badge |
accent-soft | #efecfd | #231b3a | The tint an accent label sits on |
danger (--destructive) | #c9253a | #ff6166 | Destructive actions and errors |
success, warning and error each come with a -soft tint for the back of a
badge or an alert: #0a7356, #94590a and #c9253a in light, #6cefce, #f5b94f and
#ff6166 in dark.
Midnight's own variables, read by the landing hooks and the kit: --cloud-base
(#cdb0c1 light, #cdb0c1 dark), --cloud-1 (#c8468a light, #c8468a dark),
--cloud-2 (#9a1437 light, #9a1437 dark), --cloud-3 (#f3cfe0 light, #f3cfe0
dark), --cloud-4 (#7a1a45 light, #4a0717 dark), --vapor (rgb(200 70 138 /
0.16) light, rgb(200 70 138 / 0.3) dark), --beam (#b3a8ee light, #4a4356
dark), --grid-line (rgb(10 9 9 / 0.1) light, rgb(255 255 255 / 0.09)
dark), --note (#0a0909 light, #ffffff dark), --on-note (#ffffff light,
#000000 dark), --note-muted (#a3a0a0 light, #635f5f dark), --note-line
(#2b2828 light, #e7e4e4 dark), --scribble (rgb(10 9 9 / 0.6) light, rgb(255
255 255 / 0.72) dark).
How colour is used
- The canvas is pure black (#000). Depth is a lightness step: #0a0a0a soft, #111 card, #141313 popover, #1f1e1e strong. On paper (#faf9f9), soft sinks to #f4f2f2 and cards rise to white.
- Text steps from white headings to bone (#edecee strong, #c4c1c1 body) and grey (#918d8d muted). Running text is never coloured.
- Violet (
text-accent: #9f8dfc, #6249e8 on paper) marks links, focus rings, eyebrows, the active line tab, progress, the accent badge and checked menu marks. One violet thing per card at most. - The primary is white with a black label (black with a white label on paper). Danger is coral (#ff6166) with a black label, red with a white label on paper.
- Magenta lives only in the hero cloud and the closing horizon. Mint, amber and coral mark status as soft tints with a coloured icon.
Charts
accent-1 to accent-6 (also chart-1 to chart-6) are six series colours
ordered so neighbours stay distinguishable. Six neon series on black: violet,
cyan, pink, amber, blue and bone (violet, teal, pink, amber, navy and grey on
paper). They light up inside product pictures and charts, never on buttons.
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: dark here, because
Midnight is drawn in dark first. The theme menu in the header offers light, dark
and system and remembers the choice.
Type
Faces
- Schibsted Grotesk (
font-display,font-body): headings and display type; running text and interface copy. - JetBrains Mono (
font-mono): code, ids and tabular labels.
Schibsted Grotesk is a sharp Swiss grotesque: at 400 and 500 it sets headlines and body alike, so the page has one calm voice. JetBrains Mono labels eyebrows, keys, ids and table heads, and reads as code at a glance.
Every face loads 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 | 64px | 1.05 | -0.02em | 500 | The hero headline, desktop |
text-display-lg | 52px | 1.08 | -0.02em | 500 | The hero headline, tablet |
text-display-md | 40px | 1.1 | -0.02em | 500 | Section headlines, the hero on phones |
text-display-sm | 32px | 1.15 | -0.015em | 500 | Section headlines on phones, big numbers |
text-title-lg | 24px | 1.25 | -0.01em | 500 | Page titles in the app |
text-title-md | 20px | 1.35 | -0.005em | 500 | Card titles |
text-title-sm | 16px | 1.4 | 0 | 500 | Small headings, table titles |
text-body-lg | 20px | 1.4 | 0.004em | 400 | Lead paragraphs |
text-body-md | 16px | 1.5 | 0.006em | 400 | Running text |
text-body-sm | 14px | 1.45 | 0.004em | 400 | Interface copy, table cells |
text-caption | 12px | 1.4 | 0.01em | 500 | Metadata, helper text |
text-caption-uppercase | 12px | 1.33 | 0.04em | 500 | Eyebrows above headings |
text-button | 14px | 1 | 0.005em | 500 | Buttons |
text-nav-link | 14px | 1.43 | 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. Headings are Schibsted Grotesk 500, never heavier: 64px
at line height 1.05 in the hero, 52 and 40px below it, all at -0.02em. Body is
400 at 14 to 20px with a hair of open tracking, held to the 42rem measure.
Eyebrows, stat labels, table heads and footer heads are 12px JetBrains Mono caps
at 0.04em.
Space and layout
- Spacing tokens:
xxs4px,xs8px,sm12px,md16px,lg24px,xl32px,xxl48px,section104px (the gap between landing sections). - Content sits in
max-w-content(1280px) withpx-mdon phones andpx-lgfromsmup. Reading text stops atmax-w-measure(672px). - Spacing steps are 4, 8, 12, 16, 24, 32 and 48px, with 104px between sections.
- Controls are compact (32, 40 and 44px tall); the void between sections stays generous.
- Sections split with one full-bleed 1px hairline at the top. There are no tinted bands.
Shape and depth
| Token | Value | Where |
|---|---|---|
rounded-xs | 2px | Breadcrumb, Checkbox, Kbd, the landing page |
rounded-sm | 4px | Accordion, Badge, Button, Dialog, DropdownMenu, Input, Select, Sheet, Skeleton, Tabs, Toaster, Tooltip, the landing page |
rounded-md | 6px | Tabs, the landing page |
rounded-lg | 8px | Alert, Card, DropdownMenu, Popover, Select, Table, Toaster, the landing page |
rounded-xl | 12px | AlertDialog, Dialog, the landing page |
rounded-pill | 9999px | Progress, Switch, the landing page |
rounded-full | 9999px | Avatar, RadioGroup, Switch |
Radii are 2px on checkboxes and keys, 4px on buttons, inputs, badges and menu items, 6px on the tab strip, 8px on cards, menus and the product window, and 12px on dialogs, stages and the closing panel. Borders are 1px solid: #272626 for structure, #3a3838 for inputs, outline buttons and keycaps. Dashes are only for sketch lines: skeletons, the preview bar and the step connector. Cards, buttons, inputs and the product window are flat; menus, dialogs, sheets and toasts take one deep overlay shadow.
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 Midnight |
|---|---|
Button | 4px corners, sentence case, grotesque 500 at 14px, flat. Primary is white with a black label (black with white on paper); secondary is the card surface with a hairline and a faint inner edge; outline is a #3a3838 frame that turns white on hover; ghost fills faintly on hover; danger is coral with a black label; link is violet. Large is 44px at 16px; icon buttons are 36px squares. The violet focus ring sits off the edge, so it shows on a white button. |
Badge | A 4px rectangle, never a pill: 20px tall, 12px 500, a 1px border. Neutral is a card chip with a hairline; accent is a violet tint with a violet edge; status badges are soft tints with a 25% edge. The uppercase variant switches to mono caps. |
Card | 8px corners, a 1px hairline and no shadow. Default is #111 on black (white on paper); soft, strong and outline step the tone; dark keeps a line so a black card still shows on the black page. Titles are 20px 500. |
Input, Textarea, Select | 40px fields with 4px corners and a #3a3838 line, filled with the canvas, so they read as a recess inside a card. Focus turns the line violet with a 3px violet halo; invalid turns it coral. Select content is the popover surface with 8px corners, an overlay shadow and a violet check on the chosen item. |
Checkbox, RadioGroup, Switch | 16px controls on the canvas with a #3a3838 line. A checked box turns white with a black tick; a checked radio shows a white ring and an 8px white dot (black on paper). Switches are pills: off is the strong surface with a grey thumb, on is white with a black thumb. No glow. |
Tabs | Default tabs are an editor strip: a 36px hairline box split by hairlines, the active tab on the card surface with no shadow. Line tabs mark the active tab with a 2px violet underline, the one violet state in tabs. |
Accordion | Rows split by hairlines, 16px 500 triggers that turn violet on hover, a muted chevron that turns 180 degrees, and answers in bone body text. |
Dialog, AlertDialog, Sheet | The popover surface with a hairline, 12px corners and the overlay shadow, over a black scrim at 70% with a 2px blur. Alert dialogs are 24rem wide, with an outline cancel and a danger confirm when the action destroys. Sheets sit flush to their edge with no radius and a hairline on the inner side. |
DropdownMenu, Popover, Select content, Tooltip | The popover surface with a hairline, 8px corners and the overlay shadow. Items are 32px with 4px corners and highlight to the strong surface; shortcuts and labels are mono; check marks are violet. Tooltips invert: a white chip on black, a black chip on paper, no arrow. |
Table | A hairline wrapper with 8px corners, a soft 36px header row in 12px mono caps, 44px rows split by hairlines that tint soft on hover, and tabular numbers in every cell. |
Alert | 8px corners, a 1px border and a 16px icon column. Info is a violet tint with a violet edge and icon; success, warning and danger are soft tints with a 25% status edge. Titles are 14px 500 in white. |
Avatar, Progress, Skeleton, Spinner, Separator, Kbd, Breadcrumb, Pagination, Field, Label, Toaster | Avatars are circles with a strong-surface fallback and a canvas ring in stacks. Progress is a 4px pill with a violet fill. Skeletons are dashed outlines with no fill, and spinners are thin muted rings that take the label colour inside a button. Separators are 1px solid hairlines. Kbd is a mono keycap with a 2px bottom edge. Breadcrumbs split with a slash; the current page in pagination is the outline button. Labels are 14px 500 in bone, fieldset legends are mono caps, help text is 12px muted and errors are coral. Toasts are the popover surface with 8px corners and show status only in the icon. |
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.
Midnight styles these:
hero-backdrop: removes the wash and the grid, so the headline sits on bare black.hero-titleandsection-title: balance their lines.hero-subtitle: bone grey, at most 40rem wide.hero-eyebrow: a 4px announcement bar, not a pill. Its hairline brightens from grey to violet, a 6px violet presence square leads it, and the arrow sits in a violet tile. A linked bar lights its whole edge on hover.hero-actionsand thecta-panelbuttons: the primary is a plain white button with no icon; the outline button drops its frame and becomes a text link with an arrow that nudges right on hover.hero-note: 12px mono in muted grey.hero-visual: a 12px grainy magenta cloud stage behind the product, 96px wider than the window on each side when there is room and 8px on a phone.product-preview: a flat window on the canvas colour with 8px corners and no shadow;product-preview-barsits on the canvas over a dashed sketch line.section: no tinted bands and no bottom rules; every section after the logo strip opens with one full-bleed hairline.section-eyebrow: 12px mono caps in violet, led by a 6px square in the same colour.sectionlogos and thesite-footerheads: mono caps in muted grey.logo: muted wordmarks that turn white on hover; image logos stay greyscale.feature-icon: a 40px hairline tile with a white icon; a hoveredfeature-cardbrightens its hairline and nothing lifts.showcase-visual: a 12px soft stage with a 16px dot grid and a small magenta plume from the outer top corner, flipping side with the row on wide screens.step-marker: 40px keycaps with mono numerals and a 2px bottom edge; the line between steps is dashed.stat-grid,statandstat-value: one 8px hairline grid, tabular numbers and mono caps labels.testimonial: each quote is a comment card in the opposite material, white on the black page and black on paper, by re-pointing the card tokens.cta-panel: a black panel in a 12px hairline frame, black in both themes, with a grainy magenta horizon rising from its bottom edge.site-header: the void at 82% over a blur with no rule at rest; the rule fades in over the first 96px of scroll where the browser supports scroll timelines.site-nav: bone links that turn white on hover and on the current page.brandandbrand-mark: the name tracks tight and stays white on hover; the mark is a 4px white square with a black letter.site-footer: the void under one hairline, with no soft band.
Everything else is type, space and the kit.
Signed-in screens
The dashboard and settings keep the material: a soft sidebar with a right hairline, 32px rows with 4px corners and a 2px violet bar on the active row, #111 KPI cards with mono labels and tabular values, charts in the six neon series, and no shadows outside menus.
Sign-in is one 400px #111 card with a hairline and 12px corners, centred on the void: the brand mark, a 24px title, 40px inputs, a full-width white primary button and outline buttons for other providers.
Do and don't
Do
- Keep the landing page on the canvas from header to footer: #000 in dark, #faf9f9 on paper. Split sections with one full-bleed hairline.
- Give each view one white primary button (black on paper). Pair it with an outline button or an arrow link.
- Keep violet to links, focus rings, eyebrows, the active line tab, progress, the accent badge and checked menu marks.
- Set every heading at 500, with -0.02em tracking from 40px up.
- Set ids, keys, shortcuts, table heads, stat labels and eyebrows in JetBrains Mono.
- Use 4px corners on controls, 8px on cards and menus, 12px on dialogs and stages.
- Draw placeholders and sketch lines dashed (skeletons, step connectors, the preview bar). Draw structure solid.
- Put every product picture on a stage, and use the neon chart series inside it.
Don't
- Don't fill a button with violet or a chart colour. There is no coloured call to action.
- Don't put a drop shadow on a card, button, input or the product window. Only menus, dialogs, sheets and toasts float.
- Don't round past 12px, and don't put a pill on a button, input or badge.
- Don't reuse the magenta cloud. It lives behind the hero picture, the closing horizon is its only echo, and it never sits behind text.
- Don't colour running text. Body copy is white, bone or grey.
- Don't add a grey band or a coloured section background to the landing page.
- Don't show customer logos in colour. They stay muted grey until hovered.
- Don't set headings in 600 or bold, and don't add a third family.
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 saturated accent.
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 Midnight
The builder opens with Midnight picked. Pick your batteries and the design is applied to every template before the zip is built.
