Writing these docs
How the docs are organised, how to add a page, and how the API reference stays in sync with the game.
These pages are plain Markdown files in the underlives-landing repository, under src/docs/. They are built into the site; nothing else needs to change to add one.
Adding a page
- Pick the section folder under
src/docs/content/en/:01-start,02-scripting,03-gameplay,04-world,05-characters,06-reference,07-contributing. - Create
NN-your-page.md. The number only orders the page in the sidebar; the URL is/docs/<section>/<your-page>. - Start it with frontmatter:
markdown---
title: Your page
description: One sentence shown under the title and in search results.
---
Text…
That is all: the sidebar, search, previous/next links and the "On this page" column pick it up.
A new section is a new folder NN-name/ with a _section.md holding its title.
A page whose subject is explicit 18+ content (like Sex scenes) adds adult: true to its frontmatter, and so does each of its translations. Explicit content goes on such pages only; every other page stays safe for search results.
Writing style
- Write for modders, not engine developers: what a field does and how to use it, not how the C++ implements it.
- Every page answers "which file do I write, where, with what in it". Show a complete, working example before the reference table.
- Say plainly when something is read but not applied yet (use a
> [!NOTE]or> [!WARNING]box), and remove the box when the engine catches up. - Link other pages with absolute paths:
[Scenes](/docs/scripting/scenes),[Choices](/docs/scripting/dialogue#choices).
Callout boxes:
markdown> [!NOTE]
> Neutral information.
> [!TIP]
> A shortcut or good practice.
> [!WARNING]
> Something that does not work as you would expect.
> [!MODDER]
> Where the everything-is-a-mod rule shapes how this works.
Code blocks take a language for highlighting: lua, json, ini, text, bash.
The API reference
The Game, Actor, UI, AI and Building pages are built from two files in src/docs/api/:
| File | Written by | Holds |
|---|---|---|
lua-api.generated.json |
The extractor, never by hand | Every Lua-callable name, its parameters and source location, read from the game's C++ bindings |
lua-api.notes.json |
People | The modder-facing description of each function |
After adding or renaming a Lua function in the game, run, from the game repository:
bashpython Tools/ModDocs/extract_lua_api.py
It rewrites lua-api.generated.json in the landing repository and prints every function that has no note yet, and every note whose function no longer exists. A function without a note still appears on the page, flagged "Not documented yet", so the reference can never silently fall behind the game.
A note looks like this:
json"Actor:setVar": {
"group": "Memory",
"sig": "setVar(key, value)",
"desc": "Stores a number, text or true/false on this person, saved with them. <code>nil</code> deletes the key. Prefix keys with your mod id.",
"example": "Actor:setVar(\"ynl_met\", 1)"
}
group sorts the function under a heading (the heading order is _groups at the top of the file), sig is the signature shown, desc may contain <code> tags, example is optional.
Translations
English is the reference. A translation is the same path under another locale folder (src/docs/content/fr/02-scripting/02-scenes.md) and replaces the English page for readers of that language; pages without a translation fall back to English with a notice. Translate section titles with a _section.md in the locale's section folder.
When the engine changes
When a mod-facing feature lands in the game, the same change should update the docs:
- a new file type or field → the page for that content, and File formats;
- a new Lua function → run the extractor and write its note;
- a gap closed → remove the matching warning box.