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.
Header and footer text
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>:
- row —
header,footer, orheader-and-footer - col —
left,center,right, or the parity-awareouter/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.