---
title: Theme
description: Understand how presets, colors, and fonts layer in docs.json so your docs match your brand in light and dark mode.
---

Your docs should feel like part of your product, not a generic template. The `theme` block in `docs.json` controls that first impression: typography, accent colors, and how the site looks when readers switch between light and dark mode.

## Overview

docs.page themes are **CSS-variable based**. When a reader opens your site, the renderer loads a base palette, optionally applies a [shadcn/ui](https://ui.shadcn.com/create) preset, then merges any custom hex colors you declare. Components (sidebar, callouts, buttons, code blocks) read from the same variables, so a small config change updates the whole site.

Everything lives under the top-level `theme` key in `docs.json`. You do not edit hosted CSS files or redeploy a theme package; commit changes to your GitHub repo and the live site picks them up on the next request.

```json
"theme": {
  "preset": "bcj0c6sa",
  "primary": "#E69135"
}
```

Field names, types, and defaults live in [docs.json](/reference/docs-json): this page explains the model, not every key.

## How it works

### Presets

A **preset** is a short code from the shadcn/ui theme registry. When you set `theme.preset`, docs.page resolves that code while parsing `docs.json` into a bundle of CSS: color tokens for light and dark mode, border radii, and font pairings for body and heading text.

Presets are the fastest way to get a cohesive look. Pick a code on [ui.shadcn.com](https://ui.shadcn.com), drop it into `docs.json`, and preview with [`docs preview`](/features/local-preview) or a [branch preview](/features/branch-preview) before you merge.

If the code is invalid or cannot be resolved, docs.page falls back to the default site palette. Other `theme` fields still apply.

### Light and dark mode

Every hosted site supports **light** and **dark** appearance. docs.page toggles modes with a `dark` class on the document root (via [next-themes](https://github.com/pacocoursey/next-themes)). Preset CSS defines separate token values for `:root` and `.dark`, so backgrounds, borders, and text stay balanced in both modes.

Readers switch modes from the **theme toggle** in the site header. The `header` schema also defines `showThemeToggle`, but that field is **schema only:** the toggle always renders on hosted sites today. See [Header](/features/header) and [docs.json: Schema-only fields](/reference/docs-json#schema-only-fields).

The `theme` block accepts `defaultTheme` (`light` or `dark`) to pin the starting mode. That field is also **schema only:** readers still get the platform default until default-theme support ships. Mode-specific color overrides apply only in the matching mode.

### Colors

Beyond a preset, you can override individual tokens with **six-digit hex colors** (`#RRGGBB`, with or without the leading `#`).

Use `primary` for accent color across links, buttons, and other interactive elements. When light and dark modes need different accents, set `primaryLight` and `primaryDark`; each falls back to `primary` when omitted. Set `backgroundLight` and `backgroundDark` to adjust page background per mode.

Invalid hex strings are ignored rather than breaking the site. Custom colors inject as CSS overrides on top of the preset (or the default palette when no preset is set), so you can keep a preset's typography while nudging brand orange into `--primary`.

### Fonts

Typography comes from the preset when you set `theme.preset`. Each preset selects a **sans** font for body text and a **heading** font for titles; docs.page maps those choices onto CSS variables (`--font-sans`, `--font-heading`) and loads the matching [Google Fonts](https://fonts.google.com) faces at runtime.

The platform maintains a fixed registry of supported families (Inter, Geist, Lexend, Instrument Sans, JetBrains Mono, and others), so preset font names always resolve to web-safe files. You do not configure font keys directly in `docs.json`; they travel with the preset code.

To change fonts, switch presets or pick a different code on shadcn/ui that pairs the typefaces you want.

## Related

<CardGroup cols={2}>
  <Card title="Reference" icon="book" href="/reference/docs-json">
    Field-by-field lookup for `theme`, `header`, and the rest of site configuration.
  </Card>
  <Card title="Local preview" icon="eye" href="/features/local-preview">
    See preset and color changes in the browser before you push to GitHub.
  </Card>
  <Card title="Logo" icon="image" href="/features/logo">
    Set light and dark logos and favicons alongside your theme colors.
  </Card>
  <Card title="Header" icon="window-maximize" href="/features/header">
    Control the theme toggle, site name, GitHub link, and header CTAs.
  </Card>
</CardGroup>
