Skip to content

Project settings

project.conf holds a project's operational settings: the name on its output files, its Docker names, and how a build behaves. How the book looks and what metadata it carries is pandoc.yaml.

This page is the complete key reference. The file ships commented — a line per setting, grouped, each group linking the page that owns it.

How settings are applied

A value may reference one set above it: KEYSTONE_DOCKER_COMPOSE_PROJECT=keystone-${KEYSTONE_PROJECT} expands as written.

Some settings also take a one-run override on the command line, which wins over the file:

Setting One-run override
KEYSTONE_USING make publish using=<name>
KEYSTONE_WARNINGS_AS_ERRORS make publish strict=true
KEYSTONE_PROGRESS make publish progress=<mode>
KEYSTONE_HOOKS_KEEP_ALIVE make publish down=true

Project identity

Setting Notes
KEYSTONE_PROJECT Names the output files — <project>-<target>-<date>, e.g. my-project-book-20260101.pdf. A short, lowercase string without spaces. Defaults to keystone.

This is the project's name, not the book's — the title on the cover is title:. Left at keystone, the build warns and your artifacts carry Keystone's name.

Docker

Setting Notes
KEYSTONE_DOCKER_COMPOSE_PROJECT The Compose project namespace — the prefix on the networks, containers, and volumes a build creates. Defaults to keystone-${KEYSTONE_PROJECT}.
KEYSTONE_DOCKER_IMAGE core only. The image make image builds and the build runs; override it for the tag you push, or for a CI pipeline. Defaults to ${KEYSTONE_DOCKER_COMPOSE_PROJECT}:local.

The namespace is what keeps two Keystone projects on one machine from sharing a container. core-slim runs the published image, pinned by tag in its compose file — see Choosing a template.

Builds

Setting Notes
KEYSTONE_WARNINGS_AS_ERRORS true makes any warning fail the build and write no new file. Defaults to false. See Strict builds.
KEYSTONE_PROGRESS How much of a build is reported: auto (the default), plain, off, or verbose. See Watching a build run.

Build configurations

A configuration is a named set of symbols that gates parts of the manuscript, so one source produces several editions.

Setting Notes
KEYSTONE_DEFINE_<name> Declares one configuration: KEYSTONE_DEFINE_private="personal annotations drafts". The name takes letters, digits and underscores. Declare as many as you need.
KEYSTONE_USING The configuration to build when using= is omitted. Empty (the default) builds the plain edition.

Fully covered in Conditional content.

Hooks

A hook hands a fenced code block to a program you wire in. core-diagrams ships one, and its renderer starts a browser — which is what KEYSTONE_HOOKS_TIMEOUT is for. With no hook wired, nothing acts on the timeout or the cache settings. KEYSTONE_HOOKS_KEEP_ALIVE applies either way: it decides whether a finished build stops the project's containers, hook or no hook.

Setting Notes
KEYSTONE_HOOKS_KEEP_ALIVE Leaves hook containers running when a build finishes, so the next build does not start them again. false stops them, build succeeded or not. The file ships true, and an empty value keeps them too. Read by make, so make publish down=true overrides it for one build.
KEYSTONE_HOOKS_TIMEOUT Seconds a hook has to answer one block; a whole number of 1 or greater. Raise it for a renderer that starts a browser. Defaults to 30.
KEYSTONE_HOOKS_CACHE Where replies are remembered. A path inside artifacts/ lets you open what a hook produced; anywhere else needs a writable mount of its own. Empty (the default) is a volume the engine owns, cleared by make reset.
KEYSTONE_HOOKS_CACHE_MAX Megabytes the cache may hold before the least recently used replies are dropped; a whole number of 1 or greater. Defaults to 64.

Hooks keep running after a build

A hook holds its resources — mostly memory — for as long as it is up, and that is per project. Keeping it saves the next build a second or so on a fast machine; stopping it leaves the machine free between builds, and the hook cache stays either way. Decide once with KEYSTONE_HOOKS_KEEP_ALIVE; make publish down=true covers a one-off.

A build that stops on the timeout or either cache setting names it — see A hook that fails. KEYSTONE_HOOKS_KEEP_ALIVE is make's rather than the engine's, so a value it does not recognize leaves containers running instead of failing anything.

Diagrams

Shipped in core-diagrams, whose hook reads them. These are the diagram hook's own settings — Keystone passes them through untouched, and the vocabulary is mermaid's. Wiring that hook into another template means adding these keys and passing them to its service: Wiring a published hook.

Each is house style: a single diagram can name its own and what it names wins.

Setting Notes
KEYSTONE_DIAGRAMS_THEME The palette every diagram is drawn with: default, neutral, base, forest, or dark. Empty is default. See Picking a theme.
KEYSTONE_DIAGRAMS_FONT The typeface diagrams are lettered in, as a CSS font stack. Only what the renderer carries resolves — see Matching the book. Empty is Noto Sans, sans-serif.
KEYSTONE_DIAGRAMS_LOOK How shapes are drawn: classic or handDrawn. Empty is classic. See Matching the book.
KEYSTONE_DIAGRAMS_LAYOUT How nodes are placed: dagre or elk. Empty is dagre. See Matching the book.

When the renderer does not know a value

A theme, look or layout it does not know stops the build, naming the value, so a typo cannot restyle a book in silence. A font it lacks only warns — a font stack falls through, and the fallback is legible. The checking is the renderer's own, so a different one answers for its settings its own way.