Writing documentation¶
The documentation is Markdown under docs/, built into a site by
Zensical and published at
kosmos.law/docs.
Build it locally¶
scripts/build-docs.sh # build into site/
scripts/build-docs.sh --strict # what CI runs; fails on a broken link
uvx zensical@0.0.67 serve # live preview at http://localhost:8000
Zensical runs as a standalone tool through uvx, not as a project
dependency: it needs a newer pymdown-extensions than the application
pins. The version is set in scripts/build-docs.sh; use the same one for
serve.
The build writes to site/, which is ignored by git. If the Django dev
server is already on port 8000, pass --dev-addr localhost:8001 to
serve.
How the site is published¶
The site is static files, and the server that hosts kosmos.law receives
only those: it has no checkout of this repository for the docs and no build
tools. The build happens wherever this repository already is, and
scripts/publish-docs.sh copies the result across:
It builds with --strict, then mirrors site/ to the target with rsync,
so a page removed from the docs is removed there too. Because mirroring
deletes, the script first checks that the target is new, empty or already a
docs build, and refuses anything else. --dry-run shows what would change
without copying. The target can also be given as DOCS_PUBLISH_TARGET.
On the receiving server, nginx serves that directory under /docs/ from
the same server block as the landing page:
scripts/add-docs-location.sh adds that block to an nginx site file: it
backs the file up, inserts the block, tests the configuration and reloads
nginx, and restores the backup if the test fails. It is a one-time step per
server:
site_url in zensical.toml is https://kosmos.law/docs/; the pages link
to each other relatively, so the same build also works under any other
address.
Nothing is published from GitHub. The workflow in
.github/workflows/docs.yaml only checks that a pull request's docs build
without a broken link.
How it looks¶
The site wears the landing page's design: the same typeface, the same mark
and, at night, the same palette. The landing page is its own repository
(Kosmos-Law/web) and has no day side,
so the light scheme borrows the application's nord-light theme. The
reader's system setting picks the scheme first shown, and the toggle in the
header switches it.
All of it lives in docs/stylesheets/kosmos.css: a block of design tokens
for each scheme, copied from those two sources, and the rules that restyle
the theme on top of them. zensical.toml sets the typeface and the two
schemes. When the landing page's or the application's palette changes,
change the tokens at the top of that stylesheet to match.
Where a page goes¶
The site has one section per reader. Decide who the page is for before writing it.
| Section | Reader | They want to |
|---|---|---|
admin/ |
The person running a Kosmos server | install, configure, connect services, upgrade, recover |
guide/ |
Attorneys and staff | get a task done in the application |
dev/ |
Contributors and coding agents | change the code safely |
reference/ |
Anyone | look up a variable, command, schedule or permission |
decisions/ |
Contributors | understand why something is the way it is |
A page that serves two readers is usually two pages. Setup steps for an
integration belong in admin/; how its code works belongs in dev/, and
each links to the other.
Add every new page to the nav list in zensical.toml. A page left out of
the navigation is easy to lose.
One kind of page at a time¶
Each page does one of three jobs. Mixing them is what makes documentation hard to use.
- How-to: numbered steps toward a goal the reader already has. Start with what they need before they begin; end with how to check it worked.
- Explanation: how a part of the system works and why. Prose, with the file paths a reader needs to find the code.
- Reference: tables and lists to look things up in. No narrative.
House rules¶
- Write for someone who was not there. Define a term the first time it appears. Do not assume the reader knows the firm, the history, or a branch name.
- Keep examples firm-neutral. Use
example.comhosts and invented people and matters. Never put a real client, matter, address, token or route id in a page. The repository is public. - Say only what the code does. Check each command, variable name and path against the source before committing. If the behaviour is awkward, document the behaviour and open an issue; do not describe the system you wish existed.
- Do not hand-maintain what can be generated. Lists of environment
variables, management commands and schedules belong in
reference/and come from the code. - Link, do not repeat. A fact lives on one page. Other pages link to it.
- Punctuation. No em dashes: use two sentences, a colon, or parentheses.
- Screenshots come only from an instance loaded with demo data, never from a real firm's database.
Pages moved in from before these rules existed do not all follow them yet. Fix what you touch.
User guide pages¶
Pages under docs/guide/ are for attorneys and staff, not for people who
run servers. They follow the house rules above and these as well.
Matters is the model to copy.
- Write from the screen. Read the templates, forms and views, and name every button, field, column and menu exactly as the screen does, in bold: Matters, Add Matter, Submit. Use "→" between the steps of a menu path: Settings → Appearance. Never invent a label. An icon with no text is described by what it is ("the plus button").
- Task first. Headings are things the reader wants to do or understand: "Open a new matter", "Close a matter". Steps are numbered, and each starts with the action. After the steps, one sentence says what the reader should now see.
- Second person, present tense, short sentences, plain words. No "simply", "just" or "easy".
- Nothing the reader cannot see. No code, file names, addresses with ids in them, environment variables or database terms.
- Good to know. When the application does something a careful user would not expect, say so once, plainly, in a short "Good to know" list at the end of that section: three items at most, and only real ones. If it is a bug, fix the bug and leave the item out.
- Permissions in one sentence. "You need the Financial permission for this. Ask your administrator."
- Invented examples only: the matter "Rivera v. Northside Logistics", the client "Elena Rivera", the firm "Example Law".
- Shape. An H1 title, then two or three sentences on who the page is
for and what it covers. Plain Markdown: headings, numbered lists, short
tables, at most one
!!! noteper page. Prose wrapped at about 76 columns. No screenshots yet.
Decision records¶
Write a record in decisions/ when a design choice would otherwise have to
be rediscovered: a feature retired, an approach tried and rejected, a
constraint that is not visible in the code. Give it a date, say what was
decided and what the alternatives were, and add it to
decisions/index.md. Records are not rewritten later. If a decision is
reversed, write a new record and link the two.
Links to files in the repository¶
Links between pages are relative (../admin/configuration.md) and are
checked at build time. A link to a file outside docs/ cannot be relative,
because that file is not part of the site. Use the full GitHub URL on the
dev branch: