When I say I’m writing a book, people picture a document. In my head there’s a repository with build profiles, and the PDF isn’t the book: it’s the artefact that comes out when the book compiles.
The difference shows up immediately in my strictest rule: I never invoke the compiler by hand. Everything goes through latexmk, with the profiles versioned in the repo. That isn’t pedantry. Calling the engine directly breaks the correspondence between source and PDF, and that correspondence is what lets me click a formula in the PDF and land on the exact source line that produced it. It’s the same reason you don’t hand-compile one file in a software project and then wonder why the debugger can’t find the symbols any more.
The part I enjoy most is that the same source produces three different physical formats. There’s the paperback at 7.5 by 9.25 inches, which is the reference format. There’s the version for large e-ink readers, ten inches, which is what I use to reread myself in an armchair. And there’s the hardcover, 7 by 10 inches, which has a problem all of its own: change the page proportions and the text reflows, so the pages no longer line up with the paperback’s.
I solved it with a scale factor applied to the whole text block. The hardcover’s type area is the paperback’s, enlarged just enough to fill a bigger page. The result is that all three editions share the same pagination, page for page: when a reader writes to tell me there’s an error on page 214, that’s page 214 for everyone, and one erratum covers the whole catalogue. Had I let each format reorganise itself, I’d be maintaining three books instead of one.
Out of that obsession came the script I’m proudest of, called drift.py, which does exactly one thing: it measures how far the pagination has moved between two builds. It sounds like a typesetter’s worry and it’s actually regression testing. Add three lines to chapter 3 and everything after it shifts, including cross-references and index entries. The drift figure tells you at a glance whether this morning’s edit cost zero pages or seven, and seven pages in an already typeset book is real work.
There’s also a declared technical debt, and it’s only fair to describe it. I compile with pdfLaTeX, while the branch that would produce a properly tagged, accessible PDF runs on a different engine that I haven’t touched in months. Last time I tried it, it produced files five times larger and about a hundred warnings, from incompatibilities between the packages I use for boxes and tables and the semantic tagging machinery. An accessible PDF is something I want, not something I have, and I’d rather write that down here than pretend otherwise.
The rest of the chain looks like any other project: a single bibliography shared across all editions, generated indexes, and no continuous integration, because the only client is me and the build runs on my machine every time I hit save.
You write a book once. Then you compile it three hundred times.
Last modified on 2026-07-06