# mirza-mohammad24/scribblitz architecture

> Architecture diagram of the GitHub repository mirza-mohammad24/scribblitz, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-02). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/mirza-mohammad24/scribblitz
- Repository: https://github.com/mirza-mohammad24/scribblitz

## Overview

#### Purpose and Runtime Topology
Scribblitz is a multiplayer drawing-and-guessing game. It is a pnpm/Turborepo monorepo with three Node.js services: Next.js browser UI, Express/Socket.IO authoritative game server, and BullMQ AI worker. Shared contracts prevent client/server event drift.
- `apps/web/src/app/page.tsx`
- `apps/game-server/src/server.ts`
- `apps/worker/src/index.ts`

#### Client Application and UI Control
The Next.js app renders the home, lobby, and active-game experiences. `ArenaOrchestrator` is the top-level game UI router: it consumes socket-driven state from Zustand and selects lobby versus arena views; arena components isolate canvas, chat, HUD, leaderboard, overlays, emotes, and voice controls.
- `apps/web/src/components/Arena/ArenaOrchestrator.tsx`
- `apps/web/src/store/gameStore.ts`
- `apps/web/src/hooks/useGameSocket.ts`

#### Authoritative Room and Game Lifecycle
The game server owns ephemeral room membership, host assignment, player sessions, reconnect grace periods, and all gameplay transitions. `RoomManager` manages in-memory rooms; `GameFSM` permits the lobby → word selection → drawing → round end/game end lifecycle. Socket handlers enforce role/state guards before invoking this domain layer.
- `apps/game-server/src/rooms/RoomManager.ts`
- `apps/game-server/src/rooms/Room.ts`
- `apps/game-server/src/fsm/GameFSM.ts`

#### Socket Boundary and Shared Contracts
Socket.IO is the primary control and realtime data plane between browser and game server. Handler groups separate lobby/configuration, gameplay, messages/guessing, canvas, voice, and emotes. Incoming payloads are runtime-validated with Zod; types, event names, game states, and constants are workspace-owned.
- `apps/game-server/src/socket/handlers/gameHandlers.ts`
- `packages/types/src/events.ts`
- `packages/validation/src/game.ts`

#### Drawing Synchronization and Recovery
The drawer locally buffers pointer operations and sends batched canvas events; the server immediately relays them to peers and persists/retrieves history through Redis. Canvas logic stays client-local, while server handlers enforce drawer and round permissions. Redis Streams support reconnect/late-join replay but do not store authoritative room state.
- `apps/web/src/hooks/useCanvasDrawing.ts`
- `apps/game-server/src/socket/handlers/canvasHandlers.ts`
- `apps/game-server/src/lib/redis.ts`

#### External Services and Background Work
Redis backs both canvas streams and BullMQ. Hosts request themed words through the game server; it enqueues work and the worker calls Google Gemini, then validates/filter results before completion is reflected in room configuration. Voice is separate: the game server mints scoped LiveKit tokens, while browsers carry audio directly over WebRTC to LiveKit.
- `apps/game-server/src/services/aiQueue.ts`
- `apps/worker/src/index.ts`
- `apps/game-server/src/services/voiceService.ts`

#### Persistence and Deployment Boundaries
PostgreSQL/Prisma provides schema and migrations for persistent entities such as users and game results, though active games remain process-local. Docker Compose provisions local dependencies and production services; each runtime has a Dockerfile. The architecture is currently single-instance because rooms are not distributed via a Socket.IO Redis adapter.
- `prisma/schema.prisma`
- `docker-compose.yml`
- `docker-compose.prod.yml`

Main entry points: [`apps/game-server/src/socket/handlers/gameHandlers.ts`](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/socket/handlers/gameHandlers.ts) (Socket handlers), [`apps/web/src/components/Arena/ArenaOrchestrator.tsx`](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/web/src/components/Arena/ArenaOrchestrator.tsx) (Arena UI), [`apps/web/src/hooks/useGameSocket.ts`](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/web/src/hooks/useGameSocket.ts) (Game socket hook), [`apps/worker/src/index.ts`](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/worker/src/index.ts) (AI worker)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_client["Browser client"]
  node_ui["Arena UI<br/>Next.js UI"]
  node_store["Game state store<br/>Zustand<br/>[gameStore.ts]"]
  node_socket_hook["Game socket hook<br/>Socket.IO client<br/>[useGameSocket.ts]"]
  node_drawing["Canvas drawing<br/>client canvas"]
end

