Reviewed-on: #1
module-uo — the Ultima Online module for Runic Gateway
The Runic Gateway website is becoming game-agnostic: core keeps accounts, sessions, the wiki, posts, branding, theming and the admin panel, and everything that knows what a shard is moves out into an installable module. This repo is that module — the first one, and the reference for every module that follows.
RunicGateway/website (core — game-agnostic)
│ loads modules at boot, synchronously, from the filesystem
▼
┌───────────────────────────────────────────┐
│ module-uo (>>> HERE <<<) │
│ shard status · spawn atlas · marketplace │
│ governors · cliloc · town crier · uo-link│
└───────────────────────────────────────────┘
│ server half: routers, models, schema fragment
│ client half: prebuilt ESM chunk, SPA routes + nav
▼
the shard bridge (RunicGateway/link → RunicGateway/servuo-plugins)
The module's id is uo — that is what appears in module.json, in the installed_modules
table, in the modules/<id>/ path on disk and in the URL segment (/uo/*, /admin/uo/*,
/player/uo/*). Module-uo is the repository; module-uo is the module and its release artifact.
Status: planning — no module code exists yet
This repo currently holds governance scaffolding only. The design of record is
website/MODULE_SYSTEM.md
in the docs repo — read it before opening a PR here. It defines the module API surface, the
packaging, the state machine, the install/uninstall/purge model, and the phases.
| Phase | Where it happens | State |
|---|---|---|
0 — CI trigger fix, cut website edge, bootstrap this repo |
website, here |
🟡 in progress |
1 — module API contract (docs/website/MODULE_API.md) + the atlas spike |
docs, website |
⬜ blocking |
2 — core scaffolding: loader, installed_modules, registries, client registry |
website |
⬜ |
| 3 — extract the UO half of the site into this repo | website, here |
⬜ |
| 4 — delivery: the admin Modules screen + the Docker path | website |
⬜ |
Nothing lands here until Phase 1 has settled the contract this module is written against. Phase 3 is what fills the repo.
What it will contain
One repo, one bundle: the server half and the client half live side by side and version together, so a route and the screen that calls it can never be mismatched.
module.json id, version, coreApi range, mounts, extensions
server/ routers, controllers, models, utils
server/db/schema.sql idempotent fragment, replayed by core's ensureSchema()
server/db/purge.sql destructive; only ever run by an explicit purge
client/src/ route components, nav registrations, feature provider
client/dist/ PREBUILT ESM chunk, built by CI — never by an operator
Release artifact: module-uo-<version>.tar.gz, plus a manifest carrying its sha256.
How it reaches an operator
An operator never builds anything. Installing a module is the WordPress-plugin experience: an
admin-panel action, or a directory mounted into the Docker container — never a build step, because
production runs a prebuilt, pull-only image. That constraint is why the client half ships as a
prebuilt ESM chunk that resolves React from a window.__rg global rather than an import map (an
import map must be inline, and the site's CSP is script-src 'self').
The installer is not the delivery path. It deploys the shard side — the plugin overlay and the uo-link sidecar — and never contacts the website. Module delivery is website-side only.
Compatibility
module.json declares a coreApi semver range, checked at boot against core's MODULE_API_VERSION.
A mismatch fails loudly — the module is marked startup_failed and the site comes up without it,
rather than mis-loading. This is a separate number from PROTOCOL_VERSION, which versions the shard
wire protocol and says nothing about a website module.
A module that fails to load must never take the site down.
Related repos
| Repo | What |
|---|---|
this — RunicGateway/Module-uo |
The UO module: the game-specific half of the website. |
| RunicGateway/website | Core — the site, admin panel and API that loads this module. |
| RunicGateway/link | The uo-link sidecar — the network-facing half of the game bridge this module talks to. |
| RunicGateway/servuo-plugins | The C# ServUO plugin that feeds the sidecar. |
| RunicGateway/installer | Deploys the shard side. Not the module delivery path. |
| RunicGateway/docs | All project documentation, including the module system design and this module's docs under modules/uo/. |
Contributing
See CONTRIBUTING.md. Contributions are welcome, AI assistance must be disclosed, and security problems go to SECURITY.md rather than a public issue.
License
GNU General Public License v3.0 or later — see LICENSE.md.