From d9945882e50716cda5e5a2fe12053181d4c7281d Mon Sep 17 00:00:00 2001 From: mrhid6 Date: Tue, 28 Jul 2026 15:22:20 +0100 Subject: [PATCH] docs: serve the documentation site under /docs on the marketing host --- .../specs/2026-07-28-docs-site-design.md | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/docs/superpowers/specs/2026-07-28-docs-site-design.md b/docs/superpowers/specs/2026-07-28-docs-site-design.md index e5de9e4..0ba66bd 100644 --- a/docs/superpowers/specs/2026-07-28-docs-site-design.md +++ b/docs/superpowers/specs/2026-07-28-docs-site-design.md @@ -19,10 +19,19 @@ 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`. +- Served at **`vantage.hostxtra.co.uk/docs`** — a path on the marketing site's + host, routed by a separate Nginx Proxy Manager custom location rather than by + `site/`. It is a path, not a subdomain, deliberately: `*.vantage.hostxtra.co.uk` + is the per-tenant instance namespace and `APP_ROOT_LABEL` resolves an org from + the label before `vantage`, so a `docs.` label there would be read as a tenant + slug. + + This makes `baseUrl: "/docs/"` load-bearing. An NPM custom location forwards + the **full** request path upstream — it does not strip the `/docs` prefix — so + the container serves the build from `/usr/share/nginx/html/docs`, not from the + document root. Prefix, asset URLs and upstream paths then agree with no + rewrite rule to keep in step. Getting this wrong is quiet: the HTML loads and + every stylesheet and script 404s. - 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`. @@ -35,9 +44,11 @@ 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/`. +2. `nginx:alpine-slim` runner — copies `build/` to + `/usr/share/nginx/html/docs` (see the `/docs` prefix note above), plus a + small `nginx.conf` giving `try_files` a 404 fallback to Docusaurus's + `404.html` and long cache headers on `/docs/assets/`. A bare `/` request + redirects to `/docs/`, so hitting the container directly is not a blank 403. `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. @@ -46,7 +57,8 @@ 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` | +| `DOCS_URL` | site `url`; defaults to `https://vantage.hostxtra.co.uk` | +| `DOCS_BASE_URL` | site `baseUrl`; defaults to `/docs/`. Must match the NPM location and the runner's copy target | | `APP_URL` | navbar link to the control plane | | `HQ_URL` | navbar link to the HQ portal |