TITLE=Wiki Site ROUTE=/services/wiki-site LOCALE=en MODIFIED=1792615260 URL=https://wiki.teletypegames.org/services/wiki-site L=1 https://getgrav.org/ L=2 #71 L=3 https://git.teletypegames.org/services/wiki-pages L=4 https://git.teletypegames.org/engines/rubbs L=5 #66 q│ This wiki is a 1Grav CMS site whose content lives in a git repository, plus q│ two companion services: a bfetcherq that keeps the live checkout and git in q│ sync in both directions, and a telnet bBBSq front-end. Changes surface on a q│ JSON API, which the 2Updater bot polls to announce them on Discord. 1Overview 1════════ One repository holds everything — 3cservices/wiki-pages0: content (cpages/0), Grav config, theme, companion services. Docker Compose runs three services from it: t┌──────────────┬─────────────────────────────────────────────────────────────┐ t│h Service t│h What it does t│ t├──────────────┼─────────────────────────────────────────────────────────────┤ t│0 cgrav0 t│0 Grav CMS (PHP 8.1 + Apache). cpages/0, cconfig/0, cthemes/0 are t│ t│0 t│0 bind-mounted, so the site serves the working tree. The t│ t│0 t│0 active theme is cttgwiki20 (the teletypegames.org look, with t│ t│0 t│0 dark/light and a retro mode); cpages.theme: ttgwiki0 in t│ t│0 t│0 cconfig/system.yaml0 brings the old one back. t│ t├──────────────┼─────────────────────────────────────────────────────────────┤ t│0 cwiki-fetcher0 t│0 Go sync service (cfetcher/0). Takes pushes in on the Gitea t│ t│0 t│0 webhook (cPOST /hook0) or every 10 minutes, commits and t│ t│0 t│0 pushes the server's content edits, reports on c/health0 and t│ t│0 t│0 c/metrics0. See iSync0 below. t│ t├──────────────┼─────────────────────────────────────────────────────────────┤ t│0 cwiki-bbs0 t│0 Telnet front-end (cbbs/0, on 4rubbs) browsing the wiki through t│ t│0 t│0 the JSON API. On start it updates rubbs to the newest t│ t│0 t│0 commit, waiting up to a minute for Gitea first (after a t│ t│0 t│0 server restart Gitea answers 502 for a while); if it is t│ t│0 t│0 still unreachable, the BBS starts on the installed version. t│ t│0 t│0 See 5BBS Server. t│ t└──────────────┴─────────────────────────────────────────────────────────────┘ 1Content 1═══════ Grav routes by folder: a page is cpages/
//default..md0 with YAML frontmatter. The sections follow the Gitea orgs where there is one: cservices0, cplatforms0 (the build-org toolchains), cengines0, cstores0, cdos0, cinfrastructure0, plus cprojects0, cteam0, ctechnologies0 and cdevelopment0 (guides such as the RoR styleguide). Slugs are hyphenated, and every route that moved has a redirect in cconfig/site.yaml0 — with the c/hu0 prefix too — so old links still resolve. The sidebar is curated by hand in cconfig/sitenav.yaml0. Two ways to edit: • bIn git0 — edit cdefault..md0, commit, push; the webhook brings it live within seconds. • bIn the admin panel0 (c/admin0) — Grav writes into the bind-mounted working tree, and the fetcher commits and pushes it within about a minute. Pages under cprojects/0 and cteam/0 need a login (through Authentik); a section's child index hides them from guests. Images live in cassets/0, served at c/wiki-assets/…0. 1Languages 1═════════ The wiki is bilingual: bEnglish is the default and has no URL prefix0, Hungarian lives under c/hu0. A page carries its language in its filename — cdefault.en.md or cdefault.hu.md0 — and the language switcher sits in the top bar. English pages have a Hungarian translation. Hungarian-only pages (the association paperwork, the meeting notes, the Neumatronic Universe lore) do not get an English one: ccontent_fallback0 in cconfig/system.yaml0 makes the English request fall through to the Hungarian file, so nothing 404s. The JSON API follows the same rule: c/custom/pages.json0 is English, c/hu/custom/pages.json0 is Hungarian. Each response echoes the requested clang0, and every page carries a clocale0 saying which language its body is iactually written in — the two differ exactly where the fallback kicked in. 1Update flow 1═══════════ 1. Someone pushes to cwiki-pages0 on Gitea, or edits a page in the admin panel. 2. The fetcher brings the two sides together in the live checkout (c/srv/stacks/wiki-pages0): a push arrives through the Gitea webhook, an admin edit is committed and pushed. A change to the stack itself (compose, Dockerfiles, cphp/0, capache/0, cfetcher/0, cbbs/0) also runs the pipeline, whose cci-deploy wiki-pages0 rebuilds the containers. 3. The repo is bind-mounted, so the pulled changes are live at once. Asset timestamps (cassets.enable_asset_timestamp0) make cached browsers fetch changed theme CSS/JS. 4. c/custom/updates.json0 lists every page by modification time. 5. The 2Updater bot polls it, compares against its cache, and posts a Discord notification per new update. 1Sync 1════ The live checkout is written from both sides, so the fetcher sorts paths into lanes: • bContent0 — cpages/0, cassets/0, caccounts/0: synced both ways. A server edit is committed once its files have not changed for 30 seconds, named by route (cwiki (server): /team/meetings0). • bCode0 — everything else: git only. A change on the server is idrift0: it shows on c/health0, the iWiki server drift0 alert fires after an hour, and it is never committed automatically. cdocker exec wiki-fetcher wiki-fetcher status0 lists it; cwiki-fetcher commit -m "…" 0 commits it on purpose (e.g. after a GPM update). • bState0 — Grav runtime files (cdata/api-keys.yaml0, caches): gitignored. When both sides have new commits, the server's are rebased onto the remote in a throwaway worktree; the live tree only ever moves by fast-forward. On a conflict the live wiki stays as it was and the server's commits go to a cserver/conflict-