scoreboardtools/docker-compose.yml
Ashraf Shafiq 9169bea79f Scaffold real-time SSBU scoreboard PWA
pnpm monorepo with three workspaces:
- @sbt/shared: zod ScoreboardState + WebSocket protocol (single source of truth)
- @sbt/server: Fastify REST + raw ws WebSocket + Drizzle/Postgres, run via tsx
- @sbt/web: React + Vite + Tailwind installable PWA

Real-time core: the WebSocket server holds authoritative per-board state in
memory, broadcasts to all clients (editors + OBS overlays) instantly, and
debounces Postgres saves (~750ms). One useScoreboardSync hook powers the editor,
the no-login co-edit control page, and the read-only OBS overlay.

Includes email+password auth (JWT cookie), scoreboard CRUD, logo upload,
customizable scorebug (characters/stocks/score/subtitles/callout/side-swap/theme),
Docker Compose + Caddy/nginx deploy configs, and docs/PLAN.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 00:09:27 -04:00

38 lines
1.0 KiB
YAML

services:
db:
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
POSTGRES_DB: ${POSTGRES_DB:-scoreboardtools}
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U postgres']
interval: 5s
timeout: 5s
retries: 5
restart: unless-stopped
server:
build: .
environment:
DATABASE_URL: postgres://postgres:${POSTGRES_PASSWORD:-postgres}@db:5432/${POSTGRES_DB:-scoreboardtools}
JWT_SECRET: ${JWT_SECRET:?set JWT_SECRET in .env}
COOKIE_SECURE: ${COOKIE_SECURE:-true}
UPLOAD_DIR: /data/uploads
PORT: '3000'
volumes:
- uploads:/data/uploads
depends_on:
db:
condition: service_healthy
# Bind to localhost only — your reverse proxy (nginx/Caddy) terminates TLS and
# forwards to this. Drop the 127.0.0.1 prefix only if exposing directly.
ports:
- '127.0.0.1:3000:3000'
restart: unless-stopped
volumes:
db-data:
uploads: