Skip to content

Now in the official shadcn registry directory.

Start free
Back to gallery
developer tools · saas · ai

Vercel

The platform landing that doubles as the reference implementation of its own stack — Vercel treats marketing as a living engineering brief. A Geist family trinity (sans, mono, and five decorative pixel cuts) carries the entire typographic personality. Accents come from a Radix-derived semantic palette used like confidence indicators rather than decoration. Elevation runs on a ring-plus-inset shadow grammar that makes every card feel printed. Gradients appear only as 50%-stop solid-colour dot-fill pattern backgrounds, and 96 CSS custom properties are exposed in the cascade as a public token surface.

vercel.comAdded 2026-04-23
Vercel - Desktop

Editorial disclaimer

Editorial note

This entry documents observable design-language patterns for educational transfer and AI-agent briefing. Screenshots and trademarks are property of their respective owners. AI2 Design is not affiliated with or endorsed by the featured brand. Inspiration here is about language and rhythm - do not reproduce brand identity, logo, product copy, or proprietary features.

Fair Use & Gallery Policy
FreePrompt kit

Copy the full design language into your agent

A typed, paste-ready design system brief - philosophy, tokens, rules, techniques, and fitness checks. Drop it into Claude, Cursor, v0 or any coding agent and it builds in Vercel’s language, not just a screenshot.

