Publishing your book
Keystone's output is publication-ready: the PDF is a print-quality file and the EPUB is a standards-compliant e-book. When the writing is done, the last step is getting those files to readers — Keystone produces the artifacts, and a publishing platform handles printing and distribution.
Which file goes where
- PDF → print. Print-on-demand (POD) services and offset printers take a PDF. Match your page setup to the printer's
spec first — trim size and binding margins both come from
papersizeandgeometry(see Book metadata). - EPUB → e-book stores and readers. EPUB is what e-book retailers and reading apps expect. Set a cover with
cover-imageso it appears in the store listing and the reader's library.
Print-on-demand and self-publishing
These platforms turn your files into a printed book, an e-book listing, or both. Common starting points:
- Lulu — print-on-demand and distribution.
- Amazon KDP — print and Kindle on Amazon.
- IngramSpark — print distribution to retailers and libraries.
- Draft2Digital — e-book distribution across multiple stores.
Keystone doesn't endorse any of these. Each sets its own specs for trim size,
bleed (art that extends past the trim edge), margins, and metadata — read theirs and match yours in
pandoc.yaml.
Before you upload
A short checklist for a first book:
- Pick a trim size and set
papersize/geometryto match the platform's template — see Page sizes. Common print-on-demand trims are 6×9in, 5×8in, 5.5×8.5in, and 8.5×8.5in square. - Set the gutter if the book will be bound — the spine takes part of the inner margin, and the default reserves nothing for it. See The gutter.
- Add a cover.
cover-imagecovers the EPUB; print covers are usually a separate wraparound file the platform builds to your page count. - Get an ISBN if you want retail distribution — some platforms provide one free.
- Proof the PDF at full size, and open the EPUB in a couple of readers to check how it reflows.
- Fill in your metadata — title, author, description, and keywords all carry into the files (see Book metadata).
Watching a build run
A PDF spends most of its time typesetting, which prints nothing while it runs. Keystone names each stage as it starts, keeps a clock on the one in progress, and reports the total when the file lands:
Publishing target: 'book' | format: pdf
✓ Preparing your artifact 1.5s
✓ Typesetting (pass 1) 22.1s
✓ Typesetting (pass 2) 19.8s
✓ Typesetting (pass 3) 16.5s
OK: artifacts/my-project-book-20260101.pdf (1m 01s)
Typesetting runs more than once because a table of contents can't be laid out until the pages it points at exist; two to
four passes is normal. A stage that took under a second folds into Preparing your artifact, so what stays on screen is
what took time. A build that stops shows ✗ against the stage it stopped in, and that line appears whenever stages are
reported — a stage that fails is never folded away.
A build that reports every stage ✓ and then stops failed outside its stages, and its ERROR: says why — most often
the strict gate; see Strict builds.
Every stage but Typesetting is a heading in the error map, listing what it checks — Expanding shortcuts, Running handlers, Converting math and the rest appear in both. A warning from a fast stage arrives after that stage has folded, so match it by its message rather than by a stage line.
Reading your Markdown and Writing your artifact are Pandoc's, around Keystone's stages: parsing your chapters, and writing the file — for a PDF, the LaTeX source and its images, ahead of typesetting.
Saving hook assets, Finding your fonts and Collecting your fonts are EPUB-only: they save what your hooks
returned, when a hook is wired, find the fonts your book uses, and gather what travels with the fonts, and run no checks
of their own. An EPUB reads your chapters and expands your shortcuts in a pass of its own before them, reporting the
same stages as any build. Typesetting is the one worth knowing: it is LaTeX, not Keystone, so the lines quoted after a
✗ there are Pandoc's and LaTeX's own message — usually naming a line of generated source rather than yours, so suspect
raw LaTeX in your manuscript. A strict build refused for a warning stops there too, quoting
Failing because there were warnings. instead. A pass that stops the build shows how to read
LaTeX's message.
KEYSTONE_PROGRESS in project.conf sets how much of this you get:
| Mode | What it does |
|---|---|
auto |
Stages, folded and updating in place on a terminal; plain anywhere else, so CI needs no setting. The default |
plain |
Every stage on its own line, nothing folded and nothing redrawn |
off |
No stage reporting |
verbose |
Pandoc's raw output, unfiltered, for diagnosing a failure |
make publish progress=<mode> overrides it for one build.
The first three change only how much progress you see; a warning reads the same in all of them. verbose is the
exception: it shows Pandoc's own [WARNING] prefix and the full logs Keystone otherwise hides. That is what makes it
worth reaching for when the ordinary output doesn't explain a failure.
Strict builds for CI and release
While you're drafting, Keystone prints warnings — a mistyped attribute, an unrecognized placeholder, a missing font — and keeps going, so you always get something to look at. For the build you actually publish, you usually want the opposite: a warning should stop the line, not ship.
Set KEYSTONE_WARNINGS_AS_ERRORS=true to make any warning fail the build and write no new file — including the
lint's, like a fenced div you forgot to close. Turn it on in
project.conf for release builds, or run make publish strict=true in CI to
override that value without editing it — so automated builds stay strict while local drafts stay lenient.
The file you built is the file you publish — there's no separate export step.