docs(journey): phase 7 — the installation path and administration
All checks were successful
PR checks / checks (pull_request) Successful in 9m25s

Twenty documentation pages: Getting started (7) and Administration (13), the
journey no existing document owns end to end because the repositories are
organised by component and an operator is not.

Four decisions of record, taken before anything was written (D34–D37, PLAN.md
§10 "How phase 7 built the documentation journey"):

- D34 one PR for all twenty pages.
- D35 the install page is SELF-CONTAINED: it prints a complete Compose file and
  a complete .env that an operator copies without visiting another repository.
  That is a copy of somebody else's file, so it is checked rather than trusted —
  scripts/checkQuickstart.mjs re-reads website main:docker-compose.yml and
  main:.env.example over the Gitea API and fails on any disagreement, in both
  directions: a value that drifts fails, and a service or variable that appears
  upstream fails until it is either included or recorded as deliberately omitted
  with a reason. Its first run found two stale entries.
- D36 every Administration screen was walked on a real deployment before it was
  described — the rig being the quickstart itself, against the published image,
  so one run proved the install page and produced the detail the admin pages
  needed.
- D37 a thirteenth Administration page, Content, so that every admin nav row has
  a home without organising the docs by the app's menu.

What the live deployment disproved, all three now documented:

- The documented Compose deploy does not boot. SECRET_ENC_KEY is required in
  production (utils/secretBox.js throws at require time) and is missing from
  website's ROOT .env.example — the file Compose reads. It is present in
  server/.env.example, which is why dev never hits it. The quickstart carries it,
  declared as an upstream omission so the check fails the day it is fixed.
- The installer points operators at a screen that no longer exists: it prints
  <site>/admin/shard, and INSTALL.md §5 repeats it, but since the module cutover
  the screen is /admin/uo/link. Both the binary and the guide are stale.
- The admin Restart button opens a window.confirm whose text is the honest
  warning that a deployment with no supervisor does not come back — which is why
  `restart: unless-stopped` is called out as load-bearing rather than left as
  boilerplate.

And the defect only a look found, three phases running: the .env block's prose
promised that every highlighted line must be changed, while `mark` given the
variable names highlighted the names alone and left the values unmarked. Every
check passed on a page that was wrong about its own highlighting.

verify green: 890 internal links, 52 branch links, 19 facts, 59 quickstart
checks, 0 astro-check errors.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-24 08:35:03 -05:00
parent 971fa9c032
commit f499f2b72b
27 changed files with 2260 additions and 19 deletions

87
PLAN.md
View File

