---
title: Typography and layout
description: Fonts, dimensions, and the difference between omitting a field and setting it.
---

## `typography`

```json
{
  "typography": {
    "headings": "Inter, sans-serif",
    "body": "Inter, sans-serif",
    "code": "JetBrains Mono, monospace"
  }
}
```

Three optional font-family strings, 1–200 characters each. They are CSS font-family
values, so include your fallbacks — Reed passes the string through rather than parsing it.

Reed does not fetch or bundle web fonts. Load them yourself through `customCss`, which is
the highest cascade layer and therefore the right place for an `@font-face` or an import.

## `layout`

```json
{
  "layout": {
    "header-height": 64,
    "page-width": 1280,
    "content-width": 800,
    "sidebar-width": 280
  }
}
```

| Field | Default | Range |
|---|---|---|
| `header-height` | 64 | 32–160 |
| `page-width` | 1280 | 640–1920 |
| `content-width` | 800 | 480–1600 |
| `sidebar-width` | 280 | 160–480 |

Out-of-range values are schema errors, not silently clamped. A `page-width` of `3000` is
a mistake worth surfacing, not a value to quietly reduce.

## Omitting is not defaulting

This is the one non-obvious rule on this page.

A `layout` value is emitted as CSS **only when you set it explicitly**. Omit it and the
active template's own baseline controls that dimension.

The difference is visible on `rapide` (260px baseline sidebar) and `black` (300px). Omit
`sidebar-width` and each renders at its own designed width. Set it to `280` and both obey
you. `mint`'s baseline already matches every schema default, so nothing changes there
either way.

If a template's sidebar width looks wrong after an upgrade, check whether you were relying
on a value you never actually set.

`typography` has no equivalent behaviour — those fields have no schema default to
disambiguate from a template value in the first place.
