From 9db16522e3a483b63652b799a6c71976e4319cd6 Mon Sep 17 00:00:00 2001 From: mrhid6 Date: Tue, 28 Jul 2026 15:20:07 +0100 Subject: [PATCH] docs: design for the documentation site --- .../specs/2026-07-28-docs-site-design.md | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 docs/superpowers/specs/2026-07-28-docs-site-design.md diff --git a/docs/superpowers/specs/2026-07-28-docs-site-design.md b/docs/superpowers/specs/2026-07-28-docs-site-design.md new file mode 100644 index 0000000..e5de9e4 --- /dev/null +++ b/docs/superpowers/specs/2026-07-28-docs-site-design.md @@ -0,0 +1,150 @@ +# Documentation site — design + +**Date:** 2026-07-28 +**Status:** approved + +## Problem + +Vantage has no user-facing documentation. Everything an operator needs — how to +install self-hosted, how to enrol an agent, what a workflow step is, how a +licence gets issued — lives either in `CLAUDE.md` (written for contributors, not +users) or in the code. The marketing site sells the product and the control +plane runs it; neither explains it. + +## Solution + +A fourth Next-adjacent frontend, `docsite/`, built with Docusaurus v3 and shipped +alongside the marketing site. + +### Placement and deployment + +- Lives at repo root as `docsite/`. +- Served at **`docs.hostxtra.co.uk`**, deliberately outside + `*.vantage.hostxtra.co.uk` — that namespace is per-tenant instance subdomains + and `APP_ROOT_LABEL` resolves an org from the label before `vantage`. Same + reasoning that puts `adminsite/` on `vantage-hq.hostxtra.co.uk`. +- Added to **`deploy/docker-compose.site.yml` only**, published as `3005`. + `deploy/docker-compose.yml` (the self-hosted install) must never mention it, + exactly as it never mentions `site`, `sitesvc`, `admin` or `adminsite`. +- Added to `.gitea/workflows/server-deploy.yml` as a seventh image, rebuilding + on `^docsite/` only, build context `docsite/`. + +### Runtime + +Docusaurus emits a fully static site, so unlike `site/`, `web/` and +`adminsite/` there is no Node server at runtime. Two stages: + +1. `node:26-alpine` builder — `npm ci && npm run build` → `/app/build`. +2. `nginx:alpine-slim` runner — copies `build/` to `/usr/share/nginx/html`, + plus a small `nginx.conf` giving `try_files` a 404 fallback to Docusaurus's + `404.html` and long cache headers on `/assets/`. + +`nginx:alpine-slim` is roughly 12MB against `caddy:alpine`'s ~50MB, and nothing +here needs Caddy's automatic TLS — the host proxy already terminates it. + +Build args, baked at build time the same way `site/`'s are: + +| Arg | Purpose | +| --- | --- | +| `DOCS_URL` | site `url`; defaults to `https://docs.hostxtra.co.uk` | +| `APP_URL` | navbar link to the control plane | +| `HQ_URL` | navbar link to the HQ portal | + +### Theme + +`docsite/src/css/custom.css` carries `site/app/globals.css`'s token blocks +**copied verbatim** — same names, same values — and maps Docusaurus's `--ifm-*` +variables onto them. Docusaurus stamps `data-theme="light|dark"` on ``, +which is the same selector `site/`'s dark block already keys on, so the built-in +toggle works with no extra wiring. Light is the default, matching `site/` and +`adminsite/`. + +This makes a **fifth** copy of the token block (`site/`, `adminsite/`, `web/` +dark-only, `shared/mail/templates/layout.html.tmpl` as literal hex, and now +`docsite/`). Nothing enforces the match; `CLAUDE.md`'s Frontend section is +updated to say so. No component in `docsite/` may carry a hex value. + +Search is `@easyops-cn/docusaurus-search-local` — index built at compile time, +served from the same origin. No Algolia account, no external host, nothing to +key or rotate. + +Docs-only mode: `routeBasePath: "/"`, blog disabled, no tutorial scaffolding. + +## Content + +Sidebar is authored explicitly in `sidebars.ts` rather than autogenerated, so +ordering is a decision rather than a filename accident. + +### Getting Started + +| Page | Covers | +| --- | --- | +| `what-is-vantage` | The control plane, the agent, what problem each solves | +| `cloud-vs-self-hosted` | The two deployments, what differs (licensing, HQ-managed users, reaping) | +| `self-hosted-install` | Prereqs (Docker, external MongoDB, DNS, TLS), `docker-compose.yml`, required env, `docker compose up -d` | +| `first-login` | `/setup` bootstrap, first org and owner | +| `first-server` | `POST /servers/new`, the install one-liner, Linux and Windows, watching it flip to `active` | +| `claim-free-licence` | Linking the install to an HQ account, `claim-free` | + +`self-hosted-install` is the page the section exists for; it names every +required environment variable with its consequence-of-omission, in particular +`GRPC_HOST` (boot fails, no default is safe) and `KEY_ENCRYPTION_KEY`. + +### Vantage (the application) + +`servers` (agent install Linux/Windows, inventory, OS updates, agent +self-update) · `ssh-keys` (upload, generate-on-server, assign, revoke, what the +agent writes and when) · `workflows` (step library, default steps and why they +are read-only, the designer, running, live logs, `on_failure`, `output_env`, +workspaces, log retention) · `monitors` (the four check types, server vs agent +runner, retries, incidents, uptime rollups) · `notification-channels` (five +types, testing) · `secrets` (vault, `secret_refs` in steps, the ESO read path +and its bearer token) · `browser-console` (SSH/RDP/VNC, one-time tokens) · +`audit-log` · `settings` (members and roles, OIDC per org, retention, ESO token, +licence). + +### Vantage HQ (the portal) + +`accounts-and-signup` (account-first signup, email verification, an account is +a team) · `people-and-roles` (owner/admin/member, invitations, accepting) · +`cloud-instances` (create, overview, granting members and what a grant actually +is) · `self-hosted-instances` (purchase creates a placeholder, claim-link binds +the real UUID, relink) · `licensing-and-entitlements` (tiers, metered server +count, feature toggles, desired vs granted) · `billing` (Paddle as merchant of +record, checkout, the customer portal, changing configuration) · `free-tier` +(limits, the renewal window, reaping on cloud). + +### Reference + +`environment-variables` (server, sitesvc, admin, agent) · `rest-api` (the route +tables, grouped as in `CLAUDE.md`) · `grpc-api` (the eight RPCs, the command +stream) · `agent-config` (config.yaml, paths, permissions) · +`ports-and-networking` (which ports, which direction, what needs to be +reachable) · `troubleshooting`. + +### Operations + +`upgrading` (pull and recreate) · `backups` (MongoDB is the durable state; Redis +is sessions only) · `agent-updates` · `ci-cd` (which image rebuilds when, and +the repo-variable gap that pushes no commit). + +## Writing rules + +- Every guide is task-shaped: numbered steps, real paths and commands taken from + the repository, never invented UI. +- Behaviour that is a hard refusal gets an admonition, not a paragraph: default + steps are read-only (409 `ErrDefaultStep`), `POST /license` answers 409 + `cloud_managed` on cloud, HQ-sourced users cannot have their role changed + locally (409 `ErrHQManaged`). +- Where the UI enforces something, say that the API is the boundary and the UI + is the courtesy — the same phrasing the codebase uses. +- No screenshots in this pass. They rot faster than prose and there is no + capture pipeline. + +## Out of scope + +- Versioned documentation. One version, tracking `main`. Docusaurus versioning + can be switched on later without restructuring. +- Internationalisation. +- Screenshots and diagrams beyond what Mermaid renders inline. +- A docs search backed by an external service.