feat(home): phase 3 — the homepage
All checks were successful
PR checks / checks (pull_request) Successful in 49s

Replaces phase 1's scaffold with the real homepage: hero, the data path as
inline SVG, the self-hosted argument, all five capability groups, and the
get-started CTA. Three decisions the org lead took first are recorded in
PLAN.md as D17-D19.

The data path is drawn generically and captioned specifically (D17): the nodes
say "your game server" and "sidecar", the sub-labels and caption name ServUO and
uo-link. The SVG is aria-hidden because the four numbered steps beside it carry
the same path in prose — one telling, not two.

The capability list is data with a check behind it (D18). Every Game-intelligence
item names the module-uo capability slug it comes from, and the build fails if
the page and platform.json disagree either way. That needed a fifteenth fact in
checkFacts.mjs: §12 named the capability list as an externally-sourced fact and
nothing re-read it, so the chain rested on someone remembering. It also found
that the site was omitting two of the module's eight capabilities — guilds and
city governors are now listed, in the page and in §10.

The hero leads with the emblem (D19), derived from whichever logo.png is in
force so one file still changes the hero, header, tab icon and app icon
together.

Also here, both found by standing the build up rather than by review:

  - checkBrand.mjs now enforces the demo slot's markup contract. applyBrand.mjs
    reveals the demo link by replacing an exact pair of empty attributes; an
    attribute inserted between them produces a build where the mount sets a demo
    URL, the boot log says nothing and the link never appears. Both halves are
    checked and the literal is derived from the expression applyBrand.mjs uses,
    so they cannot drift.

  - The header nav overflowed at 390px — four links plus the lockup measured
    433px against a 390px viewport, so every phone got a horizontally scrolling
    page. Phase 1 left this to phase 3 expecting a disclosure control; it got a
    wrap instead, because with four links there is nothing to disclose and a
    hamburger costs state, script and duplicate markup.

Verified on a clean checkout of this commit: all four checks, astro check, a
production build, a live /brand/* smoke, and a demo URL mounted and reverted.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-20 00:03:04 -05:00
parent bb06f1de44
commit 556dee7355
12 changed files with 1333 additions and 78 deletions

48
PLAN.md
View File

@@ -519,14 +519,57 @@ Organised by what a reader is trying to do. A reader should never need to know t
**Feature grouping**, using project terminology:
- **Community** — Teams, Team forums, notifications, wiki, news and newsletter, player self-service
- **Game intelligence** *(module-supplied; `module-uo` today)* — shard status, economy, player-vendor
marketplace, houses and IDOCs, character sheets, spawn atlas, champion boards, points leaderboards
- **Game intelligence** *(module-supplied; `module-uo` today)* — shard status, economy, character
sheets, points and loyalty boards, player-vendor marketplace, houses and IDOCs, spawn atlas,
champion boards, guilds, city governors
- **Administration** — roles, moderation and appeals, content reports, audit log, bot scoring and IP
bans, module management, the shard connection
- **Integration** — modules, the sidecar bridge, Discord (slash commands, notifications, voice),
mobile and push, SSO
- **Infrastructure** — self-hosted, Docker, prebuilt pull-only images, branding as data, OpenAPI
Guilds and city governors were added to Game intelligence in phase 3: `module-uo` declares them as
capabilities and the site was omitting two of the eight. That correction is now mechanical rather
than editorial — see D18.
### How phase 3 built the homepage
Three decisions taken before the page was written (org lead, 2026-08-20).
**D17 — the data path is drawn generically, and captioned specifically.** The diagram's nodes read
"your game server", "sidecar", "Runic Gateway", "browser and app", because a reader should not have
to know this org's repository layout to understand the picture, and because the tagline promises a
platform. It does not hide what ships: the sub-labels and the caption name ServUO and uo-link
outright, since there is exactly one implementation of the shape today and §1 says the technical
truth wins. Rejected: naming the real components in the nodes (reads as a UO product), and omitting
UO entirely (advertises a generality one module proves).
**D18 — all five groups on the homepage, named only.** Not three with a link out: Integration and
Infrastructure carry the module and self-hosted arguments, which are the differentiators, and hiding
them until phase 4 would have made the front page look smaller than the product. The per-capability
argument stays `/features/`'s job so there is one copy of it.
The list is **data with a check behind it** (`src/data/capabilities.mjs`). Every Game-intelligence
item names the `module-uo` capability slug it comes from, and the build fails if the page and
`platform.json` disagree in either direction. Closing that loop needed a fifteenth fact in
`checkFacts.mjs`: §12 listed the capability list as an externally-sourced fact and nothing re-read
it, so the whole chain rested on someone remembering. Manifest → `platform.json` → page is now
checked end to end.
**D19 — the hero leads with the emblem.** Chosen over a type-only hero: the mark is already the
site logo, the Android launcher icon and the Play listing, and showing it large is what makes the
three read as one product (D11). It costs what D16 already accepted — raster art a mounted
`theme.css` cannot recolour — but every size is derived from whichever `logo.png` is in force
(D14), so the hero, the header, the tab icon and the installed icon still change together from one
file.
**A convention, not a decision:** the homepage links the final routes — `/features/`,
`/modules/`, `/integrations/` — which phases 4 to 6 have not written yet. The header and footer
already did this from phase 1. Nothing is deployed until phase 12, so no visitor meets a 404, and
nothing has to be rewritten later. Links *into the documentation* are the exception: they point at
`/docs/`, because phases 7 and 8 own those slugs and a guessed one would be a stale URL nothing
checks.
### Documentation
```
@@ -636,6 +679,7 @@ a mechanism rather than diligence:
| Protocol version | `link` `main:sidecar/src/main.rs``PROTOCOL_VERSION` |
| Overlay protocol | `servuo-plugins` `main:overlay.toml``protocol` |
| Module API | `website` `main:server/src/modules/version.js``MODULE_API_VERSION` |
| Module capability list | `Module-uo` `main:module.json``capabilities` (added in phase 3) |
| Bundle + component pins | `installer` branch `bundles`, **root** `current.json` |
| Release versions | Gitea releases API per repo |