Developer guide for working on LAN Games: environment variables, scripts, testing, hot-reload, and the new-game checklist. For high-level architecture, see Architecture. For the game-implementation contract, see Adding a New Game. Back to README.
All of these can live in .env at the repo root. The npm run dev and npm start scripts at the root source .env automatically; docker compose reads it through env_file.
| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
TCP port the server listens on (Docker host port maps to the same value) |
HOST |
0.0.0.0 |
Bind address; set to 127.0.0.1 to refuse LAN connections |
JWT_SECRET |
(server refuses to start without one) | JWT signing secret |
JWT_EXPIRES |
7d |
JWT token lifetime |
NODE_ENV |
(unset) | Set to development to suppress the "bound to all interfaces" startup warning |
Add a line to .env:
PORT=5050Then restart with npm run dev (or docker compose up). Everything follows automatically:
- The server binds to the new port and prints the right URLs at startup
- The client uses relative URLs, so opening
http://<host>:5050Just Works — Socket.io and/api/*traffic inherit the same origin - Docker maps the host port to the same value, so
http://localhost:5050works in either dev or containerised mode
No code changes, no rebuild.
npm start # run the server
npm run dev # run with nodemon (auto-restart on file changes)
npm test # run Jest test suite (server/test/)
npm run test:integration # integration tests (Express + Socket.io round-trips)
npm run lint # ESLint
npm run format:check # Prettier (verify)
npm run format:write # Prettier (auto-fix)
npm run reset-db # drop all tables and recreate schema
npm run reset-db:hard # delete the .db file entirely and recreate it
npm run screenshots # regenerate README screenshots (requires Playwright)cd server
npm install # required — devDependencies (jest, supertest, etc.) must be present
npm test # unit tests for every bundled game's game-logic
npm run test:integration # socket + persistence round-trip testsTests live in server/test/ (unit) and server/test/integration/ (integration). At the time of this README pass: 625 unit tests across the eight bundled games plus the framework interface, and 40 integration tests covering socket emission, REST state filtering, action-descriptor wiring, spectator mode, and game-lifecycle round-trips.
Note:
node_modules/is gitignored. If you skipnpm install, the unit suite still partially runs (tests that only use relative imports), but suites requiringsupertest,uuid, orjest-environment-jsdomwill fail to load silently. Always install dependencies before running tests.
The unit suite imports game-logic modules directly and never touches the network, database, or socket layer — making it fast and reliable. The integration suite spins up a real server, a real SQLite database, and real socket clients to verify full round-trips end-to-end.
After editing a JSON config file:
curl -X POST http://localhost:3000/api/games/types/monopoly/config/reload \
-H "Authorization: Bearer <token>"Only games created after the reload will use the new config. In-progress games carry their own embedded snapshot.
-
server/games/<name>/game-logic.js— implements all required interface methods; callsvalidateImplementationat the bottom -
server/games/<name>/config/settings.json— minimum viable config -
server/src/game-registry.js— one new line in theregistryobject - (optional)
client/js/games/<name>/renderer.js— visual renderer; self-registers viaGameRendererRegistry.register('<name>', …)at the bottom of the file - (optional) One
<script>tag inclient/index.htmlto load the renderer - (recommended) Implement
getActionDescriptorsif the renderer needs dynamic labels / enabled-state logic; seeaction-descriptors.md