subgraph group_server["Game server"]
  node_socket_handlers["Socket handlers<br/>Socket.IO boundary<br/>[gameHandlers.ts]"]
  node_room_manager["Room manager<br/>in-memory rooms<br/>[RoomManager.ts]"]
  node_room["Room<br/>game aggregate<br/>[Room.ts]"]
  node_game_fsm["Game lifecycle<br/>FSM<br/>[GameFSM.ts]"]
  node_canvas_handlers["Canvas handlers<br/>realtime relay<br/>[canvasHandlers.ts]"]
  node_redis_client["Redis integration<br/>Redis client<br/>[redis.ts]"]
  node_ai_queue["Word AI queue<br/>BullMQ producer<br/>[aiQueue.ts]"]
  node_voice_service["Voice token service<br/>LiveKit auth<br/>[voiceService.ts]"]
end

subgraph group_async["Background &amp; external"]
  node_worker["AI worker<br/>BullMQ worker<br/>[index.ts]"]
  node_gemini{{"Google Gemini<br/>AI API"}}
  node_livekit{{"LiveKit<br/>voice platform"}}
end

subgraph group_data["Data &amp; contracts"]
  node_redis[("Redis<br/>streams and queues")]
  node_contracts["Shared event contracts<br/>workspace types<br/>[events.ts]"]
  node_validation["Payload validation<br/>Zod schemas<br/>[game.ts]"]
  node_postgres[("PostgreSQL / Prisma<br/>persistent data<br/>[schema.prisma]")]
  node_deployment["Docker Compose<br/>deployment<br/>[docker-compose.yml]"]
end

node_ui -->|"renders state from"| node_store
node_ui -->|"connects through"| node_socket_hook
node_socket_hook -->|"Socket.IO events"| node_socket_handlers
node_socket_hook -->|"updates"| node_store
node_drawing -->|"batched canvas events"| node_canvas_handlers
node_socket_handlers -->|"authorized commands"| node_room_manager
node_room_manager -->|"manages"| node_room
node_room -->|"advances with"| node_game_fsm
node_canvas_handlers -->|"persist and replay strokes"| node_redis_client
node_redis_client -->|"canvas streams"| node_redis
node_socket_handlers -->|"themed word request"| node_ai_queue
node_ai_queue -->|"enqueue job"| node_redis
node_worker -->|"consume jobs"| node_redis
node_worker -->|"generate words"| node_gemini
node_socket_handlers -->|"voice token request"| node_voice_service
node_voice_service -->|"mint scoped token"| node_livekit
node_ui -->|"direct WebRTC audio"| node_livekit
node_socket_handlers -->|"uses events"| node_contracts
node_socket_handlers -->|"validates payloads"| node_validation
node_socket_handlers -->|"records persistent results"| node_postgres
node_deployment -.->|"provisions"| node_redis
node_deployment -.->|"provisions"| node_postgres

