Skip to content

Slab

Warm paper, black ink and a light slab serif. Hairlines instead of shadows, rust only as text.

  • Light by default
  • 35 colours · 14 type steps
  • Inspired by town.com
Use Slab
localhost:3000

The same generated app in every design. Scroll inside the window to see the whole page.

What it is

Slab sets every heading in a light slab serif over warm olive paper, with body copy in a quiet grotesque tracked slightly open. White cards sit on the paper, held by ink hairlines, never by shadows, and product pictures are white plates in a 1px ink frame. Buttons, checkboxes, switches and the selected tab fill with ink, and the one colour, a rust red, appears only as text, underlines and the focus ring. A felt-tip yellow marks the hero label and selected text. Dark mode is a warm near-black page that keeps the same rules.

Maintained by @agentic-studio in the open registry.

Best for

Calm, trust-first products where reading matters more than chrome: assistants, writing and knowledge tools, careful B2B software. Teams that want the product to feel printed and considered, not glossy.

Trade-offs

  • The light slab headline has a strong literary voice. It can feel slow or old-fashioned for a playful consumer app.
  • No shadows and one rare colour means hierarchy rests on type, space and lines. A crowded screen needs better layout, not more decoration.
  • The paper is tinted warm olive, so pure white screenshots and logos show their edges. Roboto Slab also stands in for a paid display face with more character.

Tokens

Generated from this design’s design.yaml, and shipped as CSS variables plus a Tailwind theme. Templates may use these names and nothing else.

Colours

Every colour token in design.yaml, grouped the way the system documents them. These are the light palette's values. The dark palette uses the same names with its own values, and tokens.css ships both.

Brand and accent

  • accent

    #a5380b

  • accent-1

    #d35d34

  • accent-2

    #497032

  • accent-3

    #2b6f9c

  • accent-4

    #b88b35

  • accent-5

    #5f5dbc

  • accent-6

    #6f7069

  • accent-hover

    #8a2d07

  • accent-soft

    #f6ede5

  • primary

    #1c1b1b

Surface

  • canvas

    #fdfdfc

  • hairline

    #dcddd7

  • surface-card

    #f2f3ed

  • surface-dark

    #1c1b1b

  • surface-dark-elevated

    #272825

  • surface-soft

    #f7f8f4

  • surface-solid

    #ffffff

  • surface-strong

    #e9eae4

Text

  • body

    #3a3b37

  • body-strong

    #272825

  • ink

    #1c1b1b

  • muted

    #6b6c68

  • muted-soft

    #90918d

  • on-accent

    #ffffff

  • on-dark

    #fafaf9

  • on-primary

    #ffffff

Semantic

  • error

    #9f3e3b

  • success

    #006e3d

  • warning

    #7a5a00

Other

  • danger

    #9f3e3b

  • danger-soft

    #fbeceb

  • error-soft

    #fbeceb

  • primary-hover

    #31322e

  • success-soft

    #e8f4eb

  • warning-soft

    #f5f0e4

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
    5rem · 80px · 300 · lh 1.02 · ls -0.025em
  • Ship faster

    Token
    display-lg
    Values
    4rem · 64px · 300 · lh 1.04 · ls -0.025em
  • Ship faster

    Token
    display-md
    Values
    3rem · 48px · 300 · lh 1.08 · ls -0.022em
  • Ship faster

    Token
    display-sm
    Values
    2.25rem · 36px · 300 · lh 1.12 · ls -0.02em
  • 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.6 · ls 0.015em
  • Ship faster

    Token
    title-md
    Values
    1.125rem · 18px · 400 · lh 1.4 · ls -0.005em
  • Ship faster

    Token
    body-md
    Values
    1rem · 16px · 450 · lh 1.6 · ls 0.018em
  • Ship faster

    Token
    title-sm
    Values
    1rem · 16px · 500 · lh 1.45 · ls 0.005em
  • Ship faster

    Token
    body-sm
    Values
    0.875rem · 14px · 450 · lh 1.55 · ls 0.02em
  • Ship faster

    Token
    button
    Values
    0.875rem · 14px · 500 · lh 1 · ls 0.02em
  • Ship faster

    Token
    nav-link
    Values
    0.875rem · 14px · 450 · lh 1.4 · ls 0.02em
  • Ship faster

    Token
    caption
    Values
    0.8125rem · 13px · 500 · lh 1.45 · ls 0.02em
  • SHIP FASTER

    Token
    caption-uppercase
    Values
    0.75rem · 12px · 500 · lh 1.4 · ls 0.06em