Paste into your agent. No signup, no cost.
Light-first engineering-as-aesthetic platform landing. Pure white #ffffff canvas. Near-black #171717 primary text doing the dominant reading (measured 1908 occurrences), with a six-stop grey descender ladder (#4d4d4d / #666666 / #808080 / #a8a8a8 / #ebebeb) handling secondary, tertiary and border roles. Typography carries the entire identity: Geist Variable (sans) for voice, Geist Mono for code and tabular proof, Geist Pixel in five decorative cuts (Circle / Grid / Line / Square / Triangle) for craft punctuation. Accents come from a Radix-derived semantic palette (cyan / magenta / red / teal / orange / green) applied like state indicators, never as fills. Elevation is a ring-plus-inset grammar — 1px outer hairline with a 1px inset highlight — that makes every card feel printed rather than floated. Gradients are used only as 50%-stop solid-colour dot-fill pattern backgrounds. Motion splits into three channels: 0.1-0.15s snap chroma for input feedback, cubic-bezier(0.33, 0.12, 0.15, 1) opacity reveals, and 0.2s ease transforms.
Main prompt
Use this capture as a design language transfer brief for my project. Adopt the palette (light-first #ffffff canvas + #171717 primary text + six-stop grey descender ladder + Radix-derived semantic accents used as state indicators), typographic system (Geist Variable as primary sans, Geist Mono for code and tabular data, Geist Pixel reserved for sparse decorative punctuation), 2px base spacing scale with peaks at 2 / 6 / 8 / 12, single 1080px content rail, ring-plus-inset shadow grammar (1px outer hairline plus 1px inset highlight), 50%-stop solid-colour gradient as flat pattern fill, 96-variable open CSS token surface, border-radius double-peak at 4 / 6 px with 64px for large feature cards and 100px pill for indicators, and three-channel motion (0.1-0.15s snap chroma for input, cubic-bezier(0.33, 0.12, 0.15, 1) for opacity reveals, 0.2s ease for transform). Treat this as my project's constitution — every new component should pass as if crafted in the same studio. Apply the language, not the source brand's copy or identity. When I ask you to build a page or component, enforce these rules by default, and call out any decision that deviates.
Layout
Grid
Content width
Bounded
Framing
Flat
Grid strength
Strong

Light-first canvas — pure #ffffff background paired with #171717 near-black primary text doing the dominant reading layer (measured 1908 occurrences). Six-stop grey descender ladder: #4d4d4d (secondary body) → #666666 (muted text) → #808080 (placeholder) → #a8a8a8 (borders) → #ebebeb (light borders / strokes) → #000000 (accent border). Accent palette is Radix-derived semantic — cyan #52aeff, magenta #bd2864, red #e5484d, teal #45dec5, orange #ffb224, green #297a3a — each colour tied to a role (state, category, emphasis) rather than used as decoration. Surface area of accent colour stays below 3% of the viewport.

Mode strategylight-first
  • Primary reading pair: #171717 near-black text on #ffffff background (measured 1888 + 138 occurrences — dominant surface)
  • Secondary descender ladder: #4d4d4d (ready-to-read) → #666666 (muted) → #808080 (placeholder / disabled) — for progressive de-emphasis
  • Border grey stops: #a8a8a8 (emphasised stroke), #ebebeb (default hairline) — the ring that does the elevation work
  • Semantic accent cyan #52aeff for informational state, magenta #bd2864 for editorial emphasis
  • Semantic accent red #e5484d for destructive state, teal #45dec5 for fresh state, orange #ffb224 for warning, green #297a3a for success

Gradients (paste-ready)

linear-gradient(rgb(235, 235, 235), rgb(235, 235, 235) 50%, rgba(0, 0, 0, 0) 0px, rgba(0, 0, 0, 0))
linear-gradient(rgb(212, 238, 247), rgb(212, 238, 247) 50%, rgba(0, 0, 0, 0) 0px, rgba(0, 0, 0, 0))
linear-gradient(rgb(255, 232, 224), rgb(255, 232, 224) 50%, rgba(0, 0, 0, 0) 0px, rgba(0, 0, 0, 0))
  • Primary family: Geist Variable (self-hosted, preloaded from /vc-ap-vercel-marketing/_next/static/media/*.woff2). The family is deployed alongside Geist Mono for code and five Geist Pixel cuts (Circle, Grid, Line, Square, Triangle) for decorative punctuation.
  • Do not introduce a second foundry. The Geist trinity carries every register — voice, proof, craft. Mixing in Inter, SF Pro or any display serif breaks the identity immediately.
  • Observed size ladder: 12 / 13 / 14 / 16 / 18 / 24 / 48 px. Display hero at 48/48 with letter-spacing -2.4px. Display sub at 24/32 with letter-spacing -0.96px. Body at 14-16 with line-height 20-24.
  • Letter-spacing is px, not em: negative at display (-2.4px at 48, -0.96px at 24) to produce optical tightness; normal at body. Never invent intermediate tracking values.
  • Geist Mono reserved for code, kbd, tabular numerics, version strings, hashes, deploy IDs. Body 13-16px with line-height 20px. Never use Mono as a display substitute.
  • Geist Pixel is decorative only — reserve each of the five cuts (Circle / Grid / Line / Square / Triangle) for specific craft moments (pattern tiles, feature dividers, visual emphasis). Pasted on running text it is costume.
  • Paragraph max 55-65 ch at body 14-16px — echoes the 1080px rail when wrapped in the main container.
  • 2px base unit. Observed scale: 2 / 4 / 6 / 8 / 10 / 12 / 14 / 16 / 18 / 20 / 24 / 32 px, dominated by 2 (freq 361) / 12 (301) / 8 (277) / 6 (204).
  • Flex gaps: 8px (freq 73), 6px (69), 12px (43), 4px (15), 16px (13). Keep gutters in multiples of 2.
  • Container: single 1080px primary rail (maxWidthPx 1080, freq 6). Do not break the rail except for full-bleed feature strips or hero-scale assets.
  • Card padding scale: 12 / 16 / 20 / 24 px, aligned to gutter steps.
  • Section vertical rhythm: 32 / 48 / 64 px desktop; 24 / 32 / 48 px mobile.
Surface styleHairline
  • Default cards: shadow-xs three-layer ring + subtle drop + inset highlight — 'rgba(0,0,0,0.08) 0px 0px 0px 1px, rgba(0,0,0,0.04) 0px 2px 2px 0px, rgb(250,250,250) 0px 0px 0px 1px inset'. The inset highlight is the signature — it makes the card feel printed rather than floated.
  • Emphasised cards: shadow-lg 'rgba(0,0,0,0.08) 0px 0px 0px 1px, rgb(250,250,250) 0px 0px 0px 1px' — simpler ring + inset without the drop. Use when the card should feel set into the page rather than raised.
  • Dividers / inset outline: shadow-outline 'rgb(234,234,234) 0px -1px 0px 0px inset' — a single inset hairline on the bottom edge, used under header rows and section tops.
  • Inner shadow for pressed / input state: 'rgba(0,0,0,0.04) 0px 1px 2px 0px' — the only inner-drop shadow in the grammar.
  • Do not substitute a large blur drop-shadow for any of these — the identity breaks the instant cards start to float.

Techniques

Ring + inset highlight card

Every primary card uses a 1px outer ring (rgba(0,0,0,0.08)) plus a 1px inset highlight (rgb(250,250,250)) to feel printed. The combination produces a card that reads as set into the surface while still being visually separated.

Inset bottom divider

Section dividers use 'rgb(234,234,234) 0px -1px 0px 0px inset' — a single inset hairline rather than a border, so the divider aligns to pixel grid without adding layout height.

Radii2 / 4 / 6 / 8 / 12 / 64 / 100Icon treatmentStroke-forward, 1.5-2px weightIcon setsLucide, Phosphor, Custom Geist glyphs
  • Double-peak base: 4px (freq 41) and 6px (freq 45) cover most surfaces. Buttons and inline inputs use 6, chips and badges use 4.
  • Large cards / feature blocks use 12px; extra-large feature cards and pattern tiles use 64px (freq 6) — the distinctive 3xl.
  • Full pill (100px radius, freq 11) reserved for indicator badges, hover dots, and tag-sized controls.
  • Do not use radii between 12 and 64 — the gap is intentional. Anything in-between reads as indecisive.
  • Border widths: 1px default; 2px only for focus emphasis or active-state outlines.
  • ring-inset-card
    backgroundColor
    #ffffff
    textColor
    #171717
    radius
    12px
    padding
    20px
    border
    none
    boxShadow
    rgba(0, 0, 0, 0.08) 0px 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 2px 2px 0px, rgb(250, 250, 250) 0px 0px 0px 1px inset
    fontFamily
    Geist Variable, ui-sans-serif

    Tailwind

    rounded-xl bg-white p-5 text-[#171717] shadow-[rgba(0,0,0,0.08)_0px_0px_0px_1px,rgba(0,0,0,0.04)_0px_2px_2px_0px,rgb(250,250,250)_0px_0px_0px_1px_inset]
  • dot-fill-feature-tile
    backgroundColor
    #ffffff
    backgroundImage
    linear-gradient(rgb(212, 238, 247), rgb(212, 238, 247) 50%, rgba(0, 0, 0, 0) 0px, rgba(0, 0, 0, 0))
    radius
    64px
    padding
    32px
    textColor
    #171717
    border
    1px solid #ebebeb

    Tailwind

    rounded-[64px] border border-[#ebebeb] p-8 text-[#171717] bg-[linear-gradient(rgb(212,238,247),rgb(212,238,247)_50%,rgba(0,0,0,0)_0px,rgba(0,0,0,0))]
  • snap-chroma-button
    backgroundColor
    #171717
    textColor
    #ffffff
    radius
    6px
    padding
    8px 14px
    border
    none
    boxShadow
    rgba(0, 0, 0, 0.04) 0px 2px 2px 0px
    fontFamily
    Geist Variable
    fontSize
    14px
    fontWeight
    500
    transition
    color 0.1s ease, background 0.15s ease-in-out

    Tailwind

    inline-flex min-h-[36px] items-center gap-1.5 rounded-md bg-[#171717] px-3.5 py-2 text-[14px] font-medium text-white shadow-[rgba(0,0,0,0.04)_0px_2px_2px_0px] transition-[color,background] duration-100 ease-in-out hover:bg-[#4d4d4d]
  • pill-state-indicator
    backgroundColor
    #52aeff
    textColor
    #ffffff
    radius
    100px
    padding
    2px 8px
    border
    none
    fontFamily
    Geist Mono
    fontSize
    12px
    fontWeight
    500

    Tailwind

    inline-flex items-center rounded-full bg-[#52aeff] px-2 py-0.5 font-mono text-[12px] font-medium text-white
  • link-inline
    color
    #0070f3
    textDecoration
    none
    textUnderlineOffset
    3px
    textDecorationThickness
    1px
    transition
    color 100ms ease, text-decoration-color 100ms ease

    Tailwind

    text-[#0070f3] no-underline underline-offset-[3px] transition-colors duration-100 ease-[cubic-bezier(0.33,0.12,0.15,1)] hover:underline hover:decoration-[#0070f3] focus-visible:outline-none focus-visible:underline focus-visible:decoration-[#0070f3]
LevelexpressiveDurations0.09s / 0.1s / 0.15s / 0.2s / 0.4s

Easings

easeease-in-outcubic-bezier(0.33, 0.12, 0.15, 1)cubic-bezier(0.4, 0, 0.2, 1)cubic-bezier(0.39, 0.18, 0.17, 0.99)
HoverChroma (color / border-color / background / box-shadow): 0.1-0.15s ease, Transform (translate / rotate / scale): 0.2s ease, Opacity reveals: 0.4s cubic-bezier(0.33, 0.12, 0.15, 1)

Scroll patterns

  • Opacity fade with cubic-bezier(0.33, 0.12, 0.15, 1) over 0.4s for below-the-fold sections
  • No parallax. Transform limited to 0.2s ease reveals.
  • Three-channel motion rule: chroma is snap (0.1-0.15s ease), transform is swift (0.2s ease), opacity is theatrical (0.4s cubic-bezier(0.33, 0.12, 0.15, 1)).
  • Easing palette captured: ease + ease-in-out CSS keywords plus three custom cubic-bezier curves — cubic-bezier(0.33, 0.12, 0.15, 1) for opacity reveals, cubic-bezier(0.4, 0, 0.2, 1) and cubic-bezier(0.39, 0.18, 0.17, 0.99) for supporting state transitions. Do not substitute spring or bounce easings.
  • Hover feedback MUST land under 150ms — that is the tempo signature.
  • Opacity reveals use the custom cubic-bezier only. Swapping to ease-in-out flattens the identity.
  • Respect prefers-reduced-motion — disable cubic-bezier reveals and collapse chroma transitions to 0ms.
  • Hover states escalate through the grey ladder — #171717 → #4d4d4d on text, border thickens from #ebebeb to #a8a8a8 on cards. Elevation stays constant; only chroma shifts.
  • Active / pressed state uses the inner drop-shadow 'rgba(0,0,0,0.04) 0px 1px 2px 0px' instead of a translate.
  • Focus rings use a 2px solid ring in the semantic accent cyan #52aeff for form fields, #171717 for primary controls.
  • Status badges use the pill + Geist Mono combination with semantic colour — red for error, green for healthy, orange for warning, cyan for informational.
  • Tooltips open under 150ms with chroma-only animation — never translate, never fade in.
Approachdesktop-first

Desktop-first because the audience is developers on wide displays. The 1080px rail is the primary anchor at every size — mobile reflows into a single narrow column without re-architecting the layout. Thirty measured media queries confirm per-breakpoint adjustments rather than fluid guessing.

  • Breakpoints: sm 640 / md 768 / lg 1024 / xl 1280 / 2xl 1536 — standard Tailwind ladder.
  • The 1080px rail holds from lg upwards. Below lg, content reflows to a single 16-24px gutter column.
  • Typography scales proportionally — 48/48 hero drops to 32/36, 24/32 sub drops to 20/28. Letter-spacing compensates (less negative at smaller sizes).
  • Tap targets minimum 40×40 on pointer; 44×44 on touch.
  • Hide-on-mobile is banned — controls reflow, they do not disappear.
  • Primary reading pair #171717 on #ffffff = 16:1 (AAA). Secondary #4d4d4d on white = 8.7:1 (AAA). Muted #666666 = 5.7:1 (AA).
  • Semantic accents must pair with text at AA minimum — cyan #52aeff on #ffffff fails for normal text; use as background-plus-icon only, or thicken text to 18px bold.
  • Focus rings mandatory: 2px solid #52aeff for form fields, 2px solid #171717 for primary controls, offset 2px.
  • Do not rely on colour alone for state — pair every Radix semantic colour with an icon or label.
  • prefers-reduced-motion must disable cubic-bezier opacity reveals and collapse chroma transitions to 0ms.
  • Geist Pixel must not be used for critical reading content — it is decorative.
  • Tap targets minimum 44×44 on touch, 40×40 on pointer.
Geist font familyRadix ColorsCSS custom properties

Self-hosted variable woff2 font delivery — 8 files preloaded (Geist, Geist Mono, Geist Pixel Circle / Grid / Line / Square / Triangle) from Vercel's /_next/static/media/ pipeline with 38 @font-face declarations in the CSSOM. Palette mapped to Radix Colors semantic scale (the 10 / 11 / 12 numbering on accent colour names matches Radix step conventions). 96 CSS custom properties exposed in the cascade — the token surface is deliberately public.

  • Preload each Geist woff2 with <link rel='preload' as='font' type='font/woff2' crossorigin>
  • Adopt Radix Colors or a compatible semantic palette for accents; do not invent arbitrary colours
  • Expose design tokens as CSS custom properties — let the cascade be legible
  • No runtime motion library required — all motion rides on CSS transitions. If a spring is desired, port to Framer Motion with an explicit cubic-bezier equivalent
  • Icons stroke-based at 1.5-2px weight; Geist Pixel is reserved for decorative punctuation only
  • Use Geist Variable + Geist Mono as the entire typographic backbone.
  • Hold a pure-white canvas and let grey descender do the reading work.
  • Apply accent colour as confidence — state, category, emphasis — never as surface paint.
  • Use ring + inset shadow for every card that needs to feel set into the page.
  • Reach for 50%-stop solid-colour gradients when feature tiles need pattern ink.
  • Keep hover chroma under 150ms for snap feedback.
  • Expose your token surface publicly — CSS custom properties in the cascade are a brand signal.
  • Do not import a second type foundry. Geist trinity only.
  • Do not use Geist Pixel on running text — it is craft punctuation, not a display font.
  • Do not substitute large-blur drop shadows for the ring-plus-inset grammar.
  • Do not fill card surfaces with accent colour — below 3% of viewport is the rule.
  • Do not break the 1080px content rail for regular text sections.
  • Do not invent motion durations outside 0.09 / 0.1 / 0.15 / 0.2 / 0.4 seconds.
  • Do not use spring or bounce easings — ease, ease-in-out, and the single cubic-bezier(0.33, 0.12, 0.15, 1) only.
  • Typography must render with variable-weight Geist — static weight substitutes break the family trinity.
  • All shadows must honour the observed rgba stacks exactly; fabricated opacities collapse the elevation grammar.
  • Accents must pass AA contrast against the surface they sit on; demote to grey if they do not.
  • Breakpoints stay within Tailwind-standard 640 / 768 / 1024 / 1280 / 1536; respect 30-entry media-query discipline per component.
  • Motion durations are quantised — only the five values listed are valid.
  • Does every card use shadow-xs (ring + drop + inset) or shadow-lg (ring + inset) — and never a raw drop shadow?
  • Is accent colour usage below 3% of viewport, with every accent tied to a semantic role?
  • Do feature tiles use 50%-stop solid-colour gradients (linear-gradient(rgb X, rgb X 50%, transparent)) rather than diffuse gradients?
  • Is every hover chroma transition 0.1-0.15s ease, and every opacity reveal 0.4s cubic-bezier(0.33, 0.12, 0.15, 1)?
  • Does typography use Geist Variable by default, Geist Mono for code, and Geist Pixel only as decorative punctuation?
  • Does the page expose CSS custom properties in the cascade (at least 40+ visible), and do rounded corners follow the 4/6/12/64/100 radius grammar?

Design tokens

Observed token system

Color, type, spacing, gradients, and stacking order captured from the live page and rendered here as living, paste-ready previews.

Inspector

Observable layers

Structure, breakpoints, motion, fonts, and images captured from the live page and kept paste-ready alongside the tokens.

Depth-first walk of the meaningful sections. 10 nodes across 5 levels, shallow to deep by color.

  • body2
    • a
    • div (×4)2
      • div3
        • div1
          • Header
        • Main
        • Footer1
          • Nav
      • Aside

Accessibility

Contrast matrix

276 combinations - 78 pass AA - 34 pass AAA. Each pair is previewed with its real foreground on background; APCA Lc sits alongside the WCAG 2.1 ratio for draft WCAG 3 awareness.

Normal text passes AAALarge text passes AAA
fg
#FFFFFF
bg
#000000
APCA Lc
-108
Use
background on foreground
Normal text passes AAALarge text passes AAA
fg
#000000
bg
#FFFFFF
APCA Lc
+106
Use
foreground on background
Normal text passes AAALarge text passes AAA
fg
#171717
bg
#FFFFFF
APCA Lc
+105
Use
foreground on background
Normal text passes AAALarge text passes AAA
fg
#FFFFFF
bg
#171717
APCA Lc
-107
Use
background on foreground
Normal text passes AAALarge text passes AAA
fg
#000000
bg
#EBEBEB
APCA Lc
+94
Use
foreground on background
Normal text passes AAALarge text passes AAA
fg
#EBEBEB
bg
#000000
APCA Lc
-95
Use
background on foreground
Normal text passes AAALarge text passes AAA
fg
#000000
bg
#CCE6FF
APCA Lc
+89
Use
foreground on accent
Normal text passes AAALarge text passes AAA
fg
#CCE6FF
bg
#000000
APCA Lc
-90
Use
accent on foreground
Normal text passes AAALarge text passes AAA
fg
#171717
bg
#EBEBEB
APCA Lc
+93
Use
foreground on background

Images

Image strategy

Observable image posture - total count, lazy-loading ratio, and format mix. The hero image is measured above the fold.

Total images
30
Lazy loaded
16%
Format mix
  • svg49 · 100%

Hero image

https://vercel.com/vc-ap-vercel-marketing/_next/static/media/leonardo-ai-light.33rurcgq77tyi.svg?dpl=dpl_53dNajPAEgXXNCKBoLEtJvLR1AUh
Format
SVG
Dimensions
355x38
Loading
eager
srcset
no
Industry
developer-tools
Industry
saas
Industry
ai
Theme
Light + Dark
Added
2026-04-23

FAQ

Questions people ask about Vercel

3questions

Answers are pulled from the curator verdict and design brief - the same text your AI agent sees when it paste-reads this page.

Compare this with