Skip to content

Running headers & footers

Running headers and footers are the lines of context that repeat across a book's pages — the title, the current chapter, the page number. Keystone composes them from pandoc.yaml.

PDF only

Running headers, footers, and page numbers are a PDF feature. EPUB and DOCX/ODT have no fixed pages, so every key on this page is ignored for those formats.

Chapter-opening pages and the table of contents stay deliberately bare — the heading is the only landmark there. Running content resumes from the second page of each section.

Set free-form inline content for the header, the footer, or both:

header-text: "The Lighthouse"
footer-text: "© 2026 Jane Doe"

This puts the text in the center slot. Set any key to disabled to suppress it.

Recto and verso

Two-sided books (book / scrbook) can carry different content on right-hand (recto) and left-hand (verso) pages — the classic layout has the book title on the verso and the chapter title on the recto:

header-text-recto: "{chapter}"
header-text-verso: "{title}"

Each parity key falls back to the un-suffixed header-text (or footer-text) when blank. On single-sided targets every page is treated as recto, so use the un-suffixed key there. Whether a target is two-sided is set by the target — see Targets.

Placeholders

Embed values with {name} tokens. Some resolve once at build time (static), others update as the document paginates (dynamic):

Token Kind Resolves to
{title} static the title: metadata
{author} static the author: metadata
{date} static the date: metadata
{page} dynamic the current page number
{chapter} dynamic the current chapter title
{section} dynamic the current section title

You're not limited to these six

Declare your own dynamic placeholders for running content no heading tracks — a poem's author, a part title — with author-declared marks.

footer-text: "Chapter {chapter} — {page}"

To print a literal brace, double it ({{, }}). An unrecognized name emits a build warning and passes through as literal text — loud about the typo without breaking the build.

Substitution happens inside surrounding inline markup, so you can style a placeholder:

header-text: "**{chapter}**"                         # bold
header-text: "[{title}]{.smallcaps}"                 # small caps
header-text: "[{author}]{.font family=eb-garamond}"  # a different font

Page numbers

page-number-position places the folio, in the form <row>:<col>:

  • rowheader, footer, or header-and-footer
  • colleft, center, right, or the parity-aware outer / inner

outer is right on recto and left on verso (the outside edge, where a thumbing finger lands); inner is the mirror. The default is footer:outer — the book-typography convention. On single-sided targets, outer resolves to right.

page-number-position: footer:outer

If the page number lands on a row's center slot and that row also has text, the page number wins and the text is suppressed with a build warning.

The header rule

By default there's no rule under the running header. Add a thin one on body pages with:

header-rule: enabled    # default: disabled

It follows the same convention as the running header — never on chapter-opening pages or the table of contents.

The canonical book pattern

Trade and academic books converge on this:

header-text-recto: "{chapter}"
header-text-verso: "{title}"
page-number-position: footer:outer

The reader sees the book title on the left of every spread, the chapter on the right, and the folio on the outside edge. footer:outer is the default, so that line can be omitted.

Author-declared marks

The six built-in placeholders track metadata and headings. For running content that no heading tracks — a poetry anthology naming the current poem on each spread — declare your own mark channel in pandoc.yaml:

marks:
  - poem-author
  - poem-title

header-text-recto: "[{poem-author} — {poem-title}]{.smallcaps}"

Set a declared mark from the manuscript with the set shortcut. It produces no visible output in any format and holds its value until the next set for that mark (empty content clears it):

[John Keats]{.set mark="poem-author"}
[Ode on a Grecian Urn]{.set mark="poem-title"}

## Ode on a Grecian Urn {.unnumbered}

{poem-author} then resolves in headers exactly like a built-in dynamic placeholder, per page. Declaring the mark is also what makes it typo-safe: an undeclared {name} warns and passes through, while a set naming an undeclared mark is a hard error.

For content you set repeatedly, wrap set in a shortcut so you set marks by meaning rather than repeating mark="…" — see Writing your own shortcuts.