Typefaces

The families the generated Tailwind theme points at. A licensed face is named here even when the substitute below is what actually renders.

  • DisplayRoboto Slab, Rockwell, Georgia, ui-serif, serif
  • BodyGeist, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif
  • MonoGeist Mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace

Spacing scale

Drawn at true size. These are the only gaps and paddings a generated repo is allowed to use.

  • xxs0.25rem · 4px
  • xs0.5rem · 8px
  • sm0.75rem · 12px
  • md1rem · 16px
  • lg1.5rem · 24px
  • xl2rem · 32px
  • xxl3rem · 48px
  • section7rem · 112px

Radius scale

Sample shapes at true corner radius. Buttons and inputs sit at the small end of this scale, feature cards at the large end.

  • xs0.25rem · 4px
  • sm0.375rem · 6px
  • md0.5rem · 8px
  • lg0.75rem · 12px
  • xl0.875rem · 14px
  • full9999px
  • pill9999px

Elevation

Shadow tokens on a neutral card, at true blur and spread.

  • inset0 0 #0000
  • lift0 0 #0000
  • overlay0 20px 44px -10px rgb(28 27 27 / 0.16), 0 2px 6px 0 rgb(28 27 27 / 0.05)
  • ring0 0 0 1px rgb(28 27 27 / 0.9)
  • soft0 0 #0000
  • xs0 1px 2px 0 rgb(28 27 27 / 0.07)

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.

Slab is a well-printed book about software. Headings are a light slab serif in black ink on warm olive paper, and body copy is a quiet grotesque tracked slightly open. White cards and plates sit on the paper, held by hairlines and one line of full ink, never by shadows. Rust appears only as ink, and a felt-tip yellow marks the hero label.

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