click node_ui "https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/web/src/components/Arena/ArenaOrchestrator.tsx"
click node_store "https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/web/src/store/gameStore.ts"
click node_socket_hook "https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/web/src/hooks/useGameSocket.ts"
click node_drawing "https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/web/src/hooks/useCanvasDrawing.ts"
click node_socket_handlers "https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/socket/handlers/gameHandlers.ts"
click node_room_manager "https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/rooms/RoomManager.ts"
click node_room "https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/rooms/Room.ts"
click node_game_fsm "https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/fsm/GameFSM.ts"
click node_canvas_handlers "https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/socket/handlers/canvasHandlers.ts"
click node_redis_client "https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/lib/redis.ts"
click node_ai_queue "https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/services/aiQueue.ts"
click node_voice_service "https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/services/voiceService.ts"
click node_worker "https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/worker/src/index.ts"
click node_contracts "https://github.com/mirza-mohammad24/scribblitz/blob/main/packages/types/src/events.ts"
click node_validation "https://github.com/mirza-mohammad24/scribblitz/blob/main/packages/validation/src/game.ts"
click node_postgres "https://github.com/mirza-mohammad24/scribblitz/blob/main/prisma/schema.prisma"
click node_deployment "https://github.com/mirza-mohammad24/scribblitz/blob/main/docker-compose.yml"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_ui,node_store,node_socket_hook,node_drawing toneBlue
class node_socket_handlers,node_room_manager,node_room,node_game_fsm,node_canvas_handlers,node_redis_client,node_ai_queue,node_voice_service toneAmber
class node_worker,node_gemini,node_livekit toneMint
class node_redis,node_contracts,node_validation,node_postgres,node_deployment toneRose
```

## Components

### Browser client

- [Arena UI](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/web/src/components/Arena/ArenaOrchestrator.tsx): Next.js UI · Routes home, lobby, and active-game views. · `apps/web/src/components/Arena/ArenaOrchestrator.tsx`
- [Game state store](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/web/src/store/gameStore.ts): Zustand · Socket-driven client game state. · `apps/web/src/store/gameStore.ts`
- [Game socket hook](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/web/src/hooks/useGameSocket.ts): Socket.IO client · `apps/web/src/hooks/useGameSocket.ts`
- [Canvas drawing](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/web/src/hooks/useCanvasDrawing.ts): client canvas · Buffers and batches local pointer operations. · `apps/web/src/hooks/useCanvasDrawing.ts`

### Game server

- [Socket handlers](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/socket/handlers/gameHandlers.ts): Socket.IO boundary · Guards and validates lobby, game, message, canvas, voice, and emote events. · `apps/game-server/src/socket/handlers/gameHandlers.ts`
- [Room manager](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/rooms/RoomManager.ts): in-memory rooms · Owns membership, hosts, sessions, and reconnect grace periods. · `apps/game-server/src/rooms/RoomManager.ts`
- [Room](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/rooms/Room.ts): game aggregate · Process-local active game and player state. · `apps/game-server/src/rooms/Room.ts`
- [Game lifecycle](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/fsm/GameFSM.ts): FSM · Controls lobby through game-end transitions. · `apps/game-server/src/fsm/GameFSM.ts`
- [Canvas handlers](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/socket/handlers/canvasHandlers.ts): realtime relay · Authorizes drawer events and serves replay. · `apps/game-server/src/socket/handlers/canvasHandlers.ts`
- [Redis integration](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/lib/redis.ts): Redis client · Stores canvas streams and connects BullMQ. · `apps/game-server/src/lib/redis.ts`
- [Word AI queue](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/services/aiQueue.ts): BullMQ producer · Enqueues themed-word requests from hosts. · `apps/game-server/src/services/aiQueue.ts`
- [Voice token service](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/game-server/src/services/voiceService.ts): LiveKit auth · Mints scoped browser voice tokens. · `apps/game-server/src/services/voiceService.ts`

### Background & external

- [AI worker](https://github.com/mirza-mohammad24/scribblitz/blob/main/apps/worker/src/index.ts): BullMQ worker · Generates, validates, and filters word results. · `apps/worker/src/index.ts`
- **Google Gemini**: AI API
- **LiveKit**: voice platform · Browsers send audio directly over WebRTC.

### Data & contracts

- **Redis**: streams and queues · Canvas replay storage and BullMQ backend.
- [Shared event contracts](https://github.com/mirza-mohammad24/scribblitz/blob/main/packages/types/src/events.ts): workspace types · Shared event names, states, and constants. · `packages/types/src/events.ts`
- [Payload validation](https://github.com/mirza-mohammad24/scribblitz/blob/main/packages/validation/src/game.ts): Zod schemas · `packages/validation/src/game.ts`
- [PostgreSQL / Prisma](https://github.com/mirza-mohammad24/scribblitz/blob/main/prisma/schema.prisma): persistent data · Persists users and game results, not active rooms. · `prisma/schema.prisma`
- [Docker Compose](https://github.com/mirza-mohammad24/scribblitz/blob/main/docker-compose.yml): deployment · Provisions local and production service dependencies. · `docker-compose.yml`

## Connections

- Arena UI → Game state store: renders state from
- Arena UI → Game socket hook: connects through
- Game socket hook → Socket handlers: Socket.IO events
- Game socket hook → Game state store: updates
- Canvas drawing → Canvas handlers: batched canvas events
- Socket handlers → Room manager: authorized commands
- Room manager → Room: manages
- Room → Game lifecycle: advances with
- Canvas handlers → Redis integration: persist and replay strokes
- Redis integration → Redis: canvas streams
- Socket handlers → Word AI queue: themed word request
- Word AI queue → Redis: enqueue job
- AI worker → Redis: consume jobs
- AI worker → Google Gemini: generate words
- Socket handlers → Voice token service: voice token request
- Voice token service → LiveKit: mint scoped token
- Arena UI → LiveKit: direct WebRTC audio
- Socket handlers → Shared event contracts: uses events
- Socket handlers → Payload validation: validates payloads
- Socket handlers → PostgreSQL / Prisma: records persistent results
- Docker Compose → Redis: provisions
- Docker Compose → PostgreSQL / Prisma: provisions