@@ -236,7 +236,7 @@ Taken by the org lead (Colby Whitlock) on 2026-08-19. Recorded so they are not r
**Decisions after D13 are recorded where they were taken**, in the section describing the phase that
raised them, rather than appended here — a decision is only re-litigated when its reasoning is
somewhere other than the thing it decided. The count of record is **thirty-three**:
somewhere other than the thing it decided. The count of record is **thirty-seven**:
| # | Where | What it settled |
|---|---|---|
@@ -245,6 +245,7 @@ somewhere other than the thing it decided. The count of record is **thirty-three
| D20D25 | §10, "How phase 4 built the marketing pages" | `/features/` as the same list with detail, `/architecture/` as reasons not reference, the absences as data, the two absorbed scope items, `needsModule`, the demo deep links |
| D26D29 | §8, "How phase 5 built the app and the beta" | The screenshot slot reserved for phase 9, the demo as the tester target, `/beta` handling its own POST, equal billing for the APK and the beta |
| D30D33 | §9, "How phase 6 built the legal pages" | One logging hop and no edge provider, eighteen or older, no governing-law clause, the Data Safety notes as a generated document |
| D34D37 | §10, "How phase 7 built the documentation journey" | One PR for all twenty pages, a self-contained install quickstart with a drift check, every admin screen walked before it was described, a thirteenth Administration page for content |
---
@@ -821,7 +822,7 @@ Getting started What is Runic Gateway? · Requirements · Install the site ·
Verify the whole stack
Administration Configuration · Branding and theming · Navigation and pages ·
Users and roles · Authentication · Teams · Moderation ·
Content · Users and roles · Authentication · Teams · Moderation ·
Notifications and email · Managing modules ·
The shard connection · Maintenance and upgrades · Troubleshooting
@@ -836,7 +837,7 @@ Reference Environment variables · Installer CLI · sidecar.toml ·
Bridge.cfg · HTTP API · Event catalog · Canonical documents
```
Roughly 37 pages. Every Reference page is a **navigable summary plus a link to the canonical
Roughly 38 pages — 37 planned, plus the Content page D37 added in phase 7. Every Reference page is a **navigable summary plus a link to the canonical
document** — never a re-specification, per §1.
### The installation path
@@ -851,13 +852,81 @@ website; the website is a separate Docker deployment.
3. First run — first admin, maintenance → live
4. Install a game module — admin panel, `MODULES` env, or by hand
5. Connect a game server — the installer binary on the shard host (ServUO-specific today)
6. Paste the four values into Admin → Shard**protocol 4**, per §2
6. Paste the four values into **Shard (uo-link)**, `/admin/uo/link`**protocol 4**, per §2.
(Not `/admin/shard`: the screen belongs to the module now, and the installer still prints the
old path — see "How phase 7 built the documentation journey" below)
7. Verify — `[bridge status` in game, `/health` reporting `plugin_connected: true`, then `doctor`
8. Configure authentication and integrations
Each step states what the operator should expect to see, and links the failure modes to
Troubleshooting.
### How phase 7 built the documentation journey
Four decisions taken before a page was written (org lead, 2026-08-24), and three things the live
site disproved while it was being written.
**D34 — one PR for all twenty pages.** Twenty, not nineteen: see D37. The alternative on the table
was splitting Getting started from Administration so the installation path could land first; the
org lead kept the phase whole, as every phase before it has been.
**D35 — the install page is self-contained.** `/docs/getting-started/install-the-site/` prints a
complete Compose file and a complete `.env` that an operator copies without going to another
repository first. §1 argues at length against exactly this — it is a second copy of somebody else's
file, free to rot — so the copy is not trusted, it is checked. `src/data/quickstart.mjs` holds both
files and the page renders them; `scripts/checkQuickstart.mjs` re-reads `website`'s own
`docker-compose.yml` and `.env.example` from `main` over the Gitea API and fails the build on any
disagreement, in **both** directions:
- every value the quickstart states must match upstream's;
- every service and variable upstream has must be **either included or listed as deliberately
omitted, with a reason**, so a new variable in `.env.example` turns this repo red until someone
decides whether a first install needs it;
- and an entry in either omission list that upstream no longer has fails too, so the lists cannot
rot into permanent exemptions.
Same mechanism and same intent as `checkFacts.mjs`. It caught two stale entries on its first run —
`TOTP_ISSUER` and `MODULES`, which are commented *suggestions* upstream rather than keys — which is
the check earning its place before the page had shipped.
**D36 — every Administration screen was walked before it was described.** Not read from source:
opened, in a browser, on a real deployment. The rig was the quickstart itself — the exact two files
from D35, against the published image — so one run proved the install page and produced the
screenshots' worth of detail the admin pages needed. Three of the four defects below came from that
walk, and no check could have found any of them.
**D37 — a thirteenth Administration page.** §10's planned twelve named no home for Posts, Pages,
Wiki, Activity, Invites, the Hero editor or Web Bot Activity, all of which are real admin nav rows.
Rather than mirror the panel one page per row — which would organise the docs by the app's menu,
against this section's own principle — content authoring became one page, **Content**, and the
other four folded into the page that already owned their subject: Invites into Users and roles, the
Hero editor into Branding and theming, Web Bot Activity into Authentication.
**What the live deployment disproved.**
- **The documented Compose deploy does not boot.** `SECRET_ENC_KEY` is required in production —
`utils/secretBox.js` throws at require time, so the container crash-loops before it listens — and
it is **missing from website's root `.env.example`**, the file Compose actually reads. It is
present in `server/.env.example`, which is the file local development copies, which is why this
has never bitten anyone in dev. The quickstart carries it, declared as an upstream omission so the
check fails the day it is fixed.
- **The installer points operators at a screen that no longer exists.** It prints
`<site>/admin/shard`, and INSTALL.md §5 repeats it. Since the module-system cutover a module owns
one path segment, and the screen is **`/admin/uo/link`**, labelled *Shard (uo-link)*. Both the
binary (`installer` `main:src/sidecar.rs`) and the guide are stale; the journey documents the real
path and says the printed one does not resolve.
- **The admin "Restart the server" button opens a `window.confirm`.** Its text is the honest
warning that a deployment with no supervisor does not come back — which is exactly why
`restart: unless-stopped` is called out as load-bearing on the install page rather than left as
boilerplate.
**And the fourth defect, the one only a look found — three phases running.** The `.env` block's
prose says *every highlighted line must be changed*, and `mark` given the variable **names**
highlighted the names alone, leaving the values a reader has to replace unmarked. The build passed,
every check passed, and the page was quietly wrong about its own highlighting. Marking the whole
`KEY=value` string fixed it. See phase 4 (cascade), phase 5 (literal backticks)
and phase 6 (the card void) for the same lesson.
---
## 11. Visual direction
@@ -952,6 +1021,12 @@ a mechanism rather than diligence:
links (D25) — lifting the pattern out of `applyBrand.mjs` and running it against the stock markup,
so a template and a script that share no code cannot drift apart. Both are invisible in a stock
build, which is exactly why they need a check rather than a look.
- **`scripts/checkQuickstart.mjs`** — added in phase 7 for D35. The install page prints a Compose
file and an `.env` verbatim, which is the one place this site knowingly copies another repo's
file; this re-reads `website` `main:docker-compose.yml` and `main:.env.example` and fails on any
disagreement. Two-directional, like `PLANNED_ROUTES`: a value that drifts fails, **and** a service
or variable that appears upstream fails until it is either included or recorded as deliberately
omitted with a reason. Its own first run found two stale entries.
- **`scripts/checkTokens.mjs`** — no colour literal outside the token file (§7).
- `astro check` plus a production build, in CI on every PR.
@@ -968,11 +1043,11 @@ a mechanism rather than diligence:
| **4** | Marketing: `/features/`, `/architecture/`, `/modules/`, `/integrations/`, **and `/community/`** — plus `checkLinks.mjs`, the capability `detail` lines, `notBuilt.mjs` and the demo deep links. See D20D25 |
| **5** | The app and the beta: `/app/`, `/beta/`, the signup handler, the SQLite store, rate limiting, the export CLI (§8). **Also the repository's first `node --test` suite**, and phase 9 inherits an emulator pass (D26) |
| **6** | Legal: `/privacy/`, `/terms/`, footer links, and the Play Data Safety notes (§9) |
| **7** | Docs — the journey: Getting started (7) + Administration (12). **The installation path is the priority of the whole project** |
| **7** | Docs — the journey: Getting started (7) + Administration (**13**, per D37) — twenty pages in one PR (D34), with the install page self-contained and drift-checked (D35) and every admin screen walked before it was described (D36). **The installation path is the priority of the whole project** |
| **8** | Docs — builder and reference: Modules (8) + Architecture (5) + Reference (7) |
| **9** | Screenshots (D4): stand up the local review stack, seed presentable content, capture the admin panel, Teams, forums, marketplace, spawn atlas and shard console; build the screenshot components. **Plus an emulator pass against the same seeded stack** to fill `/app/`'s reserved slot (D26) |
| **10** | Polish: responsive, accessibility, SEO/OpenGraph/sitemap/robots, full-text search, CSP headers |
| **11** | Validation: `astro check`, production build, **all five check scripts** (tokens, brand, links, facts, types), mobile layout verified in a real browser, a signup walked end to end |
| **11** | Validation: `astro check`, production build, **all six check scripts** (tokens, brand, links, facts, quickstart, data safety), mobile layout verified in a real browser, a signup walked end to end |
| **12** | Delivery: Dockerfile, `docker-compose.yml` with both bind mounts documented, Gitea Actions workflow publishing to the registry, README, CONTRIBUTING with the AI-disclosure requirement, and an operator note covering DNS, TLS and the reverse proxy (D6) |
Phases 5 and 6 are deliberately adjacent and early: the beta cannot start without `/privacy`, and