feat(site): phase 1 — the foundation
Some checks failed
PR checks / checks (pull_request) Failing after 4m19s

Astro 7 with the Node adapter, Starlight mounted at /docs, the token file, both
self-hosted typefaces, the layout shell, and the two build-time checks from §12.

The palette's gold and cyan are sampled from runic-emblem.png rather than
guessed, per §11: 494,059 opaque pixels binned by hue, each value annotated with
its measured contrast against the ground, and restricted rather than brightened
where a ratio fails.

- checkTokens.mjs fails the build on any colour literal outside tokens.css,
  which is what keeps §7's "recolouring is a file copy" promise true.
- checkFacts.mjs re-reads all 14 externally-sourced facts from their authorities
  over the Gitea API and fails on disagreement. It also enforces D13: no email
  address in the source outside brand-default/brand.json.
- Both were negative-tested; neither has ever been allowed to pass by default.

§6 asks for output:'server' with per-page prerender=true. Astro 7 expresses the
same runtime shape as output:'static' with an adapter, opting individual routes
out — so the default is static rather than accidentally server-rendered.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-19 19:08:52 -05:00
parent 650ea21ad4
commit 66187dde5d
25 changed files with 10462 additions and 0 deletions

102
README.md
View File

@@ -1,2 +1,104 @@
# runicgateway.com
The public marketing and documentation site for [Runic Gateway][org] — the platform that puts a
private game server's live state on a public website without ever exposing the game to the internet.
Two audiences: **server administrators** who want to understand and install the platform, and
**developers** who want to build modules and integrations for it. A third arrives with the Android
closed beta: **players**, who want the app.
**The design of record is [`PLAN.md`](PLAN.md).** It is not a sketch — it carries the verified
platform state, the org lead's decisions, the information architecture, and the build phases. Read
it before changing anything here.
**Status: phase 1 of 12 — the foundation.** The scaffold, the token file, the typography, the layout
shell and the two build-time checks are in place. The homepage is phase 3, the marketing pages
phase 4, and the documentation — the installation path, which is the priority of the whole project —
phase 7.
---
## Running it
```bash
npm install
npm run dev # http://localhost:4321
```
```bash
npm run build # → dist/ (prerendered pages + the Node server entry)
npm start # serve the built site
```
Node 22 LTS or newer.
## The checks, and why they are not optional
Two of them, both from `PLAN.md` §12. Neither is a linter; each one enforces a promise the site
makes that would otherwise decay quietly.
```bash
npm run check:tokens # no colour literal outside the token file
GITEA_TOKEN=<token> npm run check:facts # every version agrees with its authority
npm run check # astro check
npm run verify # all of the above, then a production build
```
**`checkFacts.mjs`** re-reads every version, protocol number and bundle tag in
`src/data/platform.json` from its source of truth over the Gitea API — the sidecar's
`PROTOCOL_VERSION`, the overlay's `overlay.toml`, the website's `MODULE_API_VERSION`, the installer's
published bundle manifest, and each repository's latest release — and fails on any disagreement.
When the platform moves, this repository goes red so that someone updates the site. **That failure is
the feature**, the same mechanism and the same intent as the Integration Kit's `checkCoreApi.js`. §1
of the plan records what it is guarding against: an earlier draft confidently stated the platform was
on protocol 3, because every checkout in the workspace sat on a feature branch whose local `main` had
never been fetched.
It needs a token — anonymous raw fetches fail on this Gitea instance, and a check that silently skips
itself is worse than no check at all.
**`checkTokens.mjs`** fails the build if a colour literal appears anywhere in `src/` outside
`src/styles/tokens.css`. §7 promises that recolouring the site is a file copy and a container
restart; a mounted `theme.css` can only redefine custom properties, so a literal in a component is a
piece of the site an operator can never reach. Without the check, "one CSS file changes the
appearance" becomes "one CSS file changes most of the appearance".
## Layout
```
src/
data/platform.json Every externally-sourced fact. No version is written in prose.
styles/tokens.css THE token file — the only place a colour literal may appear.
styles/global.css The layout shell, built entirely from tokens.
styles/starlight.css Restates our tokens as Starlight's, so the docs cannot drift.
layouts/, components/ The marketing chrome.
pages/ Marketing routes.
content/docs/docs/ Documentation. The extra level mounts Starlight at /docs.
lib/brand.mjs The single accessor for brand text.
lib/tokens.mjs Reads tokens.css at build time, for the few values that leave CSS.
config/sidebar.mjs The documentation journey, and the planned tree behind it.
brand-default/ The stock brand, baked into the image and always complete.
scripts/ The build-time checks.
```
Two directories are bind mounts at runtime and are **not** in the repository: `brand/` overrides
anything in `brand-default/` per file, and `data/` holds the beta signup store. See `PLAN.md` §6
and §7.
## Contributing
Branch from `main` (`feature/…`, `fix/…`, `docs/…`, `chore/…`) and use
[Conventional Commits](https://www.conventionalcommits.org/). Run `npm run verify` before opening a
pull request.
**AI-assisted contributions must be disclosed**, per org policy: tick the box in the pull request
template naming the tool, and mark AI-authored commits with a trailer such as
`Co-Authored-By: Claude <noreply@anthropic.com>`. Undisclosed AI-generated contributions may be
closed.
## Licence
GPL-3.0-or-later, in common with every repository in the organisation. See [LICENSE](LICENSE).
[org]: https://gitea.whitlocktech.com/RunicGateway