Books
A Book is a folder of Markdown presented as one document: a sidebar table of contents, previous/next links, and a reading order. This guide is one.
Book(title: "Guide", folder: "guide", pageNavigation: .top, in: root)
The outline is a real document
The folder’s own index.md is its table of contents, and it is read as a nested list:
- [Manuscript](manuscript/index.md)
- [Prelude](manuscript/prelude.md)
- [Chapter One](manuscript/one.md)
- [Notes](notes.md)
The nesting in that list is the nesting in the sidebar. That sounds obvious and wasn’t: the earlier version of this ran a regular expression over the file, captured every link in encounter order, and threw the indentation away — then rebuilt a tree by splitting page URLs on /, inferring hierarchy from filenames after parsing a document that had stated it outright. Now the list is parsed as a list.
Two consequences fall out for free. A plain-text item with no link becomes a group heading rather than a broken link. And a page listed under a ## Trash heading is not part of the book — the parser stops at that heading.
Pages that the outline never mentions still get built; they just sort after the ones that do.
OKF bundles
A book can also be an OKF bundle, which is the same folder of Markdown plus concepts — front matter that says what each page is and where it stands:
Book(title: "Body and Soul", folder: "book.okf", source: .okf, in: root)
The outline and the concepts carry different things and neither subsumes the other:
| Source | Owns |
|---|---|
| the outline | order, nesting, and the titles a reader sees |
| a concept | whether the page belongs in the book at all |
A concept marked status: draft, or carrying a deleted: timestamp, drops out — of the sidebar and of the output. It is not written at all. A page removed from the table of contents but still live at its own URL is the failure this rule exists to prevent, wearing the costume of success.
If a withheld page has children, the entry survives as a plain group so its children don’t go down with it.
Titles
The outline’s title wins when it has one. It is written for a reader in context — “Prelude”, under “Manuscript” — where a concept’s own title is written to stand alone. An empty title stays empty and the page answers for itself, rather than falling back to the concept’s id and labelling the sidebar research/untitled.md.
Read-only, deliberately
Both sources are read-only. The OKF spec (§4) lets any conformant tool regenerate index.md, and _catalog.md is where structure is supposed to live — but these bundles come from an upstream producer that will eventually emit that document itself. Writing one here would fork ownership of the outline with the tool that owns it.
_catalog.md is already preferred when a bundle has one, so the day the producer starts emitting it, the better source is read and no migration has to happen.
Withholding a page
A read-only source can’t mark its own pages. This site’s manuscript bundle arrived from Scrivener with a title page filled in from the author’s address book — a real phone number and email, on a page nobody wrote to be read — and no way to say so from inside a bundle this tool must not write to.
So the site says it, in the manifest:
[content]
withhold = [
"book.okf/front-matter/manuscript-format/title-page.md",
"book.okf/template-sheets/character-sketch.md",
]
Paths are relative to content/ and name files, because the file is what exists before the build has decided where it would have gone.
This goes through the same filter drafts do, and it reaches all three places a page can leak from:
- the page is not written,
- it is not added to the search index — Saga runs
itemProcessorbeforefilter, so a page that will never be written is still read and processed, and indexing it would publish its title and an excerpt in a file anyone can fetch, - and links to it are rendered as plain text, so the prose that referenced it keeps its sentence instead of gaining a 404.
It lives in the manifest rather than in siteTree on purpose. Every other structural fact is a statement about the software; this is a statement about one site’s content, made by whoever publishes it, and it changes without any code changing. Needing a recompile to unpublish a page is how the page stays up.
site check warns about an entry matching no file. The failure mode of a typo here is silent: nothing is withheld, and the page you meant to keep off the web is simply published.
The other half of the question is unlisted: publish the book, but don’t advertise it. Withholding is don’t publish this; unlisting is publish it, and put up no signposts.
Seeing drafts
site serve --drafts
Publishes concepts marked status: draft. It does not reach trashed ones: asking to preview unfinished work is not asking to undelete anything, and no flag should quietly reverse a decision the author made.