# Vantage documentation (`vantage-docs`) The user-facing documentation, served at **vantage.hostxtra.co.uk/docs**. Docusaurus 3 in docs-only mode (`routeBasePath: "/"`, no blog), one version tracking `main`, search indexed at build time by `@easyops-cn/docusaurus-search-local` so nothing external is keyed or called. Extracted from the `vantage` monorepo with its history, where it was `docsite/`. The whole repository is the site — there is no subdirectory. It documents the **product**, not the codebase: each repository's own CLAUDE.md remains the contributor's map, and the two are allowed to differ in altitude but not in fact. Five sections — Getting started, Vantage, Vantage HQ, Reference, Operations — with `sidebars.ts` authored by hand so ordering is a decision rather than a filename accident. ## A path, not a subdomain `*.vantage.hostxtra.co.uk` is the per-tenant instance namespace, and the control plane's `APP_ROOT_LABEL` resolves an instance from the label before `vantage` — so a `docs.` label would be read as a tenant slug. Hence `/docs` on the marketing host instead. **Three things must agree, and when they do not the HTML loads while every asset 404s:** 1. `DOCS_BASE_URL` (default `/docs/` in the Dockerfile) 2. the proxy location that routes here — which must also sort **above** the catch-all forwarding to `site:3003`, or Next answers the 404 first 3. the directory the runtime stage serves from, `/usr/share/nginx/html/docs` The proxy forwards the **full** path; it does not strip `/docs`. That is the whole reason the third item exists. Unlike the three Next apps this builds to static files, so its runtime stage is `nginx:alpine-slim` rather than Node, and it listens on **80**, not 3000. ## Design tokens `src/css/custom.css` holds `vantage-site`'s `web/app/globals.css` token blocks **copied verbatim** — same names, same values. This is the one place the tokens are not consumed through Tailwind: everything below the token block maps Docusaurus's `--ifm-*` variables onto them. Docusaurus already stamps `data-theme` on ``, which is the selector the dark block keys on, so the built-in toggle needed no wiring. The rule holds all the same: **no rule in that file outside the token blocks may carry a hex.** The one concession is `static/img/favicon.svg`, which must, for the same reason the email layout must — a browser tab cannot read a token. **Nothing enforces the match across the four front ends, and they are now in four repositories.** A token change here follows one in `vantage-site`; there is no way to make them one commit. ## Deployment A fragment, composed on top of the control plane's own file: ```bash docker compose \ -f vantage/deploy/docker/docker-compose.yml \ -f vantage-site/deploy/docker-compose.yml \ -f vantage-docs/deploy/docker-compose.yml \ -f vantage-admin/deploy/docker-compose.yml \ up -d ``` Not part of a self-hosted install. ## CI/CD `.gitea/workflows/deploy.yml`, on every push to `main` plus `workflow_dispatch`. One image, `vantage/vantage-docs:latest`, from the repository root — the whole repository is the site, so there is nothing to detect a change in and it rebuilds on every push. **No build args are passed, deliberately.** `DOCS_URL`, `DOCS_BASE_URL`, `APP_URL` and `HQ_URL` all have correct defaults in the Dockerfile, and passing an unset repo variable would blank one rather than leave it alone — which for `DOCS_BASE_URL` means every asset path in the build. Change them in the Dockerfile. The monorepo's workflow passed none either; this preserves that. | Name | Type | Value | | --------------- | ------ | ----------------------------------------------------------- | | `RELEASE_TOKEN` | Secret | Gitea API token, `write:package`. No module fetch here, so it needs no org read access | | `REGISTRY_USER` | Secret | Gitea username. Must own `RELEASE_TOKEN` | | `DOCKER_HOST` | Variable | registry host used for image tags | Despite the name the workflow **does not deploy**; it only builds and pushes.