Skip to main content

Configuration

Theme

Pick from 10 built-in themes, override brand colors per mode, swap fonts, and set backgrounds — the complete appearance surface for a NookDocs site.

A theme bundles layout decisions (header rows, tab position, sidebar style, breadcrumb style) with CSS tokens (colors, typography, spacing, radius). You pick a theme by slug in nookdocs.config.json#theme, then override any piece with colors, background, typography, and appearance. Dark mode is automatic — every token has a light + dark value.

{
  "$schema": "https://nookdocs.com/schema.json",
  "name": "Acme Docs",
  "theme": "cedar",
  "colors": {
    "primary": "#0ea5e9",
    "logo": { "light": "/logo/light.svg", "dark": "/logo/dark.svg" }
  },
  "appearance": { "default": "system" }
}

Theme catalog

Ten presets ship out of the box. Each is a ThemeDefinition at src/lib/theme/themes/<slug>.ts that wires layout knobs to the shared token base.

SlugNameBest forLayout highlights
cedarCedarDeveloper docs with many tabs2-row header, underline tabs, header search bar
obsidianObsidianDev-tools with a dark brandDark-first, sharp edges, no decoration — Linear-inspired
larchLarch (default)AI / SaaS productsSidebar-first warm autumn, amber accents — tabs listed in the rail
emberEmberFast-moving startupsPill navigation, lightweight chrome
birchBirchEnterprise docsDeep customization, institutional feel
sageSageMarketing-adjacent docsCard-based minimal, teal tones
slateSlateDashboard-linked docsHeaderless — UPPERCASE mono labels, tabs collapse into one rail dropdown
oakOakAI products with warm brandWarm golden accents, modern
cypressCypressLong-form content docsSerif headings, magazine feel
terminalTerminalHacker / CLI toolsMonospace everywhere, retro terminal

Backward-compatible aliases also resolve: maplelarch (renamed 2026-05-05), classiccedar, modernember, minimalsage.

Where your navigation lands

The theme decides where each piece of chrome sits. Same navigation array, same navbar config — different placement:

Most themeslarchslate
Tabsstrip across the headerlisted down the railone dropdown at the top of the rail
Searchin the headerin the railin the rail
Appearance / languageheaderrail footerrail footer
Version / productheaderrail footerrail footer

Nothing here is fixed. navbar.controls moves any control to "header" or "sidebar" regardless of the theme — in the dashboard under Configurations → Site → Navbar, where each control has a Theme default option that writes nothing to your config. See Site settings.

On narrow screens and phones every theme behaves the same way: the rail and the tab strip step aside, and search, the assistant and a breadcrumb appear in a row beside the menu button.

theme'cedar' | 'obsidian' | 'birch' | 'oak' | 'cypress' | 'ember' | 'larch' | 'sage' | 'slate' | 'terminal'pathdefault: cedar

Built-in theme slug. Determines the shell layout (header rows, tab position, sidebar style) and the default token palette. Override individual tokens via colors, background, typography.

Appearance (light / dark)

Controls the default color-scheme and whether visitors can toggle it.

appearance.default'light' | 'dark' | 'system'pathdefault: system

Initial color scheme a visitor sees before they toggle. system honors their OS preference via prefers-color-scheme.

appearance.strictbooleanpathdefault: false

When true, hides the theme toggle entirely and forces a single mode. Use for brand-mandated single-mode sites. Docs still render both palettes so previews in the editor work.

Brand colors

Four overrides layer on top of the active theme's token palette. Leave any of them unset to inherit from the theme.

colors.primarystringpath

