Pulse
Cream type on a midnight console, an ember and mint pill pair, and a six hue waveform under the hero.
- Dark by default
- 35 colours · 14 type steps
- Inspired by vapi.ai
The same generated app in every design. Scroll inside the window to see the whole page.
What it is
Pulse is a dark console system for voice, audio and developer products. Headlines whisper in Hanken Grotesk at weight 300 on a near-black void, and every label speaks in Geist Mono caps. Buttons are full pills, ember for the main action and mint for the second one, while cards, inputs and menus keep a near-sharp 5.6px corner and a 1px hairline instead of a shadow. All the colour lives in one signature: a waveform of stacked dashes in six hues that rises behind the product window. The light theme turns the page to cream paper with void ink and keeps the same pills, labels and waveform.
Maintained by @agentic-studio in the open registry.
Best for
Voice, audio, AI and API products sold to developers, where a console feel builds trust and a waveform tells the story at a glance. It also suits dev tools and infrastructure dashboards that want a calm dark UI with one clear call to action.
Trade-offs
- Weight 300 headlines need short copy and big sizes. Below 40px they turn thin, so on small screens the mono labels carry the structure.
- Colour is rationed. Ember marks the one action and mint marks live state, so a brand that wants its colour on every screen will feel held back.
- Mono caps on buttons, nav, badges, tabs and table heads read as a console. That suits technical buyers, but long labels in caps are slower to read and can feel cold in a consumer product.
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
#d9e6ef
accent-1
#62f6b5
accent-2
#de94e2
accent-3
#e96b34
accent-4
#9977ff
accent-5
#ffdd03
accent-6
#4dcafa
accent-hover
#edf4f9
accent-soft
#172029
primary
#e96b34
Surface
canvas
#0e0e13
hairline
#27272a
surface-card
#18181b
surface-dark
#060608
surface-dark-elevated
#18181b
surface-soft
#09090b
surface-solid
#18181b
surface-strong
#27272a
Text
body
#d8d7d4
body-strong
#f4f4f5
ink
#fffaea
muted
#a1a1aa
muted-soft
#71717a
on-accent
#0e0e13
on-dark
#fffaea
on-primary
#09090b
Semantic
error
#ff6b81
success
#62f6b5
warning
#f5c542
Other
danger
#ff6b81
danger-soft
#2d1219
error-soft
#2d1219
primary-hover
#f27a43
success-soft
#0f2a21
warning-soft
#2b2310
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
- 5.5rem · 88px · 300 · lh 1 · ls -0.035em
Ship faster
- Token
- display-lg
- Values
- 4.25rem · 68px · 300 · lh 1.03 · ls -0.032em
Ship faster
- Token
- display-md
- Values
- 3.5rem · 56px · 300 · lh 1.07 · ls -0.028em
Ship faster
- Token
- display-sm
- Values
- 2.5rem · 40px · 300 · lh 1.12 · ls -0.022em
Ship faster
- Token
- title-lg
- Values
- 1.5rem · 24px · 400 · lh 1.3 · ls -0.012em
Ship faster
- Token
- body-lg
- Values
- 1.125rem · 18px · 400 · lh 1.55 · ls 0
Ship faster
- Token
- title-md
- Values
- 1.125rem · 18px · 500 · lh 1.4 · ls -0.005em
Ship faster
- Token
- body-md
- Values
- 1rem · 16px · 400 · lh 1.6 · ls 0
Ship faster
- Token
- title-sm
- Values
- 1rem · 16px · 500 · lh 1.45 · ls 0
Ship faster
- Token
- body-sm
- Values
- 0.9375rem · 15px · 400 · lh 1.55 · ls 0
Ship faster
- Token
- button
- Values
- 0.8125rem · 13px · 500 · lh 1 · ls 0.08em
Ship faster
- Token
- caption
- Values
- 0.8125rem · 13px · 400 · lh 1.45 · ls 0
SHIP FASTER
- Token
- caption-uppercase
- Values
- 0.75rem · 12px · 500 · lh 1.5 · ls 0.08em
Ship faster
- Token
- nav-link
- Values
- 0.75rem · 12px · 400 · lh 1.5 · 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.
- DisplayHanken Grotesk, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif
- BodyHanken Grotesk, 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
- section5rem · 80px
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
- lg0.35rem · 6px
- md0.35rem · 6px
- xl0.5rem · 8px
- full9999px
- pill9999px
Elevation
Shadow tokens on a neutral card, at true blur and spread.
- inset0 0 #0000
- lift0 0 #0000
- overlay0 24px 48px -16px rgb(0 0 0 / 0.8)
- ring0 0 0 3px rgb(98 246 181 / 0.22)
- 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.
Pulse is a quiet midnight console where one six hue waveform does all the talking. Headlines whisper in Hanken Grotesk at weight 300 on a near-black void, and every label speaks in Geist Mono caps. Buttons are full pills, ember for the main action and mint for the second one, while cards, inputs and menus keep a near-sharp 5.6px corner and a 1px hairline instead of a shadow.
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 a #0e0e13 void. Light is cream paper (#fffaea) with void ink and the same pills, labels and waveform. |
| Type | Hanken Grotesk for display and body (headlines 300 with tight tracking, titles 400 to 500). Geist Mono caps at 12 to 13px with +0.08em for every console label. |
| Colour | Cream, bone and pearl text on void, carbon and slab greys. Ember (#e96b34) for the one primary action, mint (#62f6b5) for the second action and for live state, ice for links and eyebrows, six hues for data only. |
| Shape | Near-sharp containers, round actions: 5.6px on cards, inputs, menus and badges, 8px on the four big frames, full pills on every button, switch and avatar. |
| Depth | Shadowless. Tone steps (void page, carbon cards and fields, slab chips and menus) plus a 1px hairline. Only overlays cast a shadow. |
| Signature | A static waveform of rounded dashes in six hues that rises from the hero floor behind the product window, on a faint 16px dot grid. |
Principles
- One ember fill per view: the primary action. Mint is its partner pill and the mark for live state.
- Colour lives in the waveform and the data. Everything else is cream, greys and hairlines.
- Headlines whisper: Hanken Grotesk 300, big sizes, short copy.
- Mono caps mean console label. Keep them short and never use them for headings or paragraphs.
- Separate by tone and a 1px hairline, never by a shadow or a tinted band.
Colour
Palette
| Token | Light | Dark | Role |
|---|---|---|---|
canvas (--background) | #fffaea | #0e0e13 | The page floor |
surface-soft | #f8f2de | #09090b | Section bands, sidebars, table heads |
surface-card (--muted) | #f4eedb | #18181b | Tinted fills: inactive tabs, hover rows, code |
surface-strong | #ebe3cb | #27272a | Pressed fills, progress tracks |
surface-solid (--popover) | #ffffff | #18181b | Menus, selects, toasts: always opaque |
card | #fffdf6 | #09090b | The card fill |
surface-dark | #0e0e13 | #060608 | The inverted panel |
hairline (--border) | #e5ddc7 | #27272a | Every border and divider |
ink (--foreground) | #0e0e13 | #fffaea | Headings and primary text |
body-strong | #27272a | #f4f4f5 | Emphasised body text |
body | #3f3f46 | #d8d7d4 | Running text |
muted (--muted-foreground) | #5c5c66 | #a1a1aa | Secondary text, captions |
muted-soft | #85858d | #71717a | Placeholders, disabled text, icons at rest |
primary | #e96b34 | #e96b34 | The action colour |
accent (--accent-fill) | #2d5068 | #d9e6ef | The saturated accent: links, the accent badge |
accent-soft | #e1ebf0 | #172029 | The tint an accent label sits on |
danger (--destructive) | #c42b45 | #ff6b81 | Destructive actions and errors |
success, warning and error each come with a -soft tint for the back of a
badge or an alert: #087a51, #8f5a00 and #c42b45 in light, #62f6b5, #f5c542 and
#ff6b81 in dark.
Pulse's own variables, read by the landing hooks and the kit: --grid-dot
(rgb(14 14 19 / 0.14) light, rgb(255 250 234 / 0.1) dark),
--secondary-hover (#4ee8a4 light, #8af9c9 dark), --pulse (#087a51 light,
#62f6b5 dark).
How colour is used
- Ember (
bg-primary) is the one primary button per view, with a carbon label. It is never text and never a band. - Mint (
--secondary) is the second call to action, always beside ember. As--pulseand--ringit marks live or current state: focus, a switch that is on, the current page, success and the eyebrow dot matrix. - Ice (
text-accent, slate ice on cream) marks links, eyebrows and check icons. - Cream is content: checked boxes, radios, progress and the active tab are ink, not colour.
- The six hues belong to data: the waveform, chart series, feature icons and topic dots. Never on a button, a badge or a heading.
Charts
accent-1 to accent-6 (also chart-1 to chart-6) are six series colours
ordered so neighbours stay distinguishable. Six series in order: mint, pink,
ember, violet, yellow, blue, with deeper versions on cream. Neighbours stay
apart under common colour blindness; light series hold 3:1 or better on every
light surface and dark ones 5.4:1 or better on every dark surface. 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
Pulse is drawn in dark first. The theme menu in the header offers light, dark
and system and remembers the choice.
Type
Faces
- Hanken Grotesk (
font-display,font-body): headings and display type; running text and interface copy. - Geist Mono (
font-mono): code, ids and tabular labels.
Hanken Grotesk is a round, open grotesque that stays calm at weight 300 and big sizes, and the same family sets the text, so the page has one voice. Geist Mono is the console label face: buttons, nav, eyebrows, badges, tabs and table heads in caps, plus code and ids.
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 | 88px | 1 | -0.035em | 300 | The hero headline, desktop |
text-display-lg | 68px | 1.03 | -0.032em | 300 | The hero headline, tablet |
text-display-md | 56px | 1.07 | -0.028em | 300 | Section headlines, the hero on phones |
text-display-sm | 40px | 1.12 | -0.022em | 300 | Section headlines on phones, big numbers |
text-title-lg | 24px | 1.3 | -0.012em | 400 | Page titles in the app |
text-title-md | 18px | 1.4 | -0.005em | 500 | Card titles |
text-title-sm | 16px | 1.45 | 0 | 500 | Small headings, table titles |
text-body-lg | 18px | 1.55 | 0 | 400 | Lead paragraphs |
text-body-md | 16px | 1.6 | 0 | 400 | Running text |
text-body-sm | 15px | 1.55 | 0 | 400 | Interface copy, table cells |
text-caption | 13px | 1.45 | 0 | 400 | Metadata, helper text |
text-caption-uppercase | 12px | 1.5 | 0.08em | 500 | Eyebrows above headings |
text-button | 13px | 1 | 0.08em | 500 | Buttons |
text-nav-link | 12px | 1.5 | 0.08em | 400 | Header and footer links |
Rules: one h1 per page. Display sizes are for marketing pages; the app tops
out at text-title-lg. Display steps run from 40 to 88px in Hanken Grotesk 300,
tracked from -0.022em to -0.035em, and the hero pulls its word spacing in too.
Titles are 400 to 500 from 16 to 24px and reading text is 15 to 18px, never
smaller. Console labels are Geist Mono caps at 12 or 13px with +0.08em.
Space and layout
- Spacing tokens:
xxs4px,xs8px,sm12px,md16px,lg24px,xl32px,xxl48px,section80px (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 80px between sections.
- Density is comfortable: cards pad 24px, elements sit 8px apart and fields stack 24px apart.
- Rhythm comes from air plus one full width hairline at the top of each section, never from tinted bands.
Shape and depth
| Token | Value | Where |
|---|---|---|
rounded-xs | 2px | Breadcrumb, Checkbox, Kbd |
rounded-sm | 4px | Accordion, DropdownMenu, Select, Skeleton, Tabs, Tooltip, the landing page |
rounded-md | 5.6px | Alert, Badge, DropdownMenu, Input, Popover, Select, Tabs, Toaster, the landing page |
rounded-lg | 5.6px | AlertDialog, Card, Dialog, Table, the landing page |
rounded-xl | 8px | The landing page |
rounded-pill | 9999px | Badge, Button, Dialog, Progress, Sheet, Switch, Toaster, the landing page |
rounded-full | 9999px | Avatar, RadioGroup, Switch |
Containers are near-sharp and actions are round: 2px on checkboxes and keys, 4px on menu items and tooltips, 5.6px on inputs, badges, cards, menus and dialogs, 8px on the product window, showcase stages, stat grid and CTA panel, and full pills on buttons, switches, avatars and the eyebrow chip. Borders are always 1px solid: iron on cards and rules, steel on inputs and outline buttons. Nothing casts a shadow except menus, selects, popovers, dialogs, sheets and toasts.
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 Pulse |
|---|---|
Button | A full pill in Geist Mono 500 caps with +0.08em tracking, flat, with no border on filled kinds. Primary is ember with a carbon label; secondary is the mint pill; outline is a steel line with an ink label; ghost fills a faint ink tint on hover; danger is rose with a carbon label (crimson with cream in light). Filled kinds press in to 98%. Sizes are 32, 40 and 48px tall with 12, 13 and 14px labels, and disabled drops to 40%. Link is the only sentence case kind, in ice Hanken 15px. Focus is a mint ring with a canvas gap. |
Badge | 5.6px corners, a 1px border, 20px tall, Geist Mono 12px in sentence case. Neutral is the slab chip with a hairline, accent is ice on a cool tint, and success, warning and danger are soft tints with no line, led by a 6px dot. Uppercase mode switches to mono caps. Never ember, mint or a spectrum hue. |
Card | 5.6px corners, a 1px iron hairline and a carbon fill one step deeper than the void page (warm white on cream), with no shadow and no hover lift. Soft, strong, outline and dark variants step the tone, and the dark card keeps an edge on a dark page; titles are Hanken 18px 500 and padding is 16, 24 or 32px. |
Input, Textarea, Select | 40px carbon wells with a steel line, 5.6px corners and 15px text. Focus turns the edge mint with a 3px mint halo; invalid turns it rose with a rose halo. Textareas start at 96px and the mono option is Geist Mono 14px. The select chevron turns ink when open; its content is slab with a hairline and the overlay shadow, and the chosen item shows a mint check. |
Checkbox, RadioGroup, Switch | Checkboxes (2px corners) and radios are carbon with a grey line that holds 3:1; checked is ink, a cream box with a void tick in dark and the reverse on cream. Focus is a mint ring 2px out. The switch is the one control that turns mint when on; off is an iron track with a grey thumb. |
Tabs | Mono caps triggers in mercury. The default list is a slab track with a hairline and the active tab is a carbon chip with a hairline; line tabs mark the active tab with a 2px mint underline. |
Accordion | Rows split by iron hairlines, Hanken 16px 500 triggers that turn ice on hover with no underline, a soft grey chevron that flips when open, and 16px pearl answers. |
Dialog, AlertDialog, Sheet | Slab panels with a hairline, 5.6px corners and the overlay shadow over a 70% dark scrim with a 2px blur. Titles are Hanken 24px 400, the close button is a round ghost icon, and footer pills sit on the right 12px apart, primary last. Alert dialogs are narrower and pair an outline cancel with a primary or danger action. Sheets are carbon, flush to the edge, with a hairline under the header. |
DropdownMenu, Popover, Select content, Tooltip | Slab, a hairline, 5.6px corners and the overlay shadow. Items are 36px tall in Hanken 15px and highlight to iron, checks are mint, group labels are mono caps and shortcuts are Geist Mono. The tooltip is the console chip in small: cream with void mono text in dark, the reverse on cream. |
Table | A hairline frame with 5.6px corners, a carbon head band with mono caps heads, hairline rows that turn slab on hover, and tabular numbers. Selected rows take the ice tint. Right-align numbers and set ids in font-mono. |
Alert | 5.6px corners, a 1px border, 16px padding and an icon. Info is an ice tint with no line and an ice icon; success, warning and danger are soft tints with a status border at 30% and a status icon. Titles are Hanken 15px 500 in ink over pearl text. |
Avatar, Progress, Skeleton, Spinner, Separator, Kbd, Breadcrumb, Pagination, Field, Label, Toaster | Avatars are circles with a hairline ring and Geist Mono caps initials on iron. Progress is a level meter: an ink bar on an iron track, cut into 10px dashes. Skeletons pulse on a faint ink tint with 4px corners, and the spinner is a plain ring in the current text colour. Separators are 1px hairlines and Kbd is flat Geist Mono caps on slab. Breadcrumbs are a mono caps path split by chevrons. Pagination numbers are 40px mono circles and the current page is the outline circle. Labels are Hanken 15px 500, never mono, and legends are mono caps. Toasts are slab, show status only in the icon and carry small mono caps action pills. |
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.
Pulse styles these:
hero-backdrop: a faint 16px dot grid over the whole hero, with no glow and no wash.hero: ends on a full width hairline, the floor the waveform stands on.hero-eyebrow: the console pill, an inverted cream chip (void on cream) with mono caps inside a hairline ring that lights mint on hover.hero-title: Hanken 300 with the word spacing pulled in, 36px under the pill.hero-actions: the ember and mint pill pair, 56px tall and at least 240px wide from 40rem up; the stack's outline button becomes the mint pill.hero-note: a mono console line under the pair.hero-visual: a static waveform of rounded dashes in six palette hues rises from the hero floor behind the product window, full bleed, faded at both edges and half size on phones.product-preview: a flat carbon console with 8px corners;product-preview-barturns its dots into short dashes and lights the first one mint.section: every section starts on one full width hairline, with no bottom rules and no tinted bands.logo-cloudandlogo: a strip with a mono caps title and equal cells split by vertical hairlines from 64rem up, wordmarks in pearl Hanken 500.section-eyebrow: mono caps in ice, led by a 3 by 3 mint dot matrix;section-titleis Hanken 300.feature-cardandfeature-icon: hairline rows with no fill or corners; each bare 24px icon takes one spectrum hue in order.step-marker: 40px steel rings on the canvas with mono numbers, joined by a dotted line.stat-gridandstat-value: an 8px hairline grid with light tabular numbers over mono caps labels.showcase-visual: an 8px hairline frame over the dot grid, and the digest chart's bars break into stacked dashes.cta-panel: the night in both themes, void with the dot grid, the ember and mint pair, and the waveform at half size along its floor.site-nav: mono caps links in mercury with no fill and a mint dot before the current page; a text ghost button in the header (an auth battery's Sign in) becomes the mint pill.brand-mark: a console disc, cream in dark and void on cream, with a mono initial and a hairline ring;brandsets the name at weight 650.site-footer: mono caps column titles on the carbon footer.
Everything else is type, space and the kit.
Signed-in screens
The dashboard sits on the void with a carbon sidebar split by a hairline, mono caps group labels, carbon stat tiles with Hanken 300 numbers, and charts in the six hues in order.
Sign-in is one 400px carbon card centred on the canvas, with carbon input wells, a mint focus halo, a full width ember pill and outline pills for providers.
Do and don't
Do
- Pair ember and mint as the two calls to action: ember first, mint beside it, same size, 12px apart.
- Set every display step in Hanken Grotesk 300 with tight tracking, and keep headlines to about 45 characters so 88px sets in two lines.
- Put every console label in Geist Mono caps at 12 or 13px with +0.08em: eyebrows, nav links, buttons, uppercase badges, tab triggers, table heads, breadcrumbs and stat labels.
- Keep containers at 5.6px and actions at a full pill. Only the product window, showcase stages, stat grid and CTA panel go to 8px.
- Separate surfaces by tone and a 1px hairline: void page, carbon cards and fields, slab chips and menus.
- Use mint (
--pulse) only for live or current state: the focus ring, a switch that is on, the current page, success and the eyebrow dot matrix. - Keep the six hues for data: the waveform, chart series in order (mint, pink, ember, violet, yellow, blue), feature icons and topic dots.
- Write cream (#fffaea) text on dark, never pure white, and check every new screen in the cream light theme too.
Don't
- Don't add drop shadows to cards, buttons, inputs or the product window. Only menus, dialogs, sheets, popovers and toasts get the overlay shadow.
- Don't round cards, inputs or menus past 5.6px, and never square off a button.
- Don't use ember or mint as a text colour, a link colour or a section background.
- Don't add glows, gradients, aurora washes or noise. Beyond the pill pair, the only colour on the page is the waveform and the data.
- Don't put a spectrum hue (pink, yellow, violet, blue) on a button, a badge or a heading.
- Don't set reading text below 15px, and don't track anything except the mono labels.
- Don't set headings, paragraphs, labels or input text in mono. Mono means console label, so it stays short.
- Don't animate the waveform or show it more than twice (hero and CTA panel), and don't put a third filled pill next to the pair.
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 Pulse
The builder opens with Pulse picked. Pick your batteries and the design is applied to every template before the zip is built.
