Jennifer's Grimoire
Build a documentation website - and a printable PDF - from a directory of Markdown files. What mdBook, MkDocs, and similar tools do - written in Jennifer.
A grimoire is a book of magical knowledge - astrological rules, lists of angels and demons, spells, and instructions for making talismans - copied and recopied across Europe from the late Middle Ages into the eighteenth century. The best known are the Clavicula Salomonis, the Grimorium Verum, and the Grand Grimoire.
The word comes from Old French gramaire, which is also the root of grammar and of glamour: a book of rules that, to anyone who could not read it, looked like sorcery. This one only makes websites.
Point it at a directory of Markdown. If that directory holds a SUMMARY.md it is used as the book outline, in the mdBook shape; if it does not, the outline is derived from the directory tree, the way MkDocs does. The output is a self-contained static site - themed, searchable, with a colour-mode selector - plus, on request, the whole book as one paginated PDF.
bin/grimoire init my-book # scaffold a book
bin/grimoire build # build the site
bin/grimoire build --pdf # site plus the printable book
bin/grimoire pdf # the printable book on its own
bin/grimoire serve # build, then preview on :8080
bin/grimoire themes # list the built-in themes
bin/grimoire plugins # list the programs this book runsbin/grimoire is a Jennifer script with a shebang; the program itself is src/grimoire.j. It runs from any working directory and through any symlink, so the path goes away once the launcher is on your PATH - see Installation, which also covers running the whole thing from a container instead.
A built site is a directory of files that works served from a web root, served from a subdirectory, or opened straight off the disk over file:// - search included. Nothing is fetched from anywhere unless you opt in, and the only setting that reaches off the machine at all is [highlightjs], which is off by default.
Tip
Read this manual as a single PDF. Every page in one paginated file, with a clickable outline in your reader's bookmark panel and page/total in the footer - handy for reading offline. It is built from these same pages on every build, so it never drifts from the site.
What it does
- Two outline styles.
SUMMARY.mdwith part headings, nested entries, prefix and suffix chapters, drafts, and separators; or noSUMMARY.mdat all, in which case the directory tree becomes the outline. - Anchors that match mdBook and GitHub exactly, so hand-written cross-references survive a migration.
### REPL (cmd/jennifer/repl.go)anchors at#repl-cmdjenniferreplgo, not#repl-cmd-jennifer-repl-go. - Links rewritten:
[x](guide/syntax.md#anchor)becomesguide/syntax.html#anchor; a directoryREADME.mdfolds onto itsindex.html. - Client-side search over per-section records, so a hit lands on the paragraph rather than the top of a long chapter. Opens with
/orCtrl-K, arrow keys to move,Enterto open. No search library: the index and the scorer are both Grimoire's own, and the index loads as a script rather than afetchso it works overfile://. - A preview that reloads itself.
serve --watchrebuilds on save and reloads the open page, with the script that does it spliced into the response rather than written to disk - the published files never carry it. - Admonitions in GitHub's syntax:
> [!WARNING]and four others, with an optional title, labelled in the book's language and coloured the same way in all ten themes. A renderer that does not know the syntax shows a plain quotation. - Plugins as programs, not modules. A preprocessor reads the book as JSON on stdin and writes the rewritten chapters back, so what it changes reaches the site, the search index and the PDF; a renderer runs on the finished book and makes something else of it.
grimoire-includeandgrimoire-sitemapship with them. - Eleven interface languages. The twenty-odd words Grimoire adds around your text - "Search", "On this page", "Previous" - follow the book's
language, with English wherever no translation exists yet. - Ten themes, each with a light and a dark palette.
- A mandatory dark mode. Every theme ships both palettes; the selector in the top bar offers light, dark, and follow-the-system, and the choice is stamped on the document before the first paint, so there is no white flash on navigation.
- Syntax highlighting in two layers.
[highlight]alone highlights Jennifer while the site is built - no CDN, no JavaScript, nothing to load, and it works with scripting off.[highlightjs]additionally pulls highlight.js from a configurable CDN for the other languages. Both are off by default, and the second does nothing without the first. - A logo beside the title: an SVG is inlined, so it inherits the colour mode and costs no extra request.
- A printable book: every chapter in one PDF, with a cover page, chapters starting on fresh pages, a nested bookmark outline, and document metadata. It wears the book's theme too - heading bars, table headers, code panels, and the tint and rule on a blockquote all come from the theme's light palette. A PNG or JPEG on a line of its own is drawn into the page, scaled to the measure; anything else keeps its alt text.
- Chapters render in parallel, one task per CPU, with the work split longest-chapter-first. With
--pdf, the PDF is laid out alongside the site rather than after it. - Deterministic output. The same input produces byte-identical files - including the search index, whose order does not depend on how the work was split across jobs.
Where to go next
| Installation | from a checkout, or from a container with Docker or Podman |
| Commands | every subcommand and flag |
| Configuration | grimoire.toml, key by key |
| Markdown | what Grimoire reads on top of CommonMark |
| Plugins | running a program over the book, and writing one |
| Themes | the ten themes, with screenshots, and how to write one |
| Internals | the source layout, and what Grimoire does to the Markdown |
| Performance | where the time goes, and why it scales the way it does |
Requirements
Jennifer 0.25.0 or newer - or nothing at all beyond a container runtime. Installation has both paths, including which of the two interpreter binaries runs which commands.
License
LGPL-3.0-only. Copyright (C) 2026 mplx <jennifer@mplx.dev>.