Primary accent color — buttons, links, focus rings. Hex only (e.g. #0ea5e9). Used when colors.light / colors.dark are omitted.

colors.lightstringpath

Primary accent applied in light mode. Takes precedence over colors.primary.

colors.darkstringpath

Primary accent applied in dark mode. Takes precedence over colors.primary.

colors.logo.lightstringpath

Logo path (repo-relative, /logo/light.svg) or absolute URL for light mode.

colors.logo.darkstringpath

Logo path or URL for dark mode. Falls back to colors.logo.light when omitted.

colors.logo.hrefstringpathdefault: /

Click target for the logo. Use when the docs shouldn't route back to /.

Background

Each theme ships its own background. Cedar paints a spotlight gradient, Obsidian a near-black #09090b, Terminal a warm cream — you get the theme's own tone automatically. background is an optional override: set it only when you want something other than the theme default.

  • Omit background → the active theme's background is used.

  • Set background.light and/or background.dark → that mode is overridden; the other mode still inherits the theme. Partial overrides (dark-only, light-only) are fully supported.

Solid colors or CSS gradients both work — anything the browser accepts for background, including linear-gradient(...), radial-gradient(...), and CSS custom properties.

background.lightstringpath

Override the light-mode page background. Example: "#f9fafb" or "linear-gradient(180deg, #fafafa, #f3f4f6)". Omit to inherit the theme's light background.

background.darkstringpath

Override the dark-mode page background. Example: "#0a0a0a" or "radial-gradient(at top, #111827, #030712)". Omit to inherit the theme's dark background.

Because overrides are opt-in, your config stays minimal and theme background updates flow through automatically — if you never set background, switching themes always gives you the new theme's tone.

Typography

Emitted as CSS custom properties (--docs-font-sans, --docs-font-heading, --docs-font-body) and read by every theme. Load the font files yourself (Google Fonts <link>, @font-face in custom-scripts, or a system-font stack).

typography.fontFamilystringpath

Default sans-serif font — used when headingFont / bodyFont are omitted. Sets --docs-font-sans.

typography.headingFontstringpath

Font stack applied to h1h4. Falls through to fontFamily when omitted. Sets --docs-font-heading.

typography.bodyFontstringpath

Font stack for paragraph + inline content. Falls through to fontFamily when omitted. Sets --docs-font-body.

{
  "typography": {
    "headingFont": "'Geist', system-ui, sans-serif",
    "bodyFont": "'Inter', system-ui, sans-serif"
  }
}

Complete example

Paste-ready block combining every appearance-related key. Drop into your nookdocs.config.json, tweak slugs/colors/paths, deploy.

{
  "$schema": "https://nookdocs.com/schema.json",
  "name": "Acme Docs",
  "theme": "larch",
  "appearance": {
    "default": "system",
    "strict": false
  },
  "colors": {
    "primary": "#0ea5e9",
    "light": "#0284c7",
    "dark": "#38bdf8",
    "logo": {
      "light": "/logo/acme-light.svg",
      "dark": "/logo/acme-dark.svg",
      "href": "https://acme.com"
    }
  },
  "background": {
    "light": "#ffffff",
    "dark": "radial-gradient(at top, #0f172a 0%, #020617 100%)"
  },
  "typography": {
    "headingFont": "'Geist', system-ui, sans-serif",
    "bodyFont": "'Inter', system-ui, sans-serif"
  }
}

Precedence rules

When multiple values could apply, NookDocs resolves in this order (last wins):

  1. Theme defaultthemes/<slug>.ts ships tokensLight + tokensDark (including the background)

  2. colors.primary — used for both modes when no per-mode override

  3. colors.light / colors.dark — overrides per-mode

  4. background.* / typography.* — optional overrides, emitted as CSS custom properties at #docs-root scope. A given mode is only overridden when its background key is present; otherwise the theme background stands.

  5. Preview header?preview_theme=<slug> (editor only) swaps the active theme definition at render time

This means colors.dark always wins over colors.primary in dark mode, and any per-tenant override always wins over the theme defaults — but an absent background key means "use the theme," not "use white/black."

Preview shows the theme, not your site. ?preview_theme= deliberately skips your colors and background overrides so you can see each theme as it was designed — otherwise every theme would render with the same overridden background and they would look identical.

So if you have set background, preview and your live site will differ. That is expected: preview answers "what does this theme look like," your live site answers "what does my site look like." Remove the override (or use Reset to theme in the dashboard) if you want your site to follow whichever theme you pick.

Editing from the dashboard

Configurations → Site surfaces every field above. When you pick a theme, the accent and background fields preview that theme's own colors; they're only written to nookdocs.config.json if you edit them, and each field has a Reset to theme action to drop the override and fall back to the theme default. A field showing Theme default is following the theme and will keep following it through future theme switches — so you can try several themes and see each one's real palette, then pin only the colors you actually want to differ. The dashboard writes back to nookdocs.config.json in your repo on save (git commit via the GitHub App), so dashboard edits and hand-edits stay in sync. Run npm run check:sync before committing schema additions — see schema reference for the validator rules.

Related

  • Schema reference — auto-generated field-by-field reference for every nookdocs.config.json key

  • Brand — favicon, OG image, manifest, PWA assets beyond logos

  • Custom domain — DNS, SSL, and canonical URL setup

  • Site settings — banner, SEO, redirects, footer, navbar

Was this page helpful?

Last updated August 10, 2026

Theme | NookDocs | NookDocs