Open Party Lab is a TypeScript npm-workspace monorepo for local browser party games.
apps/serveris the authoritative Socket.IO server. It owns rooms, players, round timing, gameplay rules, scoring, and lifecycle transitions.apps/hostis the shared-screen Phaser application. It renders the lobby, game select flow, QR join overlay, scoreboards, and game host scenes.apps/controlleris the React phone UI. It renders the player controller for the selected game and sends typed input to the server.
packages/protocol: event names, client/server event payloads, and shared DTOspackages/game-core: game manifests, layout keys, round phase helpers, and shared gameplay contractspackages/ui-kit: shared UI tokenspackages/utils: generic utilities
- The server is the single source of truth.
- Controllers send intent; they do not decide outcomes.
- Host scenes render state; they do not own game rules.
- Protocol types are the contract between all apps.
- New games should live in optional game repos and expose only the documented package entrypoints.
- Host creates a room through
room:create. - Server returns a room code and join URL.
- Host displays the room code and QR overlay.
- Phones join through the controller app.
- Host selects a game from the available catalog.
- Server starts and advances the round lifecycle.
- Controller inputs flow through
game:input. - Server broadcasts
game:stateorgame:patch. - Host and controllers render the latest public state.
- Server publishes scoreboard updates.
Room and round phases are shared across games:
lobbygame_selectedround_introcountdownplayinglockedresultscoreboardfinished
Game-specific state should fit inside this lifecycle unless there is a strong reason to extend the platform.
Main registry files:
config/known-games.jsonscripts/local-games.mjsapps/server/src/game-engine/gameRegistry.tsapps/host/src/games/registry.tsapps/controller/src/controller-ui/games/registry.tsx
npm run games:sync-local generates optional registry imports from the local repos it finds. Missing optional game repos are normal and must not break dev, typecheck, or build.