Add SPA service block, runtime config override, README updates

- compose.yaml: new spa service. Image trm/spa:${SPA_TAG:-main}.
  expose: 80 (internal-only; reverse proxy fronts it). Read-only
  volume mount ${SPA_CONFIG_FILE:-./spa-config.json} ->
  /usr/share/nginx/html/config.json for the runtime-config override.
  Healthcheck via wget against localhost.
- spa-config.example.json: dev-default-equivalent file with env=stage.
  Operators copy to spa-config.json and edit per environment.
- .gitignore: spa-config.json never committed (per-environment).
- .env.example: new spa section documenting SPA_TAG and
  SPA_CONFIG_FILE; reframes the directus internal-only note as a
  shared design (SPA also internal-only).
- README.md:
  - Services in the stack: SPA moved from Planned to Currently.
  - Step 8 in first-deploy checklist: "Verify the SPA loads".
  - Network model: spell out the four routes the proxy must wire
    (/api, /ws-business, /ws-live, default -> SPA). Same-origin
    non-negotiable callout.
  - New "Runtime config override (SPA)" section: copy/edit/mount
    workflow + when not to use absolute URLs.
This commit is contained in:
2026-05-02 18:35:01 +02:00
parent da6200afc8
commit 10c548b010
5 changed files with 106 additions and 10 deletions
+31 -3
View File
@@ -213,10 +213,38 @@ services:
retries: 3
# -------------------------------------------------------------------
# Future services land here:
# - react-spa: front-end (static, served via nginx or Caddy)
# See ../docs/wiki/ for the platform architecture.
# spa — React + TypeScript single-page app for end-user operators.
# Built by git.dev.microservices.al/trm/spa's Gitea workflow.
#
# The image is nginx serving a static bundle. The bundle's runtime
# config (Directus URL, Processor WS URL, optional Google Maps key,
# env label) is read at first paint from /config.json — overridable
# via the volume mount below without rebuilding the image.
#
# Internal-only on the stack (expose: 80). The reverse proxy that
# fronts directus also routes the SPA at the public domain root.
# Same-origin is non-negotiable: the SPA's auth cookie + the
# processor's WebSocket upgrade both rely on browser-attached cookies
# that only flow within one origin.
# -------------------------------------------------------------------
spa:
image: git.dev.microservices.al/trm/spa:${SPA_TAG:-main}
expose:
- '80'
volumes:
# Override the baked-in dev config with the per-environment one.
# Operators copy spa-config.example.json to spa-config.json (or
# whatever ${SPA_CONFIG_FILE} points at) before first deploy and
# edit the URLs / env label / optional Google Maps key. Read-only
# mount — the container can't accidentally write to its own config.
- ${SPA_CONFIG_FILE:-./spa-config.json}:/usr/share/nginx/html/config.json:ro
restart: unless-stopped
healthcheck:
test: ['CMD-SHELL', 'wget -qO- http://localhost/ || exit 1']
interval: 30s
timeout: 5s
start_period: 5s
retries: 3
volumes:
redis-data: