The design system

Styleguide

Everything the public theme ships so far, on the tokens a site owner re-skins. The page auto-themes with your system light or dark setting.

Color tokens

The DaisyUI 5 oklch role tokens and the cairn on-surface inks. A re-skin edits these in theme.css; every surface reads them, so the whole site recolors together.

Base ladder

base-100
base-200
base-300
base-content

Brand and neutral

primary
primary-content
secondary
secondary-content
accent
accent-content
neutral
neutral-content

Status fills and their content

success
success-content
warning
warning-content
error
error-content
info
info-content

On-surface inks

A fill tone fails as small text, so each status word reads a darker ink than its matching fill. Each sample below is the ink painted as text on the page paper.

color-muted — the quick brown fox

cairn-success-ink — the quick brown fox

cairn-warning-ink — the quick brown fox

cairn-error-ink — the quick brown fox

cairn-info-ink — the quick brown fox

Type scale

A fluid editorial scale on a fixed ratio, authored with clamp() so the display scales while the body stays readable. Each row is one named step.

step-5 h1, masthead
Stacked one stone at a time
step-4 section display, stat
Stacked one stone at a time
step-3 h2
Stacked one stone at a time
step-2 h3, index title
Stacked one stone at a time
step-1 lead, h4
Stacked one stone at a time
step-0 body
Stacked one stone at a time
step--1 caption, meta
Stacked one stone at a time

The faces

display (Fraunces) headings, pull-quotes

Stacked one stone at a time

body (Source Sans 3) body, UI, captions

The quick brown fox jumps over the lazy dog

mono (Source Code Pro) code

const cairn = renderMarkdown(md);

The reading surface

A representative markdown sample run through the same render the article route calls. This is the bespoke, token-bound prose surface, not stock typography.

This is the reading surface. Every element below is rendered by the same theme a reader sees, so the styleguide shows the real prose output rather than an imitation of it.

You write in markdown, and the surface binds each element to the theme tokens. Change one token and the whole surface, this article included, re-skins in lockstep.

A second-level heading

A heading on the display face, bound to the text it introduces with a large space above and a tight space below.

A third-level heading

Inside a section. Reach for it when a section grows long enough to want its own parts.

Inside a paragraph you can make a word bold or italic, and link to the cairn project. Bold reads on a skim; italic is a lighter stress.

  • An unordered list with a small accent diamond marker.
  • Each item one line, parallel in shape.
  • The marker reads the brand accent.
  1. An ordered list for steps in sequence.
  2. The numbers render in the display face.
  3. They pick up the accent color.
  • A done item in a task list
  • Another finished step
  • An open item still to do
  • One more left

A blockquote, set apart with a left accent rule and italic type, for a passage worth slowing down for.

A pull-quote hangs into the margin on a wide screen and reads in the display face.

For a short snippet inside a sentence, wrap it in backticks so a filename like cairn.config.ts reads as code. For anything longer, a fenced block turns on the highlighter:

// A render adapter is the one seam the engine asks each site to fill.
export function render(markdown) {
  const trimmed = markdown.trim();
  return renderMarkdown(trimmed);
}

The highlighting colors come from the same token set as the rest of the page, so a re-skin recolors code with no edit:

:root {
  --color-primary: oklch(45% 0.1 248); /* the brand accent */
  --font-display: 'Fraunces Variable', serif; /* headings and pull-quotes */
}

A table handles its own alignment, the header rule, and the zebra striping:

ElementHow you write itWhat it is for
Heading## TextThe shape of the post
Bold**word**A term that should stand out
Code block\``lang`Showing code, with highlighting

A figure holds a picture and its caption together, placed in the text column:

A still mountain lake reflecting the peaks above it

A centered figure holds the measure of the text.


The horizontal rule above renders as a centered cairn mark. Below are the directive components, dropped into the text with a fenced block syntax.

Check the date before you publish

An alert is a heavier signal than a callout, set in a bordered card with an icon. Save it for the rare note a reader must not miss.

Islands

An island is a directive that renders a static, no-JavaScript fallback on the server, then a small client runtime mounts a live Svelte component over it. The banner below shows its fallback first, then becomes interactive once the page hydrates, re-checking its own expiry rather than trusting the server's render. The second banner has already expired, so it renders nothing, on the server and again independently once the page hydrates.

Components

The own-it component set, built on DaisyUI primitives and the tokens. Adopt them as shipped or edit the source; nothing is locked in node_modules. The directive components (callout and alert) render in the reading surface above.

Buttons

Tags and a badge

Markdown Cloudflare New

Card

A floating card

A card uses the elevation pair (a hairline border plus a soft shadow), never a flat border. It groups related content without a heavy box.

Tabs

The editing surface. You type raw markdown on the left.

Accordion

What is a callout?

A callout pulls one idea out of the flow of a post. It ships in three tones: note, tip, and warning.

How do I re-skin the theme?

Edit the role tokens in theme.css. About fourteen values cover a full re-brand, the prose surface included.

Call to action

Start writing on cairn

A static site you edit in markdown and publish from your browser.

Open the editor

Stat

14 role values to re-skin
0 client JS on the reading route
2 themes, light and dark