Docs / Theming & branding
Theming & branding
The starter uses CSS variables as the design-token layer, Tailwind for layout and atomic styles, and a set of small typography primitives for editorial rhythm. There's no styled-components, no Emotion, no design-system runtime.
Where tokens live #
app/globals.css defines the CSS variables — colors, font families, radii. They're consumed by Tailwind via the theme extension in tailwind.config.ts. Change a variable and everything that references it updates.
The shorthand to remember: --background, --foreground, --muted, --muted-foreground, --border, --brand. Tailwind classes (bg-background, text-foreground, border-border, text-brand) map straight to these.
Typography primitives #
Editorial pages compose from a small set of components in components/typography.tsx:
<Display>— the page-scale headline. Sans by default;as="serif"for italic pull-quote moments.<Heading>— section heading, smaller than Display.<Lede>— the standfirst paragraph after a Display.<Eyebrow>— mono uppercase label that opens a section.<Pull>— a serif-italic inline phrase, used inside Display for emphasis.
Use these instead of hand-typed <h1> + classes. Consistency across pages comes for free.
Layout primitives #
From components/section.tsx:
<Section spacing="default|tight|loose">— owns vertical rhythm.<Container size="default|wide|narrow">— owns horizontal rhythm.
Don't repeat py- numbers in individual pages; the Section component is the single source of truth. If a page needs unusual spacing, that's a signal to tune Section, not to add a one-off py- class.
Changing the look #
To rebrand the starter:
- Edit the CSS variables in
app/globals.css. That's where the palette lives. - Swap the font in
app/layout.tsxif needed. The starter uses two Google fonts (a sans for body, a serif for editorial moments). - Replace the marks in
public/.
Don't fight the primitives — they're tuned for editorial pages, which is what most marketing sites are. If your app needs a different rhythm (a dense dashboard, a chat UI), build new primitives for it; don't override the existing ones globally.
Dark mode #
Not enabled in the starter by default. The token system supports it (.dark selector overrides in globals.css), but the default ships light-only. Add a theme toggle when you need it; don't ship one before you do.