Two bugs that surfaced on first real deploy:
1. SPA was COPYed to /app/apps/api/public but server.ts looks at
/app/apps/web/dist (relative to apps/api/dist via fileURLToPath).
Static handler returned 404 for /. Move the COPY to match.
2. The aliased external network (`umbrel_main` -> name:
umbrel_main_network) wasn't attaching in Portainer Stacks → DNS
lookup of datum_datum_1 fails with ENOTFOUND. Use the network's
real name directly as the alias to avoid any Portainer indirection.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two production-blocker bugs from the first deploy:
1. Static SPA never served — Dockerfile copied apps/web/dist into
apps/api/public, but server.ts default static dir resolves to
apps/web/dist. Mismatch meant every route fell through to Express'
bare 404 ("Cannot GET /"). Aligning Dockerfile to the default path.
2. DNS for the Datum container name failed (getaddrinfo ENOTFOUND
datum_datum_1) — gashboard's Docker DNS doesn't reliably alias
external-network container names across compose stacks. Switch the
default DATUM_URL to the container's known IP on umbrel_main_network
(10.21.0.11, captured during earlier diagnostics). If the IP changes
the user can override DATUM_URL in env. If gashboard isn't actually
joined to umbrel_main_network, the next failure will be a much more
diagnostic ECONNREFUSED instead of an opaque ENOTFOUND.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
User-facing port unified at 1337 — vibes-aligned and easier to remember
than 8080/8420. Updates: api default PORT, .env.example, docker-compose
mapping (1337:1337), healthcheck target, Dockerfile EXPOSE, Vite dev
proxy.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per the original brief: 1337 vibe. Internal port stays 8080 (matches
PORT env default and Express trust-proxy assumptions); just remaps the
host port from the 8420 placeholder to 1337.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two-app pnpm workspace for the gashboard (mining dashboard) project:
@gashboard/api (Express 5 + TS) and @gashboard/web (Vue 3 + Vite + TS).
Shared tsconfig.base.json. Multi-stage Dockerfile (node:22.12-alpine,
non-root, healthchecked) and docker-compose.yml ready to deploy as a
Portainer Stack on Umbrel — joins umbrel_main_network so it can reach
the Datum container directly. .env.example documents every var; README
covers the Portainer deploy flow and the security posture.
Note: Dockerfile has a TODO marker to SHA256-pin the base image before
shipping to production.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>