rescriptum
The documentation site
Development
The documentation site
The documentation site
This site is docs/ in the repository, rendered by
notabene and published to GitHub Pages. The Rust
binary knows nothing about any of it; the docs toolchain is a package.json and one
config file, and removing it would leave docs/ as perfectly readable Markdown.
Why a site and not a longer README
The README had grown to 28 KB and was three documents wearing one coat: a pitch, a user manual, and an architecture note. A reader looking for the DSM firewall step had to scroll past the merge semantics. So:
docs/guide/— using rescriptum: install, write answers, run it in production.docs/development/— building rescriptum: the constraints, the internals, the release.README.md— what it is, a 30-second demonstration, and links into the site.
The two spaces have different audiences and no reason to interleave.
Two languages
The site is bilingual: English is the source, French is a translation of it. The
suffix i18n strategy means the English files keep their paths and URLs and the French
ones are *.fr.md siblings:
docs/guide/answers/grouping.md → /guide/answers/grouping
docs/guide/answers/grouping.fr.md → /fr/guide/answers/grouping
That layout was chosen over a folder per locale because it can be added to an existing doc without moving anything — the English URLs and their comment threads survive.
Rules that follow from it:
- Write English first, then translate. A change to an English page that is not mirrored leaves the French page stale rather than broken; the reader falls back with a banner.
- Links keep the base name. From a French page, write
./selection.md, not./selection.fr.md— notabene resolves the locale. But anchors must be the French heading’s slug:./templating.md#machine-exige-un-document-machine. - Comments are per language. A comment left on the French page is its own thread and maps to the French source file.
- The site chrome, search and
llms.txtare per locale too.
README.md and README.fr.md follow the same rule and link to each other.
Working on the docs
npm install # once
npm run docs # → http://localhost:3009
That opens the site with the review loop enabled: select any text on the rendered page and leave a comment, exactly where the problem is. The anchored comment is the instruction — no quoting a passage into a chat box and hoping the agent re-finds it.
Then tell your agent “address the doc comments”. It reads docs/.notabene/, edits the
source, marks each comment handled, and appends a journal entry saying what changed and
why.
| Script | Does |
|---|---|
npm run docs | the review server, live-reloading |
npm run docs:build | the public static site into ./_site |
npm run docs:preview | serve what was built |
npm run docs:lint | validate every internal link against the routes the last build emitted |
npm run docs:status / docs:stop | manage a detached dev server |
Using Claude Code? /plugin marketplace add z29k/notabene then
/plugin install notabene@z29k, and say “set up notabene”. The plugin runs its own
pinned renderer, so it does not conflict with the one in package.json.
Review mode is approve
notabene.config.mjs sets review: "approve", so the agent proposes rather than
resolves: each edit is validated against its real git diff at /review before the
comment is closed. Documentation that describes root passwords and boot-time configuration
is worth reading before it ships. Change it to "auto" if that ceremony is not earning
its keep.
Writing a page
Every page is CommonMark with optional YAML frontmatter:
---
title: Groups and merging
description: One sentence — it becomes the meta description and the search snippet.
sidebar:
label: Grouping # sidebar text, if the title is too long for it
order: 3 # position among siblings, ascending
---
Everything has a default: a page with no frontmatter renders fine, ordered
alphabetically. A folder is named and positioned by its index.md.
Conventions in this repository:
- Relative links between pages, with the
.mdextension —./selection.md,../reference/configuration.md. They become routes on the site and stay clickable on GitHub. - Absolute GitHub URLs for repository files —
answers/,CLAUDE.md, a workflow. They are outsidedocs/and have no route. - English, like everything else written to disk here.
- Mermaid diagrams are rendered natively, in a
```mermaidfence — see architecture and the request lifecycle. - Every page needs its
*.fr.mdsibling, with the frontmatter translated too — thetitle,descriptionandsidebar.labelare all reader-facing.
Configuration
notabene.config.mjs at the repository root. The parts that matter:
roots: [
{ key: "guide", label: "Guide", path: "docs/guide" },
{ key: "development", label: { en: "Development", fr: "Développement" }, path: "docs/development" },
],
store: "docs/.notabene",
home: { en: "docs/home.md", fr: "docs/home.fr.md" },
i18n: { locales: ["en", "fr"], defaultLocale: "en", strategy: "suffix" },
branding: {
logo: "assets/rescriptum-logo.jpg",
favicon: "assets/rescriptum-logo.jpg",
socialImage: "assets/rescriptum-logo.jpg",
},
editPattern: "https://github.com/z29k/rescriptum/edit/develop/{path}",
review: "approve",
publish: { site: "https://z29k.github.io", base: "/rescriptum" },
Every reader-facing string in the config takes a per-locale map — a space’s label and
description, the home page, every nav link label, the sidebar block title, the footer.
Unset for a locale, it falls back to the default one.
The logo is assets/rescriptum-logo.jpg: a sealed rescript on a floppy disk — a written
answer, delivered by a machine. It serves as the topbar logo, the favicon and the social
card, and it is the image the README uses too.
editPattern points at develop, not main: docs are merged there like everything
else, and main only receives release commits.
docs/.notabene/ is the comment and journal store — plain JSON, committed, diffable in a
PR. Commit it.
The CI gate
.github/workflows/ci.yml has a docs job: npm ci, build the public site, then
notabene lint, which checks every internal link against the routes the build actually
emitted and suggests near-misses. A dead link in published documentation is cheap to
prevent and embarrassing to ship.
It runs on the same pushes as the Rust gates.
Publishing
.github/workflows/docs.yml builds --public and deploys to GitHub Pages on every push
to main that touches docs/, the config, or the workflow — plus
workflow_dispatch, for publishing a docs fix without waiting for a release.
Because main only receives release commits, documentation normally ships with a
release. Run the workflow by hand when it should not wait.
The artifact is the read-only public build: no review UI, no store data, plus llms.txt,
a Markdown twin per page, a sitemap and OpenGraph metadata. pagefind is a dev dependency,
so npm ci gives the site full-text search with no further configuration.
One-time repository setup: Settings → Pages → Source = GitHub Actions.
The dependency situation
npm audit reports advisories in Astro, esbuild and sharp, transitively under notabene,
with no fixes currently available upstream. They are development-only: nothing from
node_modules is executed by the published site or reaches the Rust binary, and the CI
job builds static HTML from Markdown this repository owns.
Worth re-checking when notabene updates, not worth blocking on.