Skip to content

Blockhaus

Cream paper, black ink, wide geometric headlines. Every section is a ruled block and every action a pill.

  • Light by default
  • 35 colours · 14 type steps
  • Inspired by helloivy.co
Use Blockhaus
localhost:3000

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

What it is

Blockhaus builds every page from ruled blocks, like a design journal printed on cream paper. The palette is black ink, cream and one slate grey, with white sheets for the product itself. Headlines are set in Unbounded, a wide geometric face, and everything else in Inter. Every section sits in square cells drawn with 1px black rules, every action is a black pill, and nothing casts a shadow. Colour appears only in status and in six risograph inks for charts.

Maintained by @agentic-studio in the open registry.

Best for

Tools for designers, studios and agencies: project management, briefs, reviews, portfolios and creative ops. Also any product that wants to look printed and sure of itself instead of glossy.

Trade-offs

  • Unbounded is very wide. A 40 character hero title fills two lines at 72px and a longer one takes three, and long words wrap early on a phone. Keep headlines short.
  • Every frame is 1px of black ink. That is the look, but busy screens get heavy fast: rows inside a frame drop to a soft rule, and a framed box never sits inside another.
  • There is no brand colour. Links, focus and the accent are black, so a screen that must pull the eye does it with size, an ink block or the black pill. Status and charts are the only colour.

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

    #000000

  • accent-1

    #000000

  • accent-2

    #0078bf

  • accent-3

    #e05a1a

  • accent-4

    #765ba7

  • accent-5

    #008c4c

  • accent-6

    #e6399b

  • accent-hover

    #333333

  • accent-soft

    #efe8dc

  • primary

    #000000

Surface

  • canvas

    #faf6f0

  • hairline

    #000000

  • surface-card

    #ffffff

  • surface-dark

    #000000

  • surface-dark-elevated

    #1f1e1c

  • surface-soft

    #f3ede3

  • surface-solid

    #ffffff

  • surface-strong

    #e4dac9

Text

  • body

    #555555

  • body-strong

    #1f1f1f

  • ink

    #000000

  • muted

    #5e697f

  • muted-soft

    #7d8698

  • on-accent

    #ffffff

  • on-dark

    #faf6f0

  • on-primary

    #ffffff

Semantic

  • error

    #c02a26

  • success

    #1d7a46

  • warning

    #9a5b00

Other

  • danger

    #c02a26

  • danger-soft

    #fbe6e1

  • error-soft

    #fbe6e1

  • primary-hover

    #333333

  • success-soft

    #e6f1e4

  • warning-soft

    #f8ecd6

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
    4.5rem · 72px · 500 · lh 1.1 · ls 0
  • Ship faster

    Token
    display-lg
    Values
    3.5rem · 56px · 500 · lh 1.1 · ls 0
  • Ship faster

    Token
    display-md
    Values
    2.25rem · 36px · 500 · lh 1.2 · ls 0.005em
  • Ship faster

    Token
    display-sm
    Values
    1.875rem · 30px · 500 · lh 1.2 · ls 0.01em
  • Ship faster

    Token
    title-lg
    Values
    1.5rem · 24px · 500 · lh 1.3 · ls 0.01em
  • Ship faster

    Token
    body-lg
    Values
    1.125rem · 18px · 400 · lh 1.6 · ls -0.02em
  • Ship faster

    Token
    title-md
    Values
    1.125rem · 18px · 500 · lh 1.35 · ls 0.01em
  • Ship faster

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

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

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

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

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

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

    Token
    caption-uppercase
    Values
    0.75rem · 12px · 500 · lh 1.3 · 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.

  • DisplayUnbounded, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif
  • BodyInter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif
  • MonoMartian 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
  • section4rem · 64px

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.

  • lg0 · 0px
  • md0 · 0px
  • sm0 · 0px
  • xl0 · 0px
  • xs0 · 0px
  • full9999px
  • pill9999px