ThemeLight native on near-white paper (#fdfdfc) with a greener endpaper (#f2f3ed). Dark is a warm near-black page (#131410) that keeps the same rules.
TypeRoboto Slab at 300 for display, 400 for titles, 500 for small titles. Geist at 450 with +0.02em tracking for body. Geist Mono only for code, keys and ids.
ColourWarm olive greys and black ink (#1c1b1b). One rust (#a5380b) used only as text, underlines and the focus ring. A felt-tip yellow (#f5d188) for the hero label and selected text.
ShapePrinted corners: 6px on controls, badges and tab segments, 12px on cards and menus, 14px on the big panels. Pills only for avatars, the switch, radios and progress.
DepthNothing on the page casts a shadow. Hairlines inside, one line of full ink outside. Only floating layers (menus, dialogs, toasts) get an overlay shadow.
SignatureA tilted felt-tip label over an 80px light slab headline, and the product window drawn as a white plate in a 1px ink frame on greener paper.

Principles

  1. Selected means ink: the primary button, the checked box, the on switch, the active tab segment, the current page.
  2. Rust is ink, never paint: text, underlines, check marks and the focus ring. No rust fills.
  3. White on paper, lines not shadows. Only floating layers cast a shadow.
  4. Ink outside, hairlines inside: a picture or a table gets one frame of full ink, and everything in it is split by hairlines.
  5. Small boxes, not pills: badges and tabs are 6px boxes.

Colour

Palette

TokenLightDarkRole
canvas (--background)#fdfdfc#131410The page floor
surface-soft#f7f8f4#171814Section bands, sidebars, table heads
surface-card (--muted)#f2f3ed#232420Tinted fills: inactive tabs, hover rows, code
surface-strong#e9eae4#2c2d29Pressed fills, progress tracks
surface-solid (--popover)#ffffff#1d1e1aMenus, selects, toasts: always opaque
card#ffffff#181915The card fill
surface-dark#1c1b1b#0c0d0aThe inverted panel
hairline (--border)#dcddd7#2f302cEvery border and divider
ink (--foreground)#1c1b1b#fafaf9Headings and primary text
body-strong#272825#e4e5e0Emphasised body text
body#3a3b37#c6c7c2Running text
muted (--muted-foreground)#6b6c68#8d8e8aSecondary text, captions
muted-soft#90918d#6e6f6aPlaceholders, disabled text, icons at rest
primary#1c1b1b#fafaf9The action colour
accent (--accent-fill)#a5380b#e2764aThe saturated accent: links, the accent badge
accent-soft#f6ede5#2b1f18The tint an accent label sits on
danger (--destructive)#9f3e3b#e07871Destructive actions and errors

success, warning and error each come with a -soft tint for the back of a badge or an alert: #006e3d, #7a5a00 and #9f3e3b in light, #44aa6f, #bd9023 and #e07871 in dark.

Slab's own variables, read by the landing hooks and the kit: --border-strong (#c3c4be light, #41423f dark), --border-ink (#1c1b1b light, #7c7d78 dark), --marker (#f5d188 light, #57461a dark), --page (#f2f3ed light, #1b1c18 dark).

How colour is used

  • Ink (bg-primary, text-ink) fills every selected state and the primary button. White (bg-card) is every card, field and plate on the paper.
  • Rust (text-accent) marks eyebrows, link buttons, check marks, link underlines and the current nav underline, and the focus ring is rust. It is never a fill.
  • The greener paper (--page) sits under the features chapter, the showcase mats, the hero shelf, the product title bar and the footer. Text on it stays muted or darker.
  • The felt-tip yellow (--marker) appears once per screen: the hero label, plus selected text.
  • Green, ochre and red mark status only, as soft tints with a coloured label or icon.

Charts

accent-1 to accent-6 (also chart-1 to chart-6) are six series colours ordered so neighbours stay distinguishable. Six series run terracotta, olive, blue, ochre, violet and warm grey, in that order, in both themes. The terracotta is lighter than the rust, so data is the one place a rust-family fill appears. 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: light here, because Slab is drawn in light first. The theme menu in the header offers light, dark and system and remembers the choice.

Type

Faces

  • Roboto Slab (font-display): headings and display type.
  • Geist (font-body): running text and interface copy (with italics).
  • Geist Mono (font-mono): code, ids and tabular labels.

Roboto Slab is a geometric slab with even strokes and a true light weight, so at 300 with tight tracking it gives a calm, printed shout. Geist has Swiss proportions that stay clean with open tracking at 13 to 16px, and Geist Mono shares its widths, so an id sits calmly inside a sentence.

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

TokenSizeLineTrackingWeightUse
text-display-xl80px1.02-0.025em300The hero headline, desktop
text-display-lg64px1.04-0.025em300The hero headline, tablet
text-display-md48px1.08-0.022em300Section headlines, the hero on phones
text-display-sm36px1.12-0.02em300Section headlines on phones, big numbers
text-title-lg24px1.3-0.012em400Page titles in the app
text-title-md18px1.4-0.005em400Card titles
text-title-sm16px1.450.005em500Small headings, table titles
text-body-lg18px1.60.015em400Lead paragraphs
text-body-md16px1.60.018em450Running text
text-body-sm14px1.550.02em450Interface copy, table cells
text-caption13px1.450.02em500Metadata, helper text
text-caption-uppercase12px1.40.06em500Eyebrows above headings
text-button14px10.02em500Buttons
text-nav-link14px1.40.02em450Header and footer links

Rules: one h1 per page. Display sizes are for marketing pages; the app tops out at text-title-lg. Headings are Roboto Slab at 300 from 36 to 80px, tracked tight (-0.025em at the top). Titles are 400, small titles and the brand mark 500, never heavier and never italic. Body is Geist at 450 with +0.02em tracking; that opposite pull is most of the look.

Space and layout

  • Spacing tokens: xxs 4px, xs 8px, sm 12px, md 16px, lg 24px, xl 32px, xxl 48px, section 112px (the gap between landing sections).
  • Content sits in max-w-content (1280px) with px-md on phones and px-lg from sm up. Reading text stops at max-w-measure (672px).
  • Spacing steps are 4, 8, 12, 16, 24, 32 and 48px, with 112px between sections.
  • Density is generous: 40px controls against 14 to 16px text, and 24px card padding (32px on the sign-in card).
  • Leave about half the first screen as empty paper. Space separates the showcase rows, not lines.

Shape and depth

TokenValueWhere
rounded-xs4pxBreadcrumb, Checkbox, Kbd
rounded-sm6pxAccordion, Badge, Button, Dialog, Input, Sheet, Skeleton, Tabs, Toaster, the landing page
rounded-md8pxDropdownMenu, Select, Tooltip, the landing page
rounded-lg12pxAlertDialog, Alert, Card, Dialog, DropdownMenu, Popover, Select, Toaster, the landing page
rounded-xl14pxThe landing page
rounded-pill9999pxProgress, Switch, the landing page
rounded-full9999pxAvatar, RadioGroup, Switch

Radii are 4px on checkboxes and keys, 6px on buttons, inputs, badges and tab segments, 8px on menu items and tooltips, 12px on cards, dialogs, menus and alerts, and 14px on the product window, the showcase mats and the CTA panel. Borders are always 1px solid, in four strengths: hairline, input line, strong line and full ink, plus pencil grey on checkbox and radio rings so they clear 3:1. Nothing on the page casts a shadow. Menus, popovers, dialogs, sheets and toasts float on an overlay shadow, and the switch thumb has a whisper.

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.

ComponentIn Slab
ButtonGeist 500 at 14px with +0.02em tracking, sentence case, 6px corners, flat, and every press sinks 1px. Primary is an ink fill with a white label; secondary is a flat paper step; outline carries the input line and an ink label, and turns solid ink when it marks the current page; ghost washes ink at 5% on hover; danger is a soft red tint, never solid; link is rust text with a 1px underline on hover. Sizes are 32, 40 and 48px tall, and focus is a rust ring set off the paper.
BadgeA 24px box with 6px corners, never a pill: a soft fill and a matching 13px Geist label, no line. Accent is rust on apricot paper, neutral is paper with body text, and status badges take their soft tint. The uppercase mode (12px, +0.06em) is the only place caps appear.
CardFlat, 12px corners, never a shadow. Default is white above the paper with a hairline; soft and strong are flat paper steps with no line; outline lets the paper show inside the input line; dark is the ink panel. Titles are the slab at 18px 400.
Input, Textarea, SelectWhite 40px fields on the paper with the input line and 6px corners, no shadow. Hover darkens the line, focus turns it rust with a faint rust halo, and invalid turns it red. Select content is a white menu with 12px corners, an overlay shadow and an ink check on the chosen item.
Checkbox, RadioGroup, SwitchA white 16px box with 4px corners and a pencil-grey line that fills with ink and takes a 12px tick when checked. A radio is a white circle with the same line; checked, the ring turns ink around an 8px ink dot. The switch track is pencil grey when off and ink when on, with a paper thumb and a whisper shadow. All three keep a 32px hit area and a rust focus ring set off the paper.
TabsThe default is a segmented control: a white shell with the input line and 10px corners, and the active tab a solid ink segment with no line or shadow. Idle tabs wash ink at 5% on hover. Line tabs mark the active tab with a 2px ink underline over a hairline.
AccordionRows split by hairlines, no boxes. Triggers are the slab at 16px 500 in ink with a muted chevron that turns over, and hover draws a 1px rust underline; content is 14px body copy.
Dialog, AlertDialog, SheetA white sheet in a 6px paper tray, with 12px corners, a hairline and an overlay shadow over a plain 45% dark scrim with no blur. Dialog titles are the slab at 24px 400, and the close button is a 32px ghost. Alert dialogs are narrower and pair an outline cancel with a primary or soft danger action. Sheets are square with one hairline on the inner edge, 24px padding and an 18px slab title.
DropdownMenu, Popover, Select content, TooltipWhite surfaces with a hairline, 12px corners and an overlay shadow. Items are 32px with 8px corners and highlight to paper; checks are ink and shortcuts are muted Geist Mono. Tooltips are not inverted: a small white chip with a hairline, an overlay shadow, 13px ink text and an arrow that keeps the hairline.
TableNo frame of its own. A paper header band with 36px cells and 13px muted labels in sentence case, then 48px rows split by hairlines that hover to paper. Numbers are tabular; set them right, and set ids in Geist Mono.
AlertA borderless tint with 12px corners. Info is neutral paper with an ink title and a muted icon; success, warning and danger take their soft tint with the title and icon in the status colour.
Avatar, Progress, Skeleton, Spinner, Separator, Kbd, Breadcrumb, Pagination, Field, Label, ToasterAvatars are circles with a hairline ring inside and initials on paper. Progress is a 6px pill with an ink bar, never rust. Skeletons are flat paper blocks that pulse, and spinners turn in the colour of the text around them. Separators are 1px hairlines. Kbd is Geist Mono on white with the input line and no bevel. Breadcrumbs split with a thin chevron and end on the current page in ink at 500, and the current page in pagination is an ink box. Labels are 14px 500 in ink, sentence case, and field legends are the slab. Toasts are white with a hairline and 12px 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. Slab styles these:

  • site-header: drops the blur and the full-width strip. Its bar is white with one hairline and 10px corners, floating 8px below the top with paper showing around it.
  • site-nav: the current page loses its wash and gets a thin rust underline.
  • brand-mark: an ink square with a slab letter at 500.
  • hero-backdrop: no wash, grid or glow. It becomes a shelf of greener paper behind the lower half of the product window, opened by a hairline.
  • hero-eyebrow: a felt-tip yellow swipe with uneven ends, tilted one degree, with ink text and a rust arrow. A linked label gets a rust underline on hover.
  • hero-title and section-title: the light slab from the type scale with balanced lines, and no added weight or colour.
  • product-preview: a white plate in one line of full ink, 14px corners, no shadow. A real hero screenshot gets the same frame.
  • product-preview-bar: sits on the greener paper, with its dots and address field drawn as white controls with the input line.
  • section: no section draws a bottom rule. Each one after the first, and the first one after the hero, opens on a full-width hairline, so the logo strip sits between two rules.
  • section-eyebrow: rust sentence case at 15px, weight 500, no caps and no mono.
  • section logos: the title is a small sentence-case Geist caption, and each logo is a muted slab wordmark.
  • section features: the one chapter on the greener paper. feature-card cards take the strong line, and feature-icon is a white tile with the strong line and a 1px ink icon.
  • showcase-visual: a mat of greener paper with no line. The picture on it is a white plate in an ink frame.
  • step-marker: white boxes framed in ink with slab numerals, joined by hairlines.
  • stat-grid and stat-value: the one square panel, an ink frame with lighter inner rules and white cells, holding 48px light slab figures with tabular digits.
  • testimonial: white cards with the strong line. The quote is a 20px light slab pull quote in ink.
  • faq: ruled like a printed table, with an ink rule on top and at the bottom and hairlines between. Questions are 18px slab.
  • Featured plan: the highlighted plan card is outlined in 2px ink (its border plus an ink ring), never in rust.
  • cta-panel: the one ink panel, like a back cover. The darkest ink, one hairline, no wash and no shadow, with the dark palette inside.
  • site-footer: the greener endpaper, with 16px slab column headings in sentence case.

Everything else is type, space and the kit.

Signed-in screens

The dashboard sits on the paper with a soft sidebar split by a hairline. The active row is paper with ink text, cards are white with hairlines, page titles are 24px slab and tabs are segmented with an ink active segment.

Sign-in is one white card on the paper with 12px corners, a hairline and 32px padding: a 24px slab title, white fields with the input line, a full-width ink button and rust text links.

Do and don't

Do

  • Set every heading in Roboto Slab: 300 for display sizes, 400 for titles, 500 only for small titles and the brand mark.
  • Keep body copy in Geist at +0.02em tracking and weight 450. The open tracking is part of the look.
  • Put white cards on paper: bg-card on bg-canvas or on the greener --page, held by a line.
  • Mark every selected state with ink: primary buttons, checked boxes, the on switch, the active tab segment, the current page, progress bars.
  • Keep rust for text and lines: eyebrows, link underlines, the eyebrow arrow, check marks, the current nav underline, the focus ring.
  • Use the marker once per screen: the hero label, and text selection.
  • Frame pictures and tables in one line of full ink (--border-ink), with hairlines inside.
  • Draw every icon as a 1px line (stroke = 24 / size), in ink or muted.

Don't

  • Don't fill a button, badge or band with the rust. The first chart series is a lighter terracotta, and data is the only place a rust-family fill appears.
  • Don't use a pill shape on buttons, badges, inputs or tabs. Pills are for avatars, the switch, radios and progress.
  • Don't add a drop shadow to a card, button, input, tab or the product window. Only floating layers get shadow-overlay.
  • Don't set labels in capitals or tracked caps. The Badge uppercase mode is the one exception.
  • Don't put a gradient, glow or grid on any surface, the hero included.
  • Don't set the slab above 500 or in italic. It shouts by size, not by weight.
  • Don't introduce a cool grey. Every neutral is warm olive.
  • Don't use mono for eyebrows, buttons, nav links or badges.

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 Slab

The builder opens with Slab picked. Pick your batteries and the design is applied to every template before the zip is built.