Design System
Ink & Paper — the full design.md reference behind every item in this registry.
Overview
BuildSpace should feel like a real product company with taste, not a generic SaaS kit and not a chaotic experimental playground. The design system in the reference page calls this balance out clearly: dense product UI stays composed and readable, while brand expression lives in a few deliberate devices such as stickers, tape dividers, serif italics, pastel accents, and 3D shapes.
The core principle is "ink & paper": sober, editorial restraint (the ink) carrying a few deliberate expressive flourishes (the paper's texture). We keep the information architecture sober and fast to scan, then add personality at the edges. Headlines can be dramatic. Status labels can tilt. Empty states can use shapes. Tables, forms, sidebars, and navigation should not look noisy.
This file is the source of truth for BuildSpace design direction. The implemented tokens live in packages/ui/src/styles/globals.css; when this document and the CSS disagree, treat this document as intent and fix the CSS.
Colors
The palette is built from a warm off-white canvas, near-black ink, and six soft pastel families. The canvas does most of the heavy lifting. Pastels are for emphasis, grouping, and tone, not for turning the whole product into candy.
primary/textis a near-black ink. Use it for body copy, borders that matter, primary CTAs, active nav, and table headers.backgroundandbackground-2are warm paper tones, softer than pure white.surfaceis true white for cards, inputs, and dense UI blocks that need separation from the canvas.lilac,peach,mint,sky,butter, androseeach have background, icon, text, and dot variants.mintis the default positive/status family.peachandbutterare the warm expressive families for highlights, italics, and section intros.roseis the caution/error-leaning expressive family.skyis informational and quiet.lilacis playful and best used sparingly.
Color usage should follow the density of the UI:
- Dense interfaces use mostly
background,surface,text,border, and a small amount of accent. - Marketing and empty states can use larger pastel surfaces.
- Pastel-on-pastel pairings are acceptable for decorative moments, not for critical control text.
Card and accent discipline
The fun in this system comes from contrast, not from tinting everything. The marketing pages work because pastels are scarce and deliberate: white/paper card faces with ink borders and offset shadows, pastels as full-bleed section bands or small varied accents. Product UI must follow the same physics.
- The default card face is
surface(white) with an ink border and the solid-offset shadow. Accent color enters through the icon tile, status chip, dot, and accent text — never the whole card fill by default. - A filled pastel card is a callout: at most one per view, reserved for the hero moment (an AI entry point, a launch surface, an empty state).
- Adjacent accented elements never share a pastel family. A row of steps or sibling cards should cycle families the way the marketing step cards do (lilac, peach, butter, sky, rose), not repeat one.
- To color a whole region, tint a full-width section background (a pastel band) and place white cards on top of it. Colored cards on a neutral canvas read washed out; a colored backdrop under white cards reads fun.
- Code blocks and terminal snippets sit on ink (
primarybackground,on-primarytext), never nested pastel-on-pastel. - Never fall back to a pastel silently. If an accent key is unknown, render the neutral surface treatment — a silent sky/mint default is how a UI drifts monotone.
Typography
Typography is one of the most important brand signals in the system.
DM Serif Displayis the brand voice. Use it for display text, section headings, card titles, key stats, and the BuildSpace wordmark.DM Sansis the workhorse for body copy, labels, controls, and navigation.JetBrains Monois for metadata, labels, tokens, annotations, timestamps, and structured UI chrome.
Rules for use:
- Large headlines should feel editorial, slightly compressed, and confident.
- Italics are a signature, not a default. Usually italicize one or two words in a headline, often in
peach-textorrose-text. - Dense interfaces should be mostly sans and mono.
- Mono should usually be uppercase or tracking-wide for labels and supporting metadata.
Layout
Layout should create calm before it creates flair. The page examples consistently use generous spacing, straight cards, and clear section boundaries.
- Use the 4pt spacing scale exactly.
- Default cards are straight, bordered, and lifted with a small solid-offset shadow.
- Section transitions use a dashed "tape" divider rather than heavy ornament.
- Grid layouts are simple equal-column grids with comfortable gaps.
- Product pages should privilege breathing room over cramming extra controls into a row.
A useful mental model is: the scaffolding is quiet, the accents are loud.
Elevation & Depth
Depth in BuildSpace should feel like a physical sticker or printed card sitting on paper.
- The signature shadow is a solid ink offset, not a soft blur.
- Elevated cards pair the offset shadow with a near-ink border. A pale gray border under a hard black shadow reads timid; the border and shadow should feel like the same printed edge.
- Hover states usually move up and left by 1-2px while the shadow grows.
- Blur shadows exist only as supporting effects for shapes or large marketing moments.
- Primary surfaces should read as tactile and cut out, not glassy or floating.
The product should never feel neumorphic, translucent, or over-animated.
Shapes
3D shapes are part of the identity, but they are not general-purpose decoration. The reference page is explicit here: shapes are for mood.
- Use shapes in heroes, empty states, launch surfaces, and selected feature cards.
- Use one shape at a time in most product moments.
- Keep shapes out of tables, form rows, nav items, chips, and other dense UI.
- Slight rotation is good. Constant looping animation is not.
- Shapes should support the message, not compete with it.
The same restraint applies to annotations. Short mono annotations can add voice in editorial sections, but dense app screens should stay clean.
Components
The system breaks cleanly into expressive accents and composed product primitives.
Expressive components:
stickeris the main accent badge. It can tilt, lift on hover, and carry the pastel families or dark ink.section-headcombines a small sticker-like eyebrow, a serif headline, and short supporting copy.empty-statecan include a single 3D shape, centered messaging, and one strong CTA.card-calloutis the filled pastel card — the one loud card a view is allowed. It may tilt when acting as a hero moment.code-blockis ink-dark with mono text, styled like a small terminal. It gives dense pages a contrast pole and never sits tinted inside another tinted surface.
Composed product primitives:
- Buttons are pill-shaped.
button-primaryis ink-filled;button-secondaryis white;button-accentis peach;button-ghostis low-emphasis. - Inputs, selects, textareas, checkboxes, and toggles stay straight and quiet. Focus states use ink borders and sticker-style shadow.
- Chips are quieter than stickers and belong in tables, status rows, filters, and compact metadata.
- Tables use mono headers, generous row padding, and minimal accent.
- Tabs, breadcrumbs, pagination, navbar, and sidebar all stay flat. The BuildSpace logo mark may tilt, but the navigation items do not.
- Stats get the serif treatment because they are intended to feel editorial and important.
Recommended composition patterns from the reference page:
- Login form: centered card, one shape above the heading, stacked fields, one strong full-width CTA.
- Dashboard header: breadcrumbs, large serif title, status sticker, quiet chips, CTA row, then tabs.
- Empty deployments: centered empty state with one shape and dual actions.
Do's and Don'ts
- Do keep navigation, forms, and data displays calm and legible.
- Do use stickers, italics, tape dividers, and shapes to punctuate moments.
- Do reserve tilt for accents, not for the product shell.
- Do rely on warm neutrals and ink as the default product palette.
- Do use mono for labels, metadata, and system language.
- Don't tilt buttons, table rows, sidebar items, or input fields.
- Don't put 3D shapes inside dense operational UI.
- Don't replace every badge with a sticker; chips exist for the quiet cases.
- Don't overuse italic serif text. It works because it is selective.
- Don't swap the solid-offset sticker shadow for generic soft SaaS shadows.
- Don't fill card faces with pastel by default; white cards with accented details are the baseline.
- Don't repeat one pastel family across sibling cards or stacked steps — vary the family or stay neutral.
- Don't nest tinted surfaces inside tinted surfaces (e.g. a pastel code block inside a pastel card).
Semantic tokens (shadcn mapping)
The shadcn semantic variables in packages/ui/src/styles/globals.css map to this palette:
--background/--foreground: warm paper canvas + near-black ink.--card/--popover: true white surfaces lifted from the canvas.--primary: ink CTA tone paired with--primary-foregroundpaper text.--secondary: muted paper tone for supportive surfaces.--accent: lilac highlight surface, used sparingly.--muted: subtle neutral containers and separators.--border/--input/--ring: structural strokes and focus states.- Brand pastel utilities (
bg-mint-bg,bg-lilac-bg, etc.) exist for expressive moments and follow the card-and-accent discipline above.
Dark mode maps the same variables to the colors-dark palette above: ink foundations, paper-tone foreground, unchanged pastel accents.
Dark mode
Dark mode is a paper/ink swap, not a dimmed version of light mode. The brand's dark pole is already defined by the marketing pages — the ink #121212 used for CTAs, borders, code blocks, and offset shadows is neutral near-black, never brown. Dark mode adopts that ink as the canvas. Do not build dark surfaces by darkening the warm paper tones; that produces brown-charcoal (#211e1b-style) foundations that read muddy and rob the pastels of their pop.
- The canvas is
colors-dark.background(#121212) — the brand ink itself. Section bands and sidebars step tobackground-2; cards and popovers lift tosurface/surface-raised. All neutral grays, no warm cast. - Warmth moves into the text, not the canvas. Foreground stays the warm paper tone (
#F7F2EB), so dark mode reads as light mode inverted: neutral ink under warm paper, instead of warm paper under neutral ink. - Pastel families keep their light-mode values for icon tiles, dots, chips, chart series, and accent text. Pastels on near-black pop the way stickers on a blackboard do; on brown they curdle.
- Large pastel fills are rarer in dark mode. Marketing section bands and callout cards become lifted neutral panels (
background-2/surface) with the pastel carried by stickers, icon tiles, shapes, and italic accent words instead of the full surface. - The printed edge inverts: since an ink shadow can't cut against an ink canvas, borders do more of the work. Use
border/border-strongon lifted surfaces, keep the solid-offset shadow in pure black (rgba(0,0,0,0.5)+) and ensure card surfaces are lifted enough (#1E1E1E+) for the offset to still register. - Accent
*-bgtints used as small fills (icon tiles, chart fills) are fine as-is; avoid pairing*-textcolors with dark surfaces other than as accents — body copy stays paper-on-ink.
Accessibility
- Long-form body text stays on
textoverbackgroundorsurface. - Pastel-on-pastel combinations are decorative only, never for critical actions or control labels.
- Primary interactive controls keep the
primary/on-primarypairing. - Accent
*-textcolors are the only pastel-family tones approved for text, and only on their matching*-bg.
Raw design tokens (YAML frontmatter)
version: "alpha"
name: "BuildSpace"
description: "Ink & Paper: editorial serif headlines, composed product UI, pastel accents, sticker-lift shadows, and tilts reserved for expressive moments."
colors:
primary: "#121212"
on-primary: "#FBF9F7"
background: "#FBF9F7"
background-2: "#F3F1ED"
surface: "#FFFFFF"
text: "#121212"
text-strong: "#262626"
text-muted: "#666666"
text-subtle: "#8C8C8C"
border: "#E0E0E0"
border-strong: "#D1D1D1"
lilac-bg: "#EFDCF9"
lilac-icon: "#E2BEF4"
lilac-text: "#773399"
lilac-dot: "#B152E0"
peach-bg: "#FCEBD9"
peach-icon: "#F8D1AA"
peach-text: "#A35C29"
peach-dot: "#EE8C2B"
mint-bg: "#D1F0DC"
mint-icon: "#ABE3BF"
mint-text: "#267342"
mint-dot: "#24DB67"
sky-bg: "#D4F1F7"
sky-icon: "#A8E4F0"
sky-text: "#266673"
sky-dot: "#67CFE4"
butter-bg: "#FCF3C5"
butter-icon: "#F9E586"
butter-text: "#8F6B24"
butter-dot: "#F7E06E"
rose-bg: "#FADBE6"
rose-icon: "#F4AFC6"
rose-text: "#A32952"
rose-dot: "#EC799F"
colors-dark:
background: "#121212"
background-2: "#1A1A1A"
surface: "#1E1E1E"
surface-raised: "#242424"
text: "#F7F2EB"
text-strong: "#FBF9F7"
text-muted: "#A8A29A"
text-subtle: "#7A756E"
border: "#2E2E2E"
border-strong: "#3D3D3D"
primary: "#F7F2EB"
on-primary: "#121212"
typography:
display:
fontFamily: "DM Serif Display"
fontSize: "4.5rem"
fontWeight: 400
lineHeight: 0.95
letterSpacing: "-0.03em"
h1:
fontFamily: "DM Serif Display"
fontSize: "2.75rem"
fontWeight: 400
lineHeight: 1
letterSpacing: "-0.02em"
h2:
fontFamily: "DM Serif Display"
fontSize: "2rem"
fontWeight: 400
lineHeight: 1
letterSpacing: "-0.02em"
h3:
fontFamily: "DM Serif Display"
fontSize: "1.375rem"
fontWeight: 400
lineHeight: 1.15
letterSpacing: "-0.02em"
body:
fontFamily: "DM Sans"
fontSize: "0.9375rem"
fontWeight: 400
lineHeight: 1.55
body-lg:
fontFamily: "DM Sans"
fontSize: "1rem"
fontWeight: 400
lineHeight: 1.55
label:
fontFamily: "DM Sans"
fontSize: "0.875rem"
fontWeight: 500
lineHeight: 1.4
caption:
fontFamily: "DM Sans"
fontSize: "0.8125rem"
fontWeight: 400
lineHeight: 1.45
mono:
fontFamily: "JetBrains Mono"
fontSize: "0.6875rem"
fontWeight: 500
lineHeight: 1.4
letterSpacing: "0.08em"
rounded:
xs: "6px"
sm: "10px"
md: "14px"
lg: "20px"
xl: "28px"
pill: "999px"
spacing:
1: "4px"
2: "8px"
3: "12px"
4: "16px"
5: "20px"
6: "24px"
7: "32px"
8: "40px"
9: "56px"
10: "72px"
components:
sticker:
backgroundColor: "{colors.butter-bg}"
textColor: "{colors.butter-text}"
typography: "{typography.mono}"
rounded: "{rounded.pill}"
padding: "4px 12px"
chip:
backgroundColor: "{colors.surface}"
textColor: "{colors.text-strong}"
typography: "{typography.caption}"
rounded: "{rounded.pill}"
padding: "4px 10px"
button-primary:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
typography: "{typography.label}"
rounded: "{rounded.pill}"
padding: "10px 18px"
button-secondary:
backgroundColor: "{colors.surface}"
textColor: "{colors.text}"
typography: "{typography.label}"
rounded: "{rounded.pill}"
padding: "10px 18px"
button-accent:
backgroundColor: "{colors.peach-bg}"
textColor: "{colors.text}"
typography: "{typography.label}"
rounded: "{rounded.pill}"
padding: "10px 18px"
button-ghost:
backgroundColor: "{colors.background}"
textColor: "{colors.text-strong}"
typography: "{typography.label}"
rounded: "{rounded.pill}"
padding: "10px 18px"
input:
backgroundColor: "{colors.surface}"
textColor: "{colors.text}"
typography: "{typography.body}"
rounded: "{rounded.sm}"
padding: "10px 14px"
card:
backgroundColor: "{colors.surface}"
textColor: "{colors.text}"
borderColor: "{colors.primary}"
rounded: "{rounded.lg}"
padding: "{spacing.6}"
card-callout:
backgroundColor: "{colors.mint-bg}"
textColor: "{colors.text}"
borderColor: "{colors.primary}"
rounded: "{rounded.lg}"
padding: "{spacing.6}"
code-block:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
typography: "{typography.mono}"
rounded: "{rounded.md}"
padding: "{spacing.4}"
tabs:
backgroundColor: "{colors.background-2}"
textColor: "{colors.text-strong}"
typography: "{typography.caption}"
rounded: "{rounded.pill}"
padding: "4px"
table:
backgroundColor: "{colors.surface}"
textColor: "{colors.text}"
typography: "{typography.body}"
rounded: "{rounded.md}"
empty-state:
backgroundColor: "{colors.background}"
textColor: "{colors.text}"
rounded: "{rounded.lg}"
padding: "{spacing.8}"