Files
Integration-kit/README.md
wtclaude cffd525bdf
All checks were successful
PR Checks / template (pull_request) Successful in 6s
PR Checks / links (pull_request) Successful in 7s
docs: scaffold the Integration Kit — front page, outline, and the checks
Phase 5 slice 0 (MODULE_SYSTEM.md §2.11.1). The repo's governance, the front
page, the book's outline, and the CI that keeps the whole thing from rotting.

README.md
  What the reader is building, all three parts, and the draft banner: the kit is
  finished when someone outside this project builds a working module by
  following it alone, and that has not happened. Says the sidecar rule plainly
  (MODULE_API.md §2.7) rather than leaving it to chapter 3, because a reader who
  skims the front page and starts coding should still get that one right.

book/README.md
  The outline of four chapters, landed before the prose so the shape can be
  argued with. Chapters are named but NOT linked — a link to a file that does
  not exist is what the link check is for, and an outline should not be the
  first thing to fail it.

CONTRIBUTING.md
  The rule that governs every change here: the kit never re-specifies a
  contract. Also the prose conventions, and why the pinned ref points at core's
  `edge` rather than `main`.

SECURITY.md
  Scoped for a repo that runs nothing: the two things that ARE reportable are a
  template that teaches an insecure pattern (it is meant to be copied) and a
  chapter that teaches something dangerous.

scripts/checkLinks.js
  Relative links resolve; anchors match a real heading; no link pins a reader to
  a commit snapshot of a moving document. Nothing is fetched — a self-hosted
  Gitea would fail on a credential-less runner and teach us to ignore red.
  Fences and code spans are stripped by a line walk, not a regexp.

  Its first run found a real one: a PR template's relative links resolve from
  the REPO ROOT, because that is where their text ends up when Gitea inlines
  them into a pull request body. Encoded, with the reason.

scripts/checkCoreApi.js
  The anti-rot check. Asserts template/module.json's `coreApi` EQUALS the pinned
  core's MODULE_API_VERSION — equality, not "satisfies", because a range check
  stays green across a contract bump and green would then mean "the template
  still loads" instead of "someone has re-read the book". Both failure branches
  and the pass were exercised against a real core checkout.

ci/core-ref.json
  The pin, same convention as Module-uo's. Points at `edge`: core's `main` has
  no server/src/modules/ until the cutover, and that pin is one of the things
  the cutover has to revisit.

.gitea/workflows/pr-checks.yml
  Two jobs. `links` always runs; `template` is conditional on
  template/module.json existing, so the repo is gated now and the job arms
  itself when slice 1 lands, with no edit to the workflow. Same guard Module-uo
  used through its planning phase.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-12 09:47:22 -05:00

5.3 KiB

Runic Gateway — Integration Kit

How to put a game on a Runic Gateway site.

Runic Gateway is a website platform for game communities. Core knows nothing about any particular game: everything game-specific — routes, tables, pages, navigation, notifications — arrives as an installable module, and an operator installs one from an admin panel without building anything. module-uo is the first module and serves an Ultima Online shard. This kit is how you write the second one.

🚧 This is a draft

The kit is finished when someone outside this project builds a working module for a new game by following it alone, without reading core's source. That has not happened yet, so treat every chapter as untested on you. If you are that person: the places you get stuck are the most valuable thing this repo can receive — tell us, and please say where you left the kit and what you did next.


What you are building

Three things, and the kit is one book rather than a page in three repos because the reasons live in the joins between them:

# Part What it is
1 The website module A bundle core loads at boot: server routes, a schema fragment, a prebuilt client chunk, navigation. The bulk of the work, and the only part every module needs.
2 The sidecar A small service that owns the connection to your game server, and owns the durable copy of what the game said. Not optional — see below.
3 The game-side plugin Whatever runs inside your game and feeds the sidecar, without ever letting the sidecar stall the game.
   your game server  ──dials out──▶  your sidecar  ──HTTP + WS──▶  website core
   (plugin: bounded              (owns the socket,              (loads your module,
    queue, writer thread)         persists to its own            serves the pages)
                                  store, then forwards)

The website process never opens a connection to a game server. That is a rule in the contract (MODULE_API.md §2.7, MODULE_API_VERSION 1.4.0), not a style preference, and chapter 3 is mostly about why. The short version: the website is the internet-facing process and your game is not; the sidecar persists before it forwards, so a website that is down or mid-deploy loses nothing; and a game must never block on a web request. A game that already exposes a remote-control surface — Rust's RCON over WebSocket, say — needs a thin sidecar, not none.

Start here

  1. The dry run — a complete module designed on paper for a second game, Rust, chosen for how little it shares with Ultima Online. Read it first. It is the shortest honest picture of the whole job, and it names the one thing the contract cannot do yet.
  2. template/ — a module that builds and loads, doing almost nothing. Copy it, rename it, and you have a running module before you have read a chapter.
  3. The bookbook/, four chapters, in the order the work happens.

The one rule this kit follows

It never re-specifies a contract. These documents are normative, and where the kit and one of them disagree, they win and the kit has a bug:

Authority For
MODULE_API.md Everything a module may do: module.json, ctx, the register* calls, the client registry, the UI kit, schema-fragment rules, the loader's obligations.
MODULE_SYSTEM.md Why the module system is shaped this way, and how a module is installed and removed.
link/PLAN.md + INTEGRATION.md The shard↔sidecar wire protocol, as one real sidecar implements it.

The kit teaches: the order to do things in, the reasoning, worked examples, and the mistakes that cost this project time. Where it must show a member list it quotes with a pointer rather than copying, because a guide that restates a contract diverges from it silently — and a reader who follows the divergent copy gets a module that fails validation for reasons the guide cannot explain.

What this repo contains

book/        the chapters
template/    a module that builds — copy this
scripts/     the checks CI runs over both

CI clones core at a pinned commit, asserts the version the template declares still matches that core's MODULE_API_VERSION, builds the template, and checks every link in the book. So a change to the contract breaks this repo's build loudly instead of leaving a chapter quietly wrong.

Licence

GPL-3.0-or-later, like every Runic Gateway repo — see LICENSE.md. The template/ directory is meant to be copied and made yours; it carries the same licence, and so does anything derived from it.