--- import Base from '../layouts/Base.astro'; import PageHeader from '../components/PageHeader.astro'; import NotBuilt from '../components/NotBuilt.astro'; import Screenshot from '../components/Screenshot.astro'; import platform from '../data/platform.json'; import { capabilityGroups, assertCapabilityCoverage, assertDetailCoverage, } from '../data/capabilities.mjs'; /** * `/features/` — PLAN.md §13 phase 4, built to D20. * * --------------------------------------------------------------------------------------- * THE SAME LIST THE HOMEPAGE HAS, WITH THE ARGUMENT ATTACHED * --------------------------------------------------------------------------------------- * D18 put all five groups on the homepage named only, and left the per-capability argument * here. This page is therefore not a second list: it is the same `capabilities.mjs` data * rendered with the `detail` line the homepage drops. That is the whole of D20, and it is * what makes "the site advertises something that was removed" a build failure rather than * a thing somebody has to notice. * * Both assertions below run at build time and both name this page in their message. * `assertCapabilityCoverage` is the module contract the homepage also runs — repeated here * deliberately, since either page can be built alone and each should fail on its own. * `assertDetailCoverage` is this page's own: a capability with no detail renders as a * heading with nothing under it, and nothing else in the repo would notice. * * --------------------------------------------------------------------------------------- * THREE THINGS THE MARKUP SAYS THAT THE HOMEPAGE DOES NOT * --------------------------------------------------------------------------------------- * 1. WHERE A CAPABILITY COMES FROM. Every group states whether core supplies it or the * installed module does. The homepage carries one chip on one group; here it is a full * sentence on all five, because this is the page a reader arrives at wanting to know * what they get on a deployment with no module at all. * * 2. WHAT NEEDS A MODULE TO FILL IT. Teams and Team forums are core machinery that cannot * originate a Team — see the `needsModule` note in `capabilities.mjs` for what the tree * actually says. That is neither "core" nor "module-supplied", and a page that offered * only those two words would have to lie in one direction or the other (D24). * * 3. WHERE TO SEE IT RUNNING. Capabilities with a stable public route carry a deep link * into the demo, hidden until a `demoUrl` is mounted (D25). The markup contract is * exact and `scripts/checkBrand.mjs` enforces it: * * href="" data-demo-url="" data-demo-path="/uo/market" * * `applyBrand.mjs` recomputes all three attributes at boot. Do not reorder them, do not * insert anything between them, and do not write a path into the `href` — the rewrite * matches bytes, and a stock build hides every one of these links, so a mistake here is * invisible until the day somebody configures a demo. */ assertCapabilityCoverage(platform.moduleUoCapabilities); assertDetailCoverage(); /** * Which screenshots sit under which group (PLAN.md §13 phase 9, D44). * * Deliberately here and not in `capabilities.mjs`. That file is a contract — two build-time * assertions read it and `/modules/` and the homepage render from it — and a group is * defined by what the software does, not by what somebody has got round to photographing. * A group with no figure is the normal case, not an omission: Infrastructure is about where * the container runs and who owns the database, and a picture of a web page says nothing * true about either. * * `Screenshot` throws on an id that `screens.mjs` does not declare, so a typo here fails the * build rather than rendering a broken image. */ const groupScreens: Record = { community: ['news'], 'game-intelligence': ['marketplace', 'spawn-atlas', 'guilds', 'houses'], administration: ['admin-dashboard', 'admin-users'], integration: ['admin-modules'], }; const title = 'Features'; const description = 'What a Runic Gateway deployment does — core, and what the installed game module adds.'; ---

Grouped the way the software is actually divided, because that division is the thing most worth understanding before you install it: the core site is game-agnostic and does not know what a shard is, and everything that does arrives as an installable module.

Today there is one module and it covers Ultima Online, so the second group below is what a UO deployment gets. On a deployment with no module, that group is simply absent and the other four are unchanged.

{ capabilityGroups.map((group) => (

{group.title}

{group.moduleSupplied ? 'From the installed module' : 'Core'}

{group.summary}

{groupScreens[group.id] && (
{groupScreens[group.id].map((id: string) => ( ))}
)}
)) }