feat(deploy): single-origin path-based deployment + project site #34

Merged
developer merged 4 commits from feature/deploy-single-origin into development 2026-05-23 17:24:25 +00:00
Owner

What & why

Serve the whole stack behind one host (path-based) instead of the two-host www/api split, so the built artifact is domain-agnostic — the same bundle runs under any domain with no rebuild.

  • / → project site (new VitePress)
  • /game/ → game UI (SvelteKit, base /game)
  • /api/*, /healthz → gateway public REST (galaxy-api:8080)
  • /rpc/* → gateway Connect/gRPC-web (galaxy-api:9090, /rpc stripped by the edge Caddy)

The UI talks to the gateway same-origin via relative URLs (origin resolved at runtime), so CORS is disabled (empty allow-list) and one host needs one cert. The auth model has no cookies/CSRF, so subdomain isolation would buy nothing.

Highlights

  • Proto rename galaxy.gateway.v1.EdgeGatewayedge.v1.Gateway (public path /rpc/edge.v1.Gateway/<Method>); Go + TS regenerated.
  • Game UI under /game/ via env BASE_PATH (empty by default so dev/CI stay at root); manifest, service-worker scope, WASM loader, and all navigation made base-aware via a withBase helper.
  • Project site (site/, VitePress): i18n en/ru with the built-in switcher, LaTeX math, a minimal monospace theme; built + served at /.
  • Edge Caddy (dev+prod) rewritten for path routing; dev-deploy compose/Makefile + CI (dev-deploy, prod-build, new site-build) build and seed the site; probes hit /, /game/, /healthz.
  • Docs synced (ARCHITECTURE, gateway README/openapi, dev-deploy & local-dev READMEs, CLAUDE.md, ui/PLAN); FUNCTIONAL/FUNCTIONAL_ru reviewed (no user-visible-URL change needed).

Tests (feature push — all green)

  • go-unit ✓ · ui-test ✓ (Vitest 761/761, Playwright 224 passed + 3 flaky/passed, PWA 3/3) · site-build ✓.
  • Local: buf generate clean, gateway go build/vet/test, BASE_PATH=/game UI build (assets /game-prefixed), vitepress build, caddy validate.

integration runs on this PR (covers the proto rename end-to-end through testenv/connect_client.go).

🤖 Generated with Claude Code

## What & why Serve the whole stack behind one host (path-based) instead of the two-host `www`/`api` split, so the built artifact is **domain-agnostic** — the same bundle runs under any domain with no rebuild. - `/` → project site (new VitePress) - `/game/` → game UI (SvelteKit, base `/game`) - `/api/*`, `/healthz` → gateway public REST (`galaxy-api:8080`) - `/rpc/*` → gateway Connect/gRPC-web (`galaxy-api:9090`, `/rpc` stripped by the edge Caddy) The UI talks to the gateway same-origin via relative URLs (origin resolved at runtime), so CORS is disabled (empty allow-list) and one host needs one cert. The auth model has no cookies/CSRF, so subdomain isolation would buy nothing. ## Highlights - **Proto rename** `galaxy.gateway.v1.EdgeGateway` → `edge.v1.Gateway` (public path `/rpc/edge.v1.Gateway/<Method>`); Go + TS regenerated. - **Game UI under `/game/`** via env `BASE_PATH` (empty by default so dev/CI stay at root); manifest, service-worker scope, WASM loader, and all navigation made base-aware via a `withBase` helper. - **Project site** (`site/`, VitePress): i18n en/ru with the built-in switcher, LaTeX math, a minimal monospace theme; built + served at `/`. - Edge Caddy (dev+prod) rewritten for path routing; dev-deploy compose/Makefile + CI (`dev-deploy`, `prod-build`, new `site-build`) build and seed the site; probes hit `/`, `/game/`, `/healthz`. - Docs synced (ARCHITECTURE, gateway README/openapi, dev-deploy & local-dev READMEs, CLAUDE.md, ui/PLAN); `FUNCTIONAL`/`FUNCTIONAL_ru` reviewed (no user-visible-URL change needed). ## Tests (feature push — all green) - `go-unit` ✓ · `ui-test` ✓ (Vitest 761/761, Playwright 224 passed + 3 flaky/passed, PWA 3/3) · `site-build` ✓. - Local: `buf generate` clean, gateway `go build`/`vet`/`test`, `BASE_PATH=/game` UI build (assets `/game`-prefixed), `vitepress build`, `caddy validate`. `integration` runs on this PR (covers the proto rename end-to-end through `testenv/connect_client.go`). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
developer added 2 commits 2026-05-23 16:28:20 +00:00
feat(deploy): single-origin path-based deployment + project site
Build · Site / build (push) Successful in 8s
Tests · Go / test (push) Successful in 2m22s
Tests · UI / test (push) Failing after 2m42s
8565942392
Serve the whole stack behind one host: site at /, game UI at /game/,
gateway REST at /api + /healthz, Connect at /rpc (prefix stripped by the
edge Caddy). The built artifact is domain-agnostic — the UI talks to the
gateway same-origin via relative URLs, so the same bundle runs under any
host with no rebuild and with CORS disabled.

- Rename the Connect proto service galaxy.gateway.v1.EdgeGateway ->
  edge.v1.Gateway; regenerate Go + TS; public path /rpc/edge.v1.Gateway.
- Move the game UI under base path /game (env BASE_PATH); make the
  manifest, service-worker scope, WASM loader, and all navigation
  base-aware via a withBase helper.
- Relative API + /rpc Connect prefix; Vite dev proxy mirrors the strip.
- Rewrite the edge Caddy (dev + prod) for path-based routing; empty CORS
  allow-lists (same-origin); single host.
- New VitePress project site (site/): i18n en/ru with switcher, LaTeX
  math, minimal monospace theme; built and served at /.
- dev-deploy compose/Makefile + CI (dev-deploy, prod-build, new
  site-build) build and seed the site; probes hit /, /game/, /healthz.
- Sync docs (ARCHITECTURE, gateway README/openapi, dev-deploy &
  local-dev READMEs, CLAUDE.md, ui/PLAN).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
test(ui): assert relative manifest start_url in the PWA spec
Tests · UI / test (push) Successful in 2m28s
Tests · Integration / integration (pull_request) Successful in 1m46s
Build · Site / build (pull_request) Successful in 10s
Tests · Go / test (pull_request) Successful in 2m1s
Tests · UI / test (pull_request) Successful in 2m46s
a453b74b04
The single-origin manifest now uses relative URLs (`start_url: "./"`) so
it stays base-agnostic under `/` and `/game/`. Update the PWA spec to
assert the relative value instead of the old absolute `/`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
developer added 1 commit 2026-05-23 16:53:17 +00:00
fix(ui): redirect app root to lobby/login; evict stale root service worker
Tests · UI / test (push) Has been cancelled
Build · Site / build (push) Successful in 8s
Tests · Integration / integration (pull_request) Successful in 1m42s
Build · Site / build (pull_request) Successful in 6s
Tests · UI / test (pull_request) Successful in 2m23s
Tests · Go / test (pull_request) Successful in 1m56s
9cb5097f54
- The app root ("/", i.e. /game/) rendered a dev "workspace skeleton"
  stub, and the layout guard only redirected anonymous users off it, so
  an authenticated visitor stayed on the stub. Redirect "/" to /lobby
  (authenticated) and /login (anonymous), and replace the stub with a
  minimal loading placeholder. Drop the obsolete landing-stub unit test
  (root redirect is covered by the auth-flow e2e).
- Ship a tombstone /service-worker.js on the project site so any old
  root-scoped PWA worker (from when the game lived at the origin root)
  unregisters itself instead of serving a stale cached page at the
  site origin. The game now registers its worker only under /game/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
developer added 1 commit 2026-05-23 17:13:16 +00:00
fix(site): link to the game with target=_self to avoid VitePress SPA 404
Build · Site / build (push) Successful in 8s
Tests · Integration / integration (pull_request) Successful in 1m38s
Build · Site / build (pull_request) Successful in 10s
Tests · Go / test (pull_request) Failing after 3m0s
Tests · UI / test (pull_request) Successful in 2m35s
ec98639d49
VitePress is a Vue SPA; a same-origin link to /game/ (a separate app, not
a VitePress page) was intercepted by its client router and rendered
VitePress's own 404 until a manual reload. Mark the game links (both
home pages and the nav item) target="_self" so the click is a real
browser navigation that the edge Caddy serves from the game bundle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
developer merged commit ae91037bc3 into development 2026-05-23 17:24:25 +00:00
developer deleted branch feature/deploy-single-origin 2026-05-23 17:24:26 +00:00
Sign in to join this conversation.