
Vercel
The hard-edged monochrome standard for developer infrastructure — pure black on pure white (and the documented inverse), the Geist typeface at confident weights, one classic blue (#0070f3) for links and focus, and the famous develop/preview/ship tri-color gradient as the only expressive moment. Surfaces separate by hairlines and a precise layered shadow scale rather than color; radii stay tight (6px controls, 12px cards) with pills reserved for badges and theme toggles. The system reads as engineering certainty — maximal contrast, minimal palette, typography doing all the talking.
---
version: alpha
name: Vercel-design-analysis
description: The hard-edged monochrome standard for developer infrastructure — pure black on pure white (and the documented inverse), the Geist typeface at confident weights, one classic blue (#0070f3) for links and focus, and the famous develop/preview/ship tri-color gradient as the only expressive moment. Surfaces separate by hairlines and a precise layered shadow scale rather than color; radii stay tight (6px controls, 12px cards) with pills reserved for badges and theme toggles. The system reads as engineering certainty — maximal contrast, minimal palette, typography doing all the talking.
colors:
ink: "#000000"
body: "#444444"
muted: "#666666"
quiet: "#888888"
faint: "#999999"
canvas: "#ffffff"
surface: "#fafafa"
surface-raised: "#f5f5f5"
hairline: "#eaeaea"
hairline-strong: "#cccccc"
inverse: "#000000"
on-inverse: "#ffffff"
blue: "#0070f3"
develop-blue: "#0a72ef"
preview-pink: "#de1d8d"
ship-coral: "#ff5b4f"
gradient-purple: "#7928ca"
warning: "#f59e0b"
error: "#ef4444"
colors-dark:
ink: "#ededed"
body: "#a1a1a1"
muted: "#878787"
canvas: "#000000"
surface: "#0a0a0a"
surface-raised: "#111111"
hairline: "#333333"
inverse: "#ffffff"
on-inverse: "#000000"
typography:
display-xl:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 72px
fontWeight: 600
lineHeight: 1.05
letterSpacing: -0.035em
display-lg:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 48px
fontWeight: 600
lineHeight: 1.08
letterSpacing: -0.03em
display-md:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 32px
fontWeight: 600
lineHeight: 1.15
letterSpacing: -0.02em
title-lg:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 24px
fontWeight: 600
lineHeight: 1.3
letterSpacing: -0.01em
title-md:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 20px
fontWeight: 600
lineHeight: 1.4
letterSpacing: 0
body-lg:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 18px
fontWeight: 400
lineHeight: 1.6
letterSpacing: 0
body-md:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 16px
fontWeight: 400
lineHeight: 1.6
letterSpacing: 0
body-sm:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 14px
fontWeight: 400
lineHeight: 1.55
letterSpacing: 0
caption:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 13px
fontWeight: 500
lineHeight: 1.4
letterSpacing: 0
code:
fontFamily: "Geist Mono, ui-monospace, SFMono-Regular, monospace"
fontSize: 14px
fontWeight: 400
lineHeight: 1.6
letterSpacing: 0
button:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 14px
fontWeight: 500
lineHeight: 1
letterSpacing: 0
nav-link:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 14px
fontWeight: 400
lineHeight: 1.4
letterSpacing: 0
rounded:
xs: 2px
sm: 4px
md: 6px
lg: 8px
xl: 12px
xxl: 16px
pill: 9999px
full: 9999px
spacing:
xs: 8px
sm: 12px
md: 16px
lg: 24px
xl: 32px
xxl: 48px
section: 96px
section-lg: 128px
components:
button-primary:
backgroundColor: "{colors.inverse}"
textColor: "{colors.on-inverse}"
typography: "{typography.button}"
rounded: "{rounded.md}"
padding: 0 14px
height: 40px
button-secondary:
backgroundColor: "{colors.canvas}"
textColor: "{colors.body}"
typography: "{typography.button}"
rounded: "{rounded.md}"
padding: 0 14px
height: 40px
text-link:
backgroundColor: transparent
textColor: "{colors.blue}"
typography: "{typography.body-md}"
top-nav:
backgroundColor: "{colors.canvas}"
textColor: "{colors.body}"
typography: "{typography.nav-link}"
height: 64px
hero-band:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.display-xl}"
padding: 128px
gradient-headline:
backgroundColor: transparent
textColor: "{colors.ink}"
typography: "{typography.display-xl}"
feature-card:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.title-md}"
rounded: "{rounded.xl}"
padding: 24px
product-frame:
backgroundColor: "{colors.surface}"
rounded: "{rounded.xl}"
code-block:
backgroundColor: "{colors.surface}"
textColor: "{colors.ink}"
typography: "{typography.code}"
rounded: "{rounded.lg}"
padding: 16px
terminal-block:
backgroundColor: "{colors.inverse}"
textColor: "{colors.on-inverse}"
typography: "{typography.code}"
rounded: "{rounded.lg}"
padding: 16px
badge-pill:
backgroundColor: "{colors.surface-raised}"
textColor: "{colors.body}"
typography: "{typography.caption}"
rounded: "{rounded.pill}"
padding: 2px 10px
text-input:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.body-sm}"
rounded: "{rounded.md}"
padding: 0 12px
height: 40px
stat-highlight:
backgroundColor: transparent
textColor: "{colors.ink}"
typography: "{typography.display-md}"
footer:
backgroundColor: "{colors.canvas}"
textColor: "{colors.muted}"
typography: "{typography.body-sm}"
padding: 64px
---
## Overview
Vercel's marketing surface is the purest monochrome system in developer infrastructure: black ink on white canvas, inverted wholesale in the documented dark theme. Color is rationed to one functional blue (`{colors.blue}` — #0070f3, links and focus rings) and the brand's tri-color moment — the **develop / preview / ship** gradient trio (`{colors.develop-blue}`, `{colors.preview-pink}`, `{colors.ship-coral}`, with `{colors.gradient-purple}` in legacy gradients) that paints exactly one headline per page.
Typography is **Geist** (Vercel's own open-source face) at semibold 600 for every display size with tightening negative tracking; body text drops to the gray ramp (`{colors.body}` #444 → `{colors.quiet}` #888) rather than softening weight. Depth comes from an unusually precise **layered shadow scale** (their `ds-shadow-*` tokens stack 1px borders with 2–32px diffuse layers) and hairlines — never from colored surfaces.
**Key Characteristics:**
- Pure #000 on #fff, with a documented full dark inverse (`colors-dark`) — the rare marketing site with a real two-theme system.
- Geist at 600 for all display type; tracking from -0.02em to -0.035em as size grows; body at 400/1.6.
- One blue for interaction (`{colors.blue}`); the tri-color gradient for exactly one hero headline; everything else grayscale.
- The accents ramp (#fafafa → #eaeaea → #999 → #666 → #444 → #111) is the entire surface-and-text hierarchy.
- Radius discipline: `{rounded.md}` (6px) for buttons/inputs, `{rounded.xl}` (12px) for cards/frames; pills only for badges.
- Black terminal blocks (`{component.terminal-block}`) and light code panels alternate; triangle mark and product screenshots carry the visuals.
- 40px control height across buttons and inputs; 64px nav; 96–128px section rhythm.
## Colors
### Brand & Accent
- **Blue** (`{colors.blue}` — #0070f3): links, focus rings, primary interactive accents. The only persistent color.
- **Develop / Preview / Ship** (`{colors.develop-blue}` #0a72ef, `{colors.preview-pink}` #de1d8d, `{colors.ship-coral}` #ff5b4f): the brand gradient trio for the hero headline treatment (`{component.gradient-headline}`); `{colors.gradient-purple}` (#7928ca) survives in legacy gradient pairings.
- **Semantic**: `{colors.warning}` #f59e0b, `{colors.error}` #ef4444 — product UI and callouts only.
### Surface & Text (the gray ramp)
- **Canvas** #ffffff; **Surface** `{colors.surface}` #fafafa (alt bands, code panels); **Surface Raised** #f5f5f5 (badges, table headers).
- **Hairline** `{colors.hairline}` #eaeaea (+ `{colors.hairline-strong}` #cccccc for emphasis borders).
- **Ink** #000000 for headlines and buttons; **Body** #444444; **Muted** #666666; **Quiet** #888888; **Faint** #999999 for metadata.
- **Inverse pair** (`{colors.inverse}` / `{colors.on-inverse}`): black buttons and terminal blocks on light; flips in dark.
### Documented dark theme (`colors-dark`)
True inverse, not a tint: canvas #000000, surface #0a0a0a, raised #111111, hairline #333333, ink #ededed, body #a1a1a1, muted #878787; the inverse pair flips to white-on-black. Blue stays #0070f3 in both themes.
## Typography
### Font Family
**Geist** (and **Geist Mono** for code) — Vercel's own typeface, released open-source under SIL OFL, so no substitute is required: use Geist itself. Fallback stack: Inter, then system sans.
### Hierarchy
| Token | Size | Weight | Line Height | Letter Spacing | Use |
|---|---|---|---|---|---|
| `{typography.display-xl}` | 72px† | 600 | 1.05 | -0.035em | Homepage h1 (fluid 24–72px via clamp) |
| `{typography.display-lg}` | 48px | 600 | 1.08 | -0.03em | Section heads |
| `{typography.display-md}` | 32px | 600 | 1.15 | -0.02em | Sub-section heads, stats |
| `{typography.title-lg}` | 24px | 600 | 1.3 | -0.01em | Card titles |
| `{typography.title-md}` | 20px | 600 | 1.4 | 0 | Feature titles |
| `{typography.body-lg}` | 18px | 400 | 1.6 | 0 | Hero sub-copy |
| `{typography.body-md}` | 16px | 400 | 1.6 | 0 | Running text |
| `{typography.body-sm}` | 14px | 400 | 1.55 | 0 | Secondary copy, footer |
| `{typography.caption}` | 13px | 500 | 1.4 | 0 | Badges, labels |
| `{typography.code}` | 14px | 400 | 1.6 | 0 | Code/terminal — Geist Mono |
| `{typography.button}` | 14px | 500 | 1.0 | 0 | Button labels |
| `{typography.nav-link}` | 14px | 400 | 1.4 | 0 | Nav items |
† Their hero size is literally `clamp(24px, …, 72px)` in CSS — 72px is the desktop ceiling.
### Principles
Weight 600 owns every display size — no 700s, no light display cuts. Hierarchy below the display level is carried by the gray ramp (#000 → #444 → #666 → #888), not by weight changes. Buttons and labels take 500.
### Note on Font Substitutes
None needed — Geist is freely available (SIL OFL). If unavailable in an environment, **Inter** at the same weights with -0.02em display tracking is the closest drop-in.
## Layout
### Spacing System
- 8px grid: `{spacing.xs}` 8 · `{spacing.sm}` 12 · `{spacing.md}` 16 · `{spacing.lg}` 24 · `{spacing.xl}` 32 · `{spacing.xxl}` 48 · `{spacing.section}` 96 · `{spacing.section-lg}` 128.
- Controls: 40px height, 12–14px horizontal padding. Cards pad `{spacing.lg}`.
### Grid & Container
- Max content ~1080px; hero text centered with the product/terminal demo below.
- Feature grids 2–3-up `{component.feature-card}` separated by hairlines (grid-with-borders pattern, not floating cards).
- Footer: 4–5 link columns + theme toggle (pill with sun/moon/system segments).
### Whitespace Philosophy
Engineering-spec spacing: consistent 8px multiples, no optical improvisation. Sections breathe at 96–128px while in-card density stays tight (16–24px).
## Elevation & Depth
| Level | Treatment | Use |
|---|---|---|
| Flat | none | Most bands and text blocks |
| Hairline | 1px #eaeaea (light) / #333 (dark) | Card grid separators, inputs, nav edge |
| Shadow scale | layered `0 0 0 1px` border-shadow + 2xs→2xl diffuse stack | Cards, dropdowns, tooltips — each step adds one soft layer |
| Inverse block | solid #000 (light) / #fff (dark) | Terminal blocks, primary buttons |
The signature: shadows always include a 1px border layer (`0 0 0 1px rgba(0,0,0,.08)`) so elevation never loses its crisp edge.
## Shapes
| Token | Value | Use |
|---|---|---|
| `{rounded.xs}` 2px / `{rounded.sm}` 4px | micro-controls, checkboxes |
| `{rounded.md}` | 6px | Buttons, inputs, selects — the workhorse |
| `{rounded.lg}` | 8px | Code blocks, small panels |
| `{rounded.xl}` | 12px | Cards, product frames |
| `{rounded.xxl}` | 16px | Large media frames |
| `{rounded.pill}` | 9999px | Badges, theme toggle |
| `{rounded.full}` | 9999px / 50% | Avatars |
## Components
**`top-nav`** — White (or black, in dark) 64px bar, triangle logo + wordmark left, product menu center-left in `{typography.nav-link}`, right cluster "Log In" `{component.button-secondary}` + "Sign Up" `{component.button-primary}`. Hairline bottom edge.
**`button-primary`** — Inverse block: `{colors.inverse}` background, `{colors.on-inverse}` label, 40px, `{rounded.md}`, `{typography.button}`. The active/pressed state deepens to near-black gray (`{colors.body}`-adjacent) rather than changing hue.
**`button-secondary`** — Canvas background, `{colors.body}` label, 1px `{colors.hairline}` border, same geometry. Hover ink: label darkens to `{colors.ink}` (documented as state direction, not styling).
**`text-link`** — `{colors.blue}` inline links, no underline at rest.
**`hero-band`** — Centered display-xl headline (often `{component.gradient-headline}` with the tri-color treatment), body-lg sub-copy in `{colors.muted}`, button pair, then a `{component.product-frame}` or `{component.terminal-block}` demo.
**`gradient-headline`** — The brand moment: heading text filled with the develop→preview→ship gradient sweep (blue → pink → coral). One per page, hero only.
**`feature-card`** — White card in hairline-separated grids: icon, `{typography.title-md}`, body-sm copy in `{colors.muted}`; `{rounded.xl}` with the bordered-shadow treatment when floating.
**`product-frame`** — Dashboard/deploy screenshots in `{colors.surface}` frames, `{rounded.xl}`, layered shadow.
**`code-block` / `terminal-block`** — Light gray panel for code samples; solid black terminal with white text and `▲ ~ vercel deploy`-style prompt lines. Both `{rounded.lg}`, `{typography.code}`.
**`badge-pill`** — `{colors.surface-raised}` pill, caption type: "New", framework logos, changelog tags.
**`text-input`** — 40px, `{rounded.md}`, hairline border, focus ring in `{colors.blue}`.
**`stat-highlight`** — Display-md numbers in pure ink with muted captions.
**`footer`** — Light canvas, hairline top, 4–5 columns body-sm in `{colors.muted}`, theme toggle pill bottom-left, triangle mark.
## Do's and Don'ts
### Do
- Keep it two-tone: ink on canvas, inverted in dark. Let the gray ramp do every hierarchy job.
- Reserve `{colors.blue}` for links/focus; reserve the tri-color gradient for one hero headline.
- Use the bordered-shadow recipe (1px ring + soft layers) for anything elevated.
- Set all display type in Geist 600 with negative tracking; never bold to 700.
- Keep controls at 40px/6px-radius; pills are for badges and toggles only.
- Alternate black terminal blocks with light panels to pace developer-content pages.
### Don't
- Don't introduce colored surfaces — color appears in text, links, and the single gradient, never as backgrounds.
- Don't use off-blacks for primary surfaces in light mode; canvas is #fff and ink is #000 (the dark theme has its own documented values).
- Don't round cards past 16px or square off buttons below 4px.
- Don't use drop shadows without the 1px border layer — floating blur without an edge reads off-system.
- Don't mix gradient colors into UI states (the pink/coral are brand, not semantic).
## Responsive Behavior
### Breakpoints
| Name | Width | Key Changes |
|---|---|---|
| Mobile | < 640px | Hamburger nav; hero clamps toward 24–32px; grids 1-up; terminal blocks full-bleed |
| Tablet | 640–1024px | 2-up grids; nav keeps core items + CTA |
| Desktop | 1024–1440px | Full layout, 3-up grids |
| Wide | > 1440px | Content capped ~1080px |
### Touch Targets
Buttons/inputs hold 40px (44px effective with padding on touch); nav rows expand to full-width sheets on mobile.
### Collapsing Strategy
Hero type is fluid (`clamp(24px → 72px)`); grids drop columns before shrinking type; hairline-separated grids become stacked hairline rows.
## Iteration Guide
1. One component at a time by key (`{component.terminal-block}`, `{component.gradient-headline}`).
2. Variants are separate entries; no hover styling documented (state directions only).
3. `{token.refs}` everywhere — never inline hex.
4. Need emphasis? Step the gray ramp before adding color; color means blue, and blue means interactive.
5. Dark mode = the documented `colors-dark` inverse; never invent intermediate grays.
6. The gradient budget is one headline. A second gradient on the page is off-system.
## Known Gaps
- **Dark values partially from the published Geist system**: light values were captured from vercel.com CSS (`accents-1..8`, shadows, blue); the dark set documents Vercel's well-known inverse (#000/#0a0a0a/#111/#333/#ededed/#a1a1a1) but a full dark-mode CSS capture was not performed this pass — re-capture with forced `prefers-color-scheme: dark` planned.
- **Geist font naming**: served via next/font with hashed family names; documented as "Geist" per their published system rather than from the CSS string.
- **Display sizes are fluid** (`clamp(24px, …, 72px)` captured literally); intermediate viewport behavior not tabulated.
- **Shadow recipes**: the `ds-shadow-*` stack is documented directionally in Elevation; exact per-level values live in their CSS and were captured only partially.
- **Gradient angles/stops** for develop/preview/ship vary by campaign; colors documented, geometry not.
- **Dashboard/product UI** (the Vercel dashboard's Geist application) is a separate dashboard-surface analysis — high-value future entry.
<!-- Documented by duply · real-world design systems as ready-to-use DESIGN.md for AI coding agents · https://duply.ai/vercel/design-md -->
Color Palette
Accent
Neutrals
Documented dark theme
Typography
display-xl72px · 600 · 1.05
The quick brown fox jumpsdisplay-lg48px · 600 · 1.08
The quick brown fox jumpsdisplay-md32px · 600 · 1.15
The quick brown fox jumpstitle-lg24px · 600 · 1.3
The quick brown fox jumpstitle-md20px · 600 · 1.4
The quick brown fox jumpsbody-lg18px · 400 · 1.6
The quick brown fox jumpsSpacing & Shape
Spacing
| Name | Value | Preview |
|---|---|---|
| xs | 8px | |
| sm | 12px | |
| md | 16px | |
| lg | 24px | |
| xl | 32px | |
| xxl | 48px | |
| section | 96px | |
| section-lg | 128px |
Border Radius
| Name | Value | Preview |
|---|---|---|
| xs | 2px | |
| sm | 4px | |
| md | 6px | |
| lg | 8px | |
| xl | 12px | |
| xxl | 16px | |
| pill | 9999px | |
| full | 9999px |
More like this
---
version: alpha
name: Vercel-design-analysis
description: The hard-edged monochrome standard for developer infrastructure — pure black on pure white (and the documented inverse), the Geist typeface at confident weights, one classic blue (#0070f3) for links and focus, and the famous develop/preview/ship tri-color gradient as the only expressive moment. Surfaces separate by hairlines and a precise layered shadow scale rather than color; radii stay tight (6px controls, 12px cards) with pills reserved for badges and theme toggles. The system reads as engineering certainty — maximal contrast, minimal palette, typography doing all the talking.
colors:
ink: "#000000"
body: "#444444"
muted: "#666666"
quiet: "#888888"
faint: "#999999"
canvas: "#ffffff"
surface: "#fafafa"
surface-raised: "#f5f5f5"
hairline: "#eaeaea"
hairline-strong: "#cccccc"
inverse: "#000000"
on-inverse: "#ffffff"
blue: "#0070f3"
develop-blue: "#0a72ef"
preview-pink: "#de1d8d"
ship-coral: "#ff5b4f"
gradient-purple: "#7928ca"
warning: "#f59e0b"
error: "#ef4444"
colors-dark:
ink: "#ededed"
body: "#a1a1a1"
muted: "#878787"
canvas: "#000000"
surface: "#0a0a0a"
surface-raised: "#111111"
hairline: "#333333"
inverse: "#ffffff"
on-inverse: "#000000"
typography:
display-xl:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 72px
fontWeight: 600
lineHeight: 1.05
letterSpacing: -0.035em
display-lg:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 48px
fontWeight: 600
lineHeight: 1.08
letterSpacing: -0.03em
display-md:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 32px
fontWeight: 600
lineHeight: 1.15
letterSpacing: -0.02em
title-lg:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 24px
fontWeight: 600
lineHeight: 1.3
letterSpacing: -0.01em
title-md:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 20px
fontWeight: 600
lineHeight: 1.4
letterSpacing: 0
body-lg:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 18px
fontWeight: 400
lineHeight: 1.6
letterSpacing: 0
body-md:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 16px
fontWeight: 400
lineHeight: 1.6
letterSpacing: 0
body-sm:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 14px
fontWeight: 400
lineHeight: 1.55
letterSpacing: 0
caption:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 13px
fontWeight: 500
lineHeight: 1.4
letterSpacing: 0
code:
fontFamily: "Geist Mono, ui-monospace, SFMono-Regular, monospace"
fontSize: 14px
fontWeight: 400
lineHeight: 1.6
letterSpacing: 0
button:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 14px
fontWeight: 500
lineHeight: 1
letterSpacing: 0
nav-link:
fontFamily: "Geist, Inter, sans-serif"
fontSize: 14px
fontWeight: 400
lineHeight: 1.4
letterSpacing: 0
rounded:
xs: 2px
sm: 4px
md: 6px
lg: 8px
xl: 12px
xxl: 16px
pill: 9999px
full: 9999px
spacing:
xs: 8px
sm: 12px
md: 16px
lg: 24px
xl: 32px
xxl: 48px
section: 96px
section-lg: 128px
components:
button-primary:
backgroundColor: "{colors.inverse}"
textColor: "{colors.on-inverse}"
typography: "{typography.button}"
rounded: "{rounded.md}"
padding: 0 14px
height: 40px
button-secondary:
backgroundColor: "{colors.canvas}"
textColor: "{colors.body}"
typography: "{typography.button}"
rounded: "{rounded.md}"
padding: 0 14px
height: 40px
text-link:
backgroundColor: transparent
textColor: "{colors.blue}"
typography: "{typography.body-md}"
top-nav:
backgroundColor: "{colors.canvas}"
textColor: "{colors.body}"
typography: "{typography.nav-link}"
height: 64px
hero-band:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.display-xl}"
padding: 128px
gradient-headline:
backgroundColor: transparent
textColor: "{colors.ink}"
typography: "{typography.display-xl}"
feature-card:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.title-md}"
rounded: "{rounded.xl}"
padding: 24px
product-frame:
backgroundColor: "{colors.surface}"
rounded: "{rounded.xl}"
code-block:
backgroundColor: "{colors.surface}"
textColor: "{colors.ink}"
typography: "{typography.code}"
rounded: "{rounded.lg}"
padding: 16px
terminal-block:
backgroundColor: "{colors.inverse}"
textColor: "{colors.on-inverse}"
typography: "{typography.code}"
rounded: "{rounded.lg}"
padding: 16px
badge-pill:
backgroundColor: "{colors.surface-raised}"
textColor: "{colors.body}"
typography: "{typography.caption}"
rounded: "{rounded.pill}"
padding: 2px 10px
text-input:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.body-sm}"
rounded: "{rounded.md}"
padding: 0 12px
height: 40px
stat-highlight:
backgroundColor: transparent
textColor: "{colors.ink}"
typography: "{typography.display-md}"
footer:
backgroundColor: "{colors.canvas}"
textColor: "{colors.muted}"
typography: "{typography.body-sm}"
padding: 64px
---
## Overview
Vercel's marketing surface is the purest monochrome system in developer infrastructure: black ink on white canvas, inverted wholesale in the documented dark theme. Color is rationed to one functional blue (`{colors.blue}` — #0070f3, links and focus rings) and the brand's tri-color moment — the **develop / preview / ship** gradient trio (`{colors.develop-blue}`, `{colors.preview-pink}`, `{colors.ship-coral}`, with `{colors.gradient-purple}` in legacy gradients) that paints exactly one headline per page.
Typography is **Geist** (Vercel's own open-source face) at semibold 600 for every display size with tightening negative tracking; body text drops to the gray ramp (`{colors.body}` #444 → `{colors.quiet}` #888) rather than softening weight. Depth comes from an unusually precise **layered shadow scale** (their `ds-shadow-*` tokens stack 1px borders with 2–32px diffuse layers) and hairlines — never from colored surfaces.
**Key Characteristics:**
- Pure #000 on #fff, with a documented full dark inverse (`colors-dark`) — the rare marketing site with a real two-theme system.
- Geist at 600 for all display type; tracking from -0.02em to -0.035em as size grows; body at 400/1.6.
- One blue for interaction (`{colors.blue}`); the tri-color gradient for exactly one hero headline; everything else grayscale.
- The accents ramp (#fafafa → #eaeaea → #999 → #666 → #444 → #111) is the entire surface-and-text hierarchy.
- Radius discipline: `{rounded.md}` (6px) for buttons/inputs, `{rounded.xl}` (12px) for cards/frames; pills only for badges.
- Black terminal blocks (`{component.terminal-block}`) and light code panels alternate; triangle mark and product screenshots carry the visuals.
- 40px control height across buttons and inputs; 64px nav; 96–128px section rhythm.
## Colors
### Brand & Accent
- **Blue** (`{colors.blue}` — #0070f3): links, focus rings, primary interactive accents. The only persistent color.
- **Develop / Preview / Ship** (`{colors.develop-blue}` #0a72ef, `{colors.preview-pink}` #de1d8d, `{colors.ship-coral}` #ff5b4f): the brand gradient trio for the hero headline treatment (`{component.gradient-headline}`); `{colors.gradient-purple}` (#7928ca) survives in legacy gradient pairings.
- **Semantic**: `{colors.warning}` #f59e0b, `{colors.error}` #ef4444 — product UI and callouts only.
### Surface & Text (the gray ramp)
- **Canvas** #ffffff; **Surface** `{colors.surface}` #fafafa (alt bands, code panels); **Surface Raised** #f5f5f5 (badges, table headers).
- **Hairline** `{colors.hairline}` #eaeaea (+ `{colors.hairline-strong}` #cccccc for emphasis borders).
- **Ink** #000000 for headlines and buttons; **Body** #444444; **Muted** #666666; **Quiet** #888888; **Faint** #999999 for metadata.
- **Inverse pair** (`{colors.inverse}` / `{colors.on-inverse}`): black buttons and terminal blocks on light; flips in dark.
### Documented dark theme (`colors-dark`)
True inverse, not a tint: canvas #000000, surface #0a0a0a, raised #111111, hairline #333333, ink #ededed, body #a1a1a1, muted #878787; the inverse pair flips to white-on-black. Blue stays #0070f3 in both themes.
## Typography
### Font Family
**Geist** (and **Geist Mono** for code) — Vercel's own typeface, released open-source under SIL OFL, so no substitute is required: use Geist itself. Fallback stack: Inter, then system sans.
### Hierarchy
| Token | Size | Weight | Line Height | Letter Spacing | Use |
|---|---|---|---|---|---|
| `{typography.display-xl}` | 72px† | 600 | 1.05 | -0.035em | Homepage h1 (fluid 24–72px via clamp) |
| `{typography.display-lg}` | 48px | 600 | 1.08 | -0.03em | Section heads |
| `{typography.display-md}` | 32px | 600 | 1.15 | -0.02em | Sub-section heads, stats |
| `{typography.title-lg}` | 24px | 600 | 1.3 | -0.01em | Card titles |
| `{typography.title-md}` | 20px | 600 | 1.4 | 0 | Feature titles |
| `{typography.body-lg}` | 18px | 400 | 1.6 | 0 | Hero sub-copy |
| `{typography.body-md}` | 16px | 400 | 1.6 | 0 | Running text |
| `{typography.body-sm}` | 14px | 400 | 1.55 | 0 | Secondary copy, footer |
| `{typography.caption}` | 13px | 500 | 1.4 | 0 | Badges, labels |
| `{typography.code}` | 14px | 400 | 1.6 | 0 | Code/terminal — Geist Mono |
| `{typography.button}` | 14px | 500 | 1.0 | 0 | Button labels |
| `{typography.nav-link}` | 14px | 400 | 1.4 | 0 | Nav items |
† Their hero size is literally `clamp(24px, …, 72px)` in CSS — 72px is the desktop ceiling.
### Principles
Weight 600 owns every display size — no 700s, no light display cuts. Hierarchy below the display level is carried by the gray ramp (#000 → #444 → #666 → #888), not by weight changes. Buttons and labels take 500.
### Note on Font Substitutes
None needed — Geist is freely available (SIL OFL). If unavailable in an environment, **Inter** at the same weights with -0.02em display tracking is the closest drop-in.
## Layout
### Spacing System
- 8px grid: `{spacing.xs}` 8 · `{spacing.sm}` 12 · `{spacing.md}` 16 · `{spacing.lg}` 24 · `{spacing.xl}` 32 · `{spacing.xxl}` 48 · `{spacing.section}` 96 · `{spacing.section-lg}` 128.
- Controls: 40px height, 12–14px horizontal padding. Cards pad `{spacing.lg}`.
### Grid & Container
- Max content ~1080px; hero text centered with the product/terminal demo below.
- Feature grids 2–3-up `{component.feature-card}` separated by hairlines (grid-with-borders pattern, not floating cards).
- Footer: 4–5 link columns + theme toggle (pill with sun/moon/system segments).
### Whitespace Philosophy
Engineering-spec spacing: consistent 8px multiples, no optical improvisation. Sections breathe at 96–128px while in-card density stays tight (16–24px).
## Elevation & Depth
| Level | Treatment | Use |
|---|---|---|
| Flat | none | Most bands and text blocks |
| Hairline | 1px #eaeaea (light) / #333 (dark) | Card grid separators, inputs, nav edge |
| Shadow scale | layered `0 0 0 1px` border-shadow + 2xs→2xl diffuse stack | Cards, dropdowns, tooltips — each step adds one soft layer |
| Inverse block | solid #000 (light) / #fff (dark) | Terminal blocks, primary buttons |
The signature: shadows always include a 1px border layer (`0 0 0 1px rgba(0,0,0,.08)`) so elevation never loses its crisp edge.
## Shapes
| Token | Value | Use |
|---|---|---|
| `{rounded.xs}` 2px / `{rounded.sm}` 4px | micro-controls, checkboxes |
| `{rounded.md}` | 6px | Buttons, inputs, selects — the workhorse |
| `{rounded.lg}` | 8px | Code blocks, small panels |
| `{rounded.xl}` | 12px | Cards, product frames |
| `{rounded.xxl}` | 16px | Large media frames |
| `{rounded.pill}` | 9999px | Badges, theme toggle |
| `{rounded.full}` | 9999px / 50% | Avatars |
## Components
**`top-nav`** — White (or black, in dark) 64px bar, triangle logo + wordmark left, product menu center-left in `{typography.nav-link}`, right cluster "Log In" `{component.button-secondary}` + "Sign Up" `{component.button-primary}`. Hairline bottom edge.
**`button-primary`** — Inverse block: `{colors.inverse}` background, `{colors.on-inverse}` label, 40px, `{rounded.md}`, `{typography.button}`. The active/pressed state deepens to near-black gray (`{colors.body}`-adjacent) rather than changing hue.
**`button-secondary`** — Canvas background, `{colors.body}` label, 1px `{colors.hairline}` border, same geometry. Hover ink: label darkens to `{colors.ink}` (documented as state direction, not styling).
**`text-link`** — `{colors.blue}` inline links, no underline at rest.
**`hero-band`** — Centered display-xl headline (often `{component.gradient-headline}` with the tri-color treatment), body-lg sub-copy in `{colors.muted}`, button pair, then a `{component.product-frame}` or `{component.terminal-block}` demo.
**`gradient-headline`** — The brand moment: heading text filled with the develop→preview→ship gradient sweep (blue → pink → coral). One per page, hero only.
**`feature-card`** — White card in hairline-separated grids: icon, `{typography.title-md}`, body-sm copy in `{colors.muted}`; `{rounded.xl}` with the bordered-shadow treatment when floating.
**`product-frame`** — Dashboard/deploy screenshots in `{colors.surface}` frames, `{rounded.xl}`, layered shadow.
**`code-block` / `terminal-block`** — Light gray panel for code samples; solid black terminal with white text and `▲ ~ vercel deploy`-style prompt lines. Both `{rounded.lg}`, `{typography.code}`.
**`badge-pill`** — `{colors.surface-raised}` pill, caption type: "New", framework logos, changelog tags.
**`text-input`** — 40px, `{rounded.md}`, hairline border, focus ring in `{colors.blue}`.
**`stat-highlight`** — Display-md numbers in pure ink with muted captions.
**`footer`** — Light canvas, hairline top, 4–5 columns body-sm in `{colors.muted}`, theme toggle pill bottom-left, triangle mark.
## Do's and Don'ts
### Do
- Keep it two-tone: ink on canvas, inverted in dark. Let the gray ramp do every hierarchy job.
- Reserve `{colors.blue}` for links/focus; reserve the tri-color gradient for one hero headline.
- Use the bordered-shadow recipe (1px ring + soft layers) for anything elevated.
- Set all display type in Geist 600 with negative tracking; never bold to 700.
- Keep controls at 40px/6px-radius; pills are for badges and toggles only.
- Alternate black terminal blocks with light panels to pace developer-content pages.
### Don't
- Don't introduce colored surfaces — color appears in text, links, and the single gradient, never as backgrounds.
- Don't use off-blacks for primary surfaces in light mode; canvas is #fff and ink is #000 (the dark theme has its own documented values).
- Don't round cards past 16px or square off buttons below 4px.
- Don't use drop shadows without the 1px border layer — floating blur without an edge reads off-system.
- Don't mix gradient colors into UI states (the pink/coral are brand, not semantic).
## Responsive Behavior
### Breakpoints
| Name | Width | Key Changes |
|---|---|---|
| Mobile | < 640px | Hamburger nav; hero clamps toward 24–32px; grids 1-up; terminal blocks full-bleed |
| Tablet | 640–1024px | 2-up grids; nav keeps core items + CTA |
| Desktop | 1024–1440px | Full layout, 3-up grids |
| Wide | > 1440px | Content capped ~1080px |
### Touch Targets
Buttons/inputs hold 40px (44px effective with padding on touch); nav rows expand to full-width sheets on mobile.
### Collapsing Strategy
Hero type is fluid (`clamp(24px → 72px)`); grids drop columns before shrinking type; hairline-separated grids become stacked hairline rows.
## Iteration Guide
1. One component at a time by key (`{component.terminal-block}`, `{component.gradient-headline}`).
2. Variants are separate entries; no hover styling documented (state directions only).
3. `{token.refs}` everywhere — never inline hex.
4. Need emphasis? Step the gray ramp before adding color; color means blue, and blue means interactive.
5. Dark mode = the documented `colors-dark` inverse; never invent intermediate grays.
6. The gradient budget is one headline. A second gradient on the page is off-system.
## Known Gaps
- **Dark values partially from the published Geist system**: light values were captured from vercel.com CSS (`accents-1..8`, shadows, blue); the dark set documents Vercel's well-known inverse (#000/#0a0a0a/#111/#333/#ededed/#a1a1a1) but a full dark-mode CSS capture was not performed this pass — re-capture with forced `prefers-color-scheme: dark` planned.
- **Geist font naming**: served via next/font with hashed family names; documented as "Geist" per their published system rather than from the CSS string.
- **Display sizes are fluid** (`clamp(24px, …, 72px)` captured literally); intermediate viewport behavior not tabulated.
- **Shadow recipes**: the `ds-shadow-*` stack is documented directionally in Elevation; exact per-level values live in their CSS and were captured only partially.
- **Gradient angles/stops** for develop/preview/ship vary by campaign; colors documented, geometry not.
- **Dashboard/product UI** (the Vercel dashboard's Geist application) is a separate dashboard-surface analysis — high-value future entry.
<!-- Documented by duply · real-world design systems as ready-to-use DESIGN.md for AI coding agents · https://duply.ai/vercel/design-md -->





