Skip to content

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 papersize and geometry (see Book metadata).
  • EPUB → e-book stores and readers. EPUB is what e-book retailers and reading apps expect. Set a cover with cover-image so it appears in the store listing and the reader's library.

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 / geometry to 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-image covers 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.