Skip to content

Write documentation

How a page on this site is written. Follow it for every change to any tab.

Where the site lives

The site is its own repository, nerthus.docs: docs/ holds the Markdown, zensical.toml the nav and the theme, data/nerthus.yml the Jinja variables, ci/ the checks. It documents the whole estate. Code repositories hold no hand-written explanation: every design note, how-to and runbook about their code is a page here, and the code cites it by URL. A page's path is therefore an address other repositories depend on; move one only with the code change that repoints its citations.

Two truths, kept apart

The site describes two systems and never mixes them on one page.

  • Nerthus.Core runs today. Every page about it is in the tab Nerthus.Core (until cutover), which is deleted at cutover. Each such page opens, directly under its title, with this line and nothing else in its place:

    > **Nerthus.Core (until cutover).** This page describes the frozen system that runs today and is deleted at cutover. Replaced by: …
    

    The line ends with a link to the page that replaces it, with not yet written., or with none, retired with Core. A Core page is not rewritten: only that line and a dead link change. - The estate is what replaces it. Every other tab describes Platform, Config, the corpora and the regime. A page here says what exists today and what is ruled and not built, and never describes the second as if it ran.

A sentence that describes Core as if it were the estate, or the estate as if it ran today, is the defect to remove. When in doubt, the page goes under the Core tab with the line.

The tabs and their readers

Tab The reader Holds
Start here anyone, before they know which tab is theirs the front page, the ecosystem map, the glossary
Contributors changes Platform, Config or this site the regime, the programmes' history, each repository's pages
Hosting runs an instance or changes the estate's declared resources a Platform site, Config's plans, the runbooks
Nerthus.Core (until cutover) uses or keeps today's tools every Core-era page, in its old sections

Pick the tab by who has to do the thing on the page, not by its subject. Within a section, order is reading order: a page comes after the pages it assumes.

Pages for narrators and players are written in Polish, for someone who writes Markdown and runs no command: an example they could paste first, the explanation after, one idea per sentence, and everything needed to finish the task on the one page. Pages for contributors and hosts are written in English and give exact shapes: commands, file formats, settings, refusals.

Words

Everything the estate names is English; Polish is the language it shows to narrators and players. The glossary is the one table of both, and it is generated:

python3 ci/generate-glossary.py ../../../../GLOSSARY.md

GLOSSARY.md lives in the workspace beside the checkouts. To change a word, change a row there and regenerate the page in the same merge request; never edit docs/glossary.md by hand.

  • Write the English canonical: session, character, player, skill points, Council, vault, site, host, instance. Give the Polish label beside it where a reader will meet the Polish on a screen or in the lore.
  • Quote the lore's own grammar exactly as a narrator types it: its paths (Postaci/, Lokacje/), its tag keys (@należy_do, @lokacja) and the repozytorium-* names are the world's words, not the estate's.
  • A word in the glossary's retired table is not written outside the Core tab.

No history in a page

A page states what is true now. It carries no dates of past events, no task or project ids, no «used to», no story of how a number was measured, and no argument for a decision. A rule is stated as a rule; its ruling number may follow as a citation. How something came to be is the workspace ledger's and git's to record.

Dates and ids inside an example, such as a sample commit message or a pinned value, are part of the example and stay.

One concept, one page

Every concept has one page that owns it. Another page states it in at most one sentence and links there. A page that restates another in full is the defect, because the two drift.

A page generated from a source opens with <!-- generated by <command> --> and is regenerated, never edited. The glossary is one; reference pages for routes, commands and errors will be generated from each repository's contracts.

  • Link between pages by relative path to the .md file: [The database](../explanation/platform/database.md).
  • An address data/nerthus.yml holds is written as its variable ({{ lore.url }}), never pasted: an undefined variable fails the build, a pasted address rots unseen.
  • An example that needs literal double braces wraps them in a Jinja raw block.

The checks

Every merge request builds the site with zensical build --strict and runs the jobs Nerthus.Docs lists. Two of them bind every page:

  • nav-coverage: every page is in the nav, so no page is published where no reader can reach it.
  • addresses: an address the variables file holds is not hand-typed, in prose or in an example.

Build and run the checks locally before you push:

pip install -r requirements.txt
zensical build --strict
for c in ci/assert-*.py; do python3 "$c" || break; done

ci/assert-merge-request-lane.py takes the CI file as its argument (.gitlab-ci.yml).