Architecture
Repository layoutβ
/
βββ back/ β PartyKit backend (Durable Object)
β βββ game.ts β GameSession class (main entry point)
β βββ types.ts β exported types & interfaces
β βββ constants.ts β word lists, category prompts
β βββ utils.ts β pure utility functions (shuffle, pseudonym gen)
β βββ scoring.ts β pure scoring functions
β βββ timer.ts β TimerManager class
βββ front/ β Astro + React frontend
β βββ src/
β βββ lib/socket.ts β PartySocket factory
β βββ types/events.ts β shared event payload types
β βββ stores/
β β βββ hostStore.ts
β β βββ participantStore.ts
β βββ hooks/
β β βββ useHostSocket.ts
β β βββ useParticipantSocket.ts
β βββ components/
β βββ host/
β βββ participant/
βββ docs-site/ β Docusaurus docs
βββ proxy-worker/
β βββ index.ts β Cloudflare Worker: routes /docs/* to docs Pages
βββ partykit.json β PartyKit config + KV binding
βββ package.json β root: partykit + partysocket
βββ docker-compose.yml β Mode B: full-stack with PartyKit in Docker
Runtime communicationβ
Browser (Host) Browser (Participant)
β β
β PartySocket ws β PartySocket ws
βΌ βΌ
ββββββββββββββββββββββββββββββββββββββββββ
β PartyKit Durable Object β
β room = 4-digit session code β
β β
β this.room.storage β game state β
β this.room.broadcast β fan-out msgs β
ββββββββββββββββββββ¬ββββββββββββββββββββββ
β KV write
βΌ
Cloudflare KV
SOMMELIER_HOSTS
key: host:{TANNIC-FALCON}
Durable Object lifecycleβ
| Hook | Called when | What we do |
|---|---|---|
onStart() | DO wakes from eviction | Restore SavedState from storage |
onConnect(ws) | Client opens WebSocket | Register connection (host or participant) |
onMessage(ws, msg) | Message arrives | Parse { type }, dispatch to handler |
alarm() | Timer alarm fires | Auto-reveal current question |
onClose(ws) | Client disconnects | Mark participant offline; detect host drop |
Host vs participant socket flowβ
Host joins β sends rejoin_host { hostId } on socket open β server validates hostId against stored value β sends host:state_snapshot
Participant joins β sends join_session { code } β server creates participant, issues rejoinToken, broadcasts lobby:updated
Participant rejoins β localStorage { rejoinToken, code } detected on mount β sends rejoin_session { rejoinToken } β server sends participant:state_snapshot
Docker vs PartyKit devβ
| Mode A (partykit dev) | Mode B (docker) | |
|---|---|---|
| Backend | npx partykit dev on :1999 | partykit Docker container on :1999 |
| Frontend | npm run dev on :4321 | nginx on :4321 |
| Docs | cd docs-site && npm start | Docker container on :3002 |
| Requires Docker | β | β |
| Hot-reload backend | β | β |