Hosting
Local Compose services and the preview deployment on the development server.
The App Router web app, legacy web app, docs, and API run as containers. Expo is distributed through app-store builds and has no server container.
Local Compose
docker compose up web legacy docs api postgres| Service | Default host port |
|---|---|
| App Router web | 3002 |
| Legacy web | 3000 |
| Docs | 3001 |
| API | 8080 |
| Postgres | 5432 |
Compose loads an optional root .env. The web and docs images receive public
environment variables at build time because Next.js inlines them into browser
bundles.
Preview deployment
scripts/deploy/preview.sh archives a commit, builds the service images, and
starts the statshub-preview Compose project. Containers bind to loopback;
Caddy publishes the generated hostnames.
Set PREVIEW_WEB_HOST and PREVIEW_LEGACY_HOST in
~/.config/statshub/preview-hosts.env when the box has stable DNS names. This
small file is separate from the secret-bearing preview.env, and is loaded by
both manual and timer-driven deployments.
Required production-style values include:
PREVIEW_DB_URLfor a populated Postgres databasePREVIEW_API_ENV_FILEfor API credentialsPREVIEW_WEB_ENV_FILEfor App Router runtime credentials and CMS prerenderingPREVIEW_LEGACY_ENV_FILEfor legacy runtime credentialsPREVIEW_APIV2_CURSOR_SECRETwith at least 32 bytes
Run:
pnpm deploy:preview
pnpm deploy:preview:status
pnpm deploy:preview:logs
pnpm deploy:preview:downThe deployer prints the active URLs and updates the preview links in the root README. Do not copy hostnames or loopback ports into docs; they are allocated from the current machine and service list.
Automatic deployment
The systemd timer runs scripts/deploy/preview-on-push.sh, which watches
origin/main and deploys each new commit once. It loads secrets from
~/.config/statshub/preview.env by default and uses a file lock to prevent
overlapping deployments.
A failed SHA is recorded and is not retried on every timer tick. Push a new
commit or run the watcher with --force after fixing local infrastructure.
The timer's branch is deployment configuration, not a statement about the branch you should develop on. Follow the current repository Git instructions before pushing or releasing.