Elevation

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

  • inset0 0 #0000
  • lift0 0 #0000
  • overlay0 0 #0000
  • ring0 0 0 1px #000000
  • 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.

Blockhaus is a risograph design journal on cream paper: black ink, ruled blocks and one wide geometric headline doing all the talking. Every landing block sits in square cells drawn with 1px ink rules on the same two column lines. Every action is a black pill, product screens are white sheets, and pictures rest on a hatched kraft tray. Nothing casts a shadow, and colour is kept for status and charts.

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: black ink on cream paper (#faf6f0). Dark is the carbon print: warm near-black paper (#151412), cream ink and grey rules.
TypeUnbounded 500 for every heading, card and dialog title. Inter for everything else, tracked tight. Martian Mono only for code, keys and ids.
ColourBlack, cream, kraft and one slate grey (#5e697f) for secondary text. No brand colour: status and six risograph chart inks are the only hues.
ShapeEvery box is square. Only actions and marks are round: pill buttons, circle icon buttons, switches, radios, avatars and stamps.
DepthNone cast. Five of six shadows are empty and the ring thickens a 1px frame to 2px. Depth is paper: cream page, white sheets, kraft trays.
SignatureRuled cells on one column, eyebrows led by a 24 by 6px ink block, tick-ring stamps on the steps and a solid ink closing block.

Principles

  1. Every block is a ruled box: 1px ink frames, square corners, shared edges, no gaps.
  2. Every frame lands on the same two column lines.
  3. Round means action. Buttons are pills; boxes are square.
  4. Depth is paper and ink, never a shadow, glow, gradient or blur.
  5. Black pulls the eye. Colour is only for status and data.

Colour

Palette

TokenLightDarkRole
canvas (--background)#faf6f0#151412The page floor
surface-soft#f3ede3#0f0e0cSection bands, sidebars, table heads
surface-card (--muted)#ffffff#1e1c19Tinted fills: inactive tabs, hover rows, code
surface-strong#e4dac9#2f2c28Pressed fills, progress tracks
surface-solid (--popover)#ffffff#211f1cMenus, selects, toasts: always opaque
card#ffffff#1e1c19The card fill
surface-dark#000000#000000The inverted panel
hairline (--border)#000000#6b6761Every border and divider
ink (--foreground)#000000#f4efe6Headings and primary text
body-strong#1f1f1f#e8e2d8Emphasised body text
body#555555#c4bfb6Running text
muted (--muted-foreground)#5e697f#9aa3b5Secondary text, captions
muted-soft#7d8698#6f7788Placeholders, disabled text, icons at rest
primary#000000#f4efe6The action colour
accent (--accent-fill)#000000#f4efe6The saturated accent: links, the accent badge
accent-soft#efe8dc#2b2824The tint an accent label sits on
danger (--destructive)#c02a26#f0705fDestructive actions and errors

success, warning and error each come with a -soft tint for the back of a badge or an alert: #1d7a46, #9a5b00 and #c02a26 in light, #5cc98a, #e8a33d and #f0705f in dark.

Blockhaus's own variables, read by the landing hooks and the kit: --rule-soft (rgb(0 0 0 / 0.16) light, rgb(244 239 230 / 0.14) dark), --hatch (rgb(0 0 0 / 0.1) light, rgb(244 239 230 / 0.07) dark).

How colour is used

  • Ink (--foreground, black, cream in dark) draws headings, actions, rules, the feature icon blocks and the closing block.
  • Running text is charcoal (text-body, #555555). Secondary text, eyebrows and labels are slate (text-muted, #5e697f).
  • Surfaces are paper: the cream canvas, white sheets (bg-card) for product UI, kraft (bg-secondary, bg-surface-soft) for trays and secondary buttons.
  • The accent is ink too: links, focus and text-accent are black. Pull the eye with size, an ink block or the black pill.
  • Green, amber and red mark status only, as -soft tints with a 1px border in the full status colour.

Charts

accent-1 to accent-6 (also chart-1 to chart-6) are six series colours ordered so neighbours stay distinguishable. Six risograph inks in order: black, blue, orange, violet, green, pink (cream leads in dark). A single series is always black, and colour always pairs with a label or a pattern. 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 Blockhaus is drawn in light first. The theme menu in the header offers light, dark and system and remembers the choice.

Type

Faces

  • Unbounded (font-display): headings and display type.
  • Inter (font-body): running text and interface copy.
  • Martian Mono (font-mono): code, ids and tabular labels.

Unbounded is wide, geometric and a little quirky: at 72px it carries the whole brand, so the palette can stay quiet. Inter's optical sizes keep running text open and dense, and Martian Mono shares the headline's width, so a key or an id reads as part of the same voice.

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-xl72px1.10500The hero headline, desktop
text-display-lg56px1.10500The hero headline, tablet
text-display-md36px1.20.005em500Section headlines, the hero on phones
text-display-sm30px1.20.01em500Section headlines on phones, big numbers
text-title-lg24px1.30.01em500Page titles in the app
text-title-md18px1.350.01em500Card titles
text-title-sm16px1.40.01em500Small headings, table titles
text-body-lg18px1.6-0.02em400Lead paragraphs
text-body-md16px1.6-0.02em400Running text
text-body-sm14px1.55-0.01em400Interface copy, table cells
text-caption13px1.450500Metadata, helper text
text-caption-uppercase12px1.30.06em500Eyebrows above headings
text-button14px1-0.01em500Buttons
text-nav-link14px1.4-0.01em500Header and footer links

Rules: one h1 per page. Display sizes are for marketing pages; the app tops out at text-title-lg. Headings are Unbounded 500 from 16 to 72px, tracked 0 to 0.01em: never tighter, never in capitals, never under 16px. Inter runs -0.02em at 16px and up and -0.01em at 14px; labels are 12px capitals at +0.06em. Stat numbers and prices are Unbounded with tabular figures.

Space and layout

  • Spacing tokens: xxs 4px, xs 8px, sm 12px, md 16px, lg 24px, xl 32px, xxl 48px, section 64px (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 64px of section padding, so landing blocks sit about 128px apart.
  • Cells pad 24 to 32px, controls are 40px tall and elements sit 16px apart.
  • Header, hero, grids, showcase rows, FAQ, closing block and footer all share the content column's two edges.
  • Space separates sections. There are no bands and no rules between them.

Shape and depth

TokenValueWhere
rounded-xs0Not used by the kit
rounded-sm0The landing page
rounded-md0Toaster, the landing page
rounded-lg0The landing page
rounded-xl0The landing page
rounded-pill9999pxButton, Switch, Toaster, the landing page
rounded-full9999pxAccordion, Avatar, Dialog, RadioGroup, Sheet, Switch

Every radius is 0 except pill, which belongs to buttons, switches, radios, avatars, status dots and stamps. Borders are solid: a 1px ink rule on frames and fields, a soft rule (ink at 15%) for rows inside a frame, and 3 to 6px ink bars for emphasis. Shadows are empty; shadow-ring is a 1px ink ring that marks a selected card or a pressed toggle. Floating layers get an ink frame, not a shadow.

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 Blockhaus
ButtonA pill in every variant and size: Inter 14px 500, sentence case, no shadow. Primary is black with a white label, #333333 on hover, and presses down 1px. Secondary is kraft, outline is an ink ring that inverts to ink on hover and on the current page, ghost tints ink at 6%, danger is red. Sizes are 32, 40 and 48px tall; icon buttons are 40px circles. Focus is a second ink frame 2px outside, and disabled drops to 40%.
BadgeSquare, never a pill: a 1px border and a 13px 500 label. Neutral is a stamped ink outline, accent is an ink label with white text, and status badges are soft tints with a full-colour border.
CardSquare, no shadow. Default is a white sheet in a 1px ink frame; soft is a kraft cell in the same frame, strong is the darker kraft with no border, outline is a bare cream cell and dark is the ink block. Titles are Unbounded 18px 500.
Input, Textarea, Select40px white fields in a 1px ink frame, square, with 14px text, a pale slate placeholder and no hover change. Textareas start at 96px and resize vertically. Focus adds a second ink frame 2px outside; invalid turns the frame red. Select content is a white sheet in an ink frame; the highlighted option is inked with cream text and the chosen one shows a check.
Checkbox, RadioGroup, SwitchCheckboxes are 16px squares that fill with ink and a white check. Radios are circles with an 8px ink dot. The switch is a pill: white with an ink thumb when off, an ink track with a cream thumb when on.
TabsDefault is a segmented ink box: square cells split by ink rules, the active one inked with cream text. Line tabs sit on a 1px ink rule and mark the active tab with a 3px ink bar.
AccordionRows split by ink rules. Triggers are Unbounded 16px, underlined on hover. The chevron sits in a 24px ink ring that fills with ink and turns over when open.
Dialog, AlertDialog, SheetWhite square panels in a 1px ink frame, no shadow, over a 50% ink overlay with no blur. Titles are Unbounded 24px and left-aligned; actions are an outline pill, then a primary pill. Close is a 32px ghost circle. Sheets are cream with an ink rule on the inner edge and under the title.
DropdownMenu, Popover, Select content, TooltipWhite sheets in a 1px ink frame, square, no shadow. Highlighted items are inked with cream text, danger items fill red, labels are slate capitals, separators are the soft rule and shortcuts are Martian Mono 11px. Tooltips are small square ink blocks.
TableInter 14px with tabular figures. Heads are 12px slate capitals over a 1px ink rule, rows split by the soft rule, hover kraft, selected rows a kraft tint, and the footer is kraft under an ink rule. Right-align numbers and set ids and keys in font-mono at 12px.
AlertSquare, a 1px border and 16px of padding. Info is a white sheet in an ink frame; success, warning and danger are soft tints with a full-colour border, title and icon.
Avatar, Progress, Skeleton, Spinner, Separator, Kbd, Breadcrumb, Pagination, Field, Label, ToasterAvatars are circles with Unbounded initials on the darker kraft. Progress is an 8px square bar in an ink frame that fills with ink. Skeletons pulse slowly on the darker kraft and spinners are ink. Separators are 1px ink rules, soft inside menus and tables. Kbd is Martian Mono 11px on white with a 2px bottom edge. Breadcrumbs are slate links that underline in ink on hover; the current page is ink. In pagination the current page is an ink disc and the others are ghost circles. Labels are Inter 14px 500 in ink, with 13px slate descriptions and red errors, and fields stack 16px apart. Toasts are white sheets in an ink frame with a small ink pill action and an outline pill cancel.

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. Blockhaus styles these:

  • site-header: an opaque cream strip with no blur, holding a 72px ruled box on the column lines.
  • site-nav: from 64rem the middle cell, ruled on both sides, with ink links at its right. Hover draws a 1px underline; the current page gets a 3px ink bar.
  • brand and brand-mark: the name in Unbounded 500; the mark is an ink square with its letter in Unbounded.
  • hero: a ruled box hanging from the masthead box so the two share one rule, with everything left-aligned.
  • hero-backdrop: hidden. The hero is bare paper: no wash, no grid, no glow.
  • hero-title: Unbounded across the full width of the box, 30 to 36px on a phone; a long word breaks instead of clipping.
  • hero-subtitle: a near-black Inter deck that grows to 26px.
  • hero-eyebrow: a white pill with an ink edge; a linked eyebrow inverts to an ink pill on hover.
  • hero-visual and showcase-visual: a kraft tray with a faint 45 degree hatch. The hero tray is the box's second cell, under an ink rule.
  • product-preview and product-preview-bar: a white sheet in an ink frame with no shadow; the cream title bar turns its window dots into an ink circle, square and triangle, and rows inside its cards drop to the soft rule.
  • section: soft sections and the steps lose their bands and rules; space separates blocks.
  • section-heading: left-aligned. From 64rem it splits: eyebrow on its own row, title left (3fr), description right (2fr), bottoms aligned. The FAQ keeps its own two columns.
  • section-eyebrow: slate capitals led by a 24 by 6px ink block, on every section and showcase row.
  • feature-grid, feature-card and feature-icon: one ruled block of bare cream cells with no gaps, each led by a 40px ink square with a cream icon.
  • logo-cloud and logo: one ruled strip of equal cells, two across on a phone, each name centred in Unbounded slate. The strip title goes back to Inter capitals.
  • steps, step and step-marker: ruled cells with no connector lines. Each step opens with a stamp: a hollow 52px circle with an Unbounded numeral inside a ring of 24 ink ticks.
  • showcase-row and showcase-copy: each row is one box split into a cream copy cell and the hatched tray. Rows share edges, so the three read as one checkerboard block.
  • stat-grid, stat and stat-value: a 4px ink bar on top, left-aligned cells and Unbounded numbers up to 64px with tabular figures.
  • testimonial: the quotes become bare ruled cells hanging from the figures, set in 18px Inter in ink.
  • faq: a closed ruled box. Questions are Unbounded 16px, underlined on hover, with the chevron in a 30px ink ring that fills when open.
  • cta-band and cta-panel: a solid ink block with no wash and no shadow, a cream headline and cream pills, and from 64rem a tick-ring stamp in the top right corner. On a dark page it keeps a grey edge.
  • site-footer: cream paper, not a band. The colophon is the last ruled box on the column lines, with a 24px wordmark and Inter column heads.

Everything else is type, space and the kit.

Signed-in screens

The dashboard is the same paper at work: a kraft sidebar ruled off in ink, Unbounded 24px page titles, white card sheets in ink frames, black pill actions and tables with Inter capital heads over an ink rule.

Sign-in is one narrow white sheet in an ink frame on bare cream, with ink-framed fields, a full-width black pill and outline pills for the providers.

Do and don't

Do

  • Put every landing section's content in ruled cells: 1px ink frames, square corners, shared edges, no gaps.
  • Line up every framed block on the content column: header, hero, grids, showcase rows, FAQ, closing block and footer.
  • Set every heading (h1 to h6, card, dialog and sheet titles, FAQ questions) in Unbounded 500, everything else in Inter, and code in Martian Mono.
  • Make every action a pill: the black primary for the one main action, outline or ghost pills for the rest.
  • Put product UI on white sheets (bg-card) and pictures on the hatched kraft tray.
  • Keep running text in text-body and secondary text in text-muted. Keep black for headings, actions and rules.
  • Plot data in the chart inks in order: black, blue, orange, violet, green, pink. A single series is always black.
  • Check both prints every time, including the black closing block, which gains a grey edge on a dark page.

Don't

  • Don't add a shadow, a glow, a gradient or a blur. Depth is paper and ink.
  • Don't round a box. Cards, fields, menus, dialogs, tabs, badges and tooltips stay square.
  • Don't make anything that is not an action into a pill: not a badge, a label, an input or a section eyebrow.
  • Don't put a framed box inside another framed box. Inside a frame, divide with the soft rule.
  • Don't add a brand colour: no blue links, no tinted buttons, no coloured bands.
  • Don't use the chart inks for text, icons, borders or decoration.
  • Don't set Unbounded below 16px, in capitals, in running text or with negative tracking.
  • Don't use dashed or dotted lines. The stamp ticks and the tray hatch are the only broken marks.

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 Blockhaus

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