A normal deploy no longer starts the livekit container (it would crashloop with
empty keys before provisioning). Enable with 'docker compose --profile sfu up -d'.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds the server side of scaling meetings past the ~5-peer mesh:
- config.js: LIVEKIT_URL/API_KEY/API_SECRET + LIVEKIT_ENABLED flag. All optional;
when unset the app keeps the built-in P2P mesh (fully additive, like push).
- routes.js: GET /api/meetings/config (tells the client sfu on/off + wss url) and
POST /api/meetings/token (mints a per-user, per-room LiveKit join token — hand-rolled
HS256 JWT like the FCM/APNs tokens, no new dependency; secret stays server-side).
- docker-compose.yml: optional livekit service (single-node, no Redis), keys injected
via LIVEKIT_KEYS from the same .env; media over published UDP 50000-50100 + TCP 7881,
signaling proxied by NPM.
- livekit.yaml + .env.example documented.
Client (mesh->LiveKit media swap, behind the flag) lands in phase 2.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- docker-compose: DOWNLOADS_DIR=/data/downloads so uploaded installers/latest.yml
survive image rebuilds (deploy.sh) instead of being wiped.
- DEPLOY.md: step-by-step for publishing a desktop release (build → upload the
3 feed files → verify) so the Download button + auto-update go live.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>