WebSocket relay server for the multiplayer quiz. Handles room management, player connections, and message relay between host and players. All state is held in memory (no database).
cd server
npm install
node server.jsThe server starts on port 8080 (or PORT env variable). Health check: GET http://localhost:8080/health
To connect from the client, set WS_URL in your local quiz-config.js:
const WS_URL = 'ws://localhost:8080';-
Install the Fly CLI: https://fly.io/docs/flyctl/install/
-
Sign up / log in:
fly auth signup # or: fly auth login -
Launch the app (from the
server/directory):cd server fly launchThis creates the app on Fly.io using the existing
fly.tomlandDockerfile. Note:fly launchcreates 2 machines by default for high availability. Scale down to 1 for the free tier:fly scale count 1 --app qlash-server
-
Add the
FLY_API_TOKENsecret to your GitHub repository for automated deploys:fly tokens create deploy -x 999999h
Copy the token and add it as
FLY_API_TOKENin GitHub repo Settings > Secrets > Actions. -
Add the
WS_URLsecret to GitHub (used by the build pipeline to inject into the client):- Value:
wss://qlash-server.fly.dev(or your custom domain) - Add as
WS_URLin GitHub repo Settings > Secrets > Actions.
- Value:
cd server
fly deployPushes to main that change files in server/ automatically trigger deployment via .github/workflows/deploy-server.yml.
- Single Fly.io machine in
fra(Frankfurt) auto_stop_machines = "stop": machine sleeps when idle (no active connections), saving free-tier hoursauto_start_machines = true: machine wakes on incoming request (~2-3s cold start)- In-memory state is lost when machine sleeps, but rooms auto-expire after 2 hours anyway
- Rooms are cleaned up when the host terminates the quiz or after 2 hours of inactivity
- Host disconnect grace period: 5 minutes before the room is terminated
- Ping/pong heartbeat every 30 seconds to detect dead connections