# Architecture Diagram ## System Overview ``` ┌────────────────────────────────────────────────────────────────┐ │ CLIENT APPLICATIONS │ │ │ │ ┌───────────────────┐ ┌───────────────────┐ │ │ │ Settlers Game │ │ Chat Room App │ │ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │ │ │ Game UI │ │ │ │ Chat UI │ │ │ │ │ │ - Board │ │ │ │ - Messages │ │ │ │ │ │ - Actions │ │ │ │ - Input │ │ │ │ │ └─────────────┘ │ │ └─────────────┘ │ │ │ │ │ │ │ │ │ │ Uses: │ │ Uses: │ │ │ │ ┌──────────────────────────────────────────┐ │ │ │ │ │ REUSABLE COMPONENTS │ │ │ │ │ │ • MediaControl (Video/Audio UI) │ │ │ │ │ │ • MediaAgent (WebRTC Signaling) │ │ │ │ │ │ • PlayerList (Participant Display) │ │ │ │ │ └──────────────────────────────────────────┘ │ │ │ └───────────────────┘ └───────────────────┘ │ └────────────────────────────────────────────────────────────────┘ │ │ WebSocket ↓ ┌────────────────────────────────────────────────────────────────┐ │ SERVER LAYERS │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ APPLICATION LAYER (App-Specific) │ │ │ │ │ │ │ │ Settlers Game │ Chat App │ │ │ │ ┌────────────────────┐ │ ┌───────────────────┐ │ │ │ │ │ GameSessionMeta │ │ │ ChatSessionMeta │ │ │ │ │ │ - color │ │ │ - status │ │ │ │ │ │ - player │ │ │ - messageCount │ │ │ │ │ │ - resources │ │ │ - customStatus │ │ │ │ │ └────────────────────┘ │ └───────────────────┘ │ │ │ │ │ │ │ │ │ ┌────────────────────┐ │ ┌───────────────────┐ │ │ │ │ │ GameRoomMeta │ │ │ ChatRoomMeta │ │ │ │ │ │ - players │ │ │ - messages │ │ │ │ │ │ - board setup │ │ │ - topic │ │ │ │ │ │ - game rules │ │ │ - pinnedMessages │ │ │ │ │ └────────────────────┘ │ └───────────────────┘ │ │ │ │ │ │ │ │ Message Handlers: │ Message Handlers: │ │ │ │ • set color │ • send message │ │ │ │ • place settlement │ • set status │ │ │ │ • trade resources │ • pin message │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ │ │ uses metadata │ │ ↓ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ ADAPTER LAYER (Optional Compatibility) │ │ │ │ │ │ │ │ Proxy Handlers: │ │ │ │ • session.color ─────→ session.metadata.color │ │ │ │ • session.player ────→ session.metadata.player │ │ │ │ • game.players ──────→ game.metadata.players │ │ │ │ │ │ │ │ Enables backward compatibility without code changes │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ │ │ wraps │ │ ↓ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ INFRASTRUCTURE LAYER (Reusable Framework) │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ │ │ Session Management │ │ │ │ │ │ • BaseSession (id, name, ws, live, has_media) │ │ │ │ │ │ • Session (+ metadata field) │ │ │ │ │ │ • createBaseSession() │ │ │ │ │ │ • updateSessionActivity() │ │ │ │ │ │ • isSessionActive() │ │ │ │ │ │ • getSessionName() │ │ │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ │ │ Room Management │ │ │ │ │ │ • BaseRoom (id, name, sessions, state) │ │ │ │ │ │ • Room (+ metadata field) │ │ │ │ │ │ • getParticipants() │ │ │ │ │ │ • getActiveSessions() │ │ │ │ │ │ • cleanupInactiveSessions() │ │ │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ │ │ WebRTC Signaling │ │ │ │ │ │ • join() - Add peer to registry │ │ │ │ │ │ • part() - Remove peer from registry │ │ │ │ │ │ • relayICECandidate() - Forward ICE │ │ │ │ │ │ • relaySessionDescription() - Forward SDP │ │ │ │ │ │ • PeerRegistry - Track peer connections │ │ │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ │ │ WebSocket Handling │ │ │ │ │ │ • Connection management │ │ │ │ │ │ • Automatic reconnection │ │ │ │ │ │ • Message routing │ │ │ │ │ │ • Keep-alive pings │ │ │ │ │ └────────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ │ └────────────────────────────────────────────────────────────────┘ ``` ## Data Flow: Setting User Name ``` ┌─────────────┐ │ CLIENT │ └─────────────┘ │ │ 1. User types name "Alice" │ ↓ sendJsonMessage({ type: "set", field: "name", value: "Alice" }) │ │ WebSocket ↓ ┌─────────────────────────────────────────┐ │ SERVER │ │ │ │ Infrastructure Layer: │ │ ├─ Receive message │ │ ├─ Find session by WebSocket │ │ └─ Route to handler │ │ │ │ Application Layer: │ │ ├─ session.name = "Alice" │ │ └─ Broadcast to all sessions │ │ │ │ Infrastructure Layer: │ │ └─ getParticipants(room.sessions) │ │ └─ Returns: [ │ │ { session_id, name: "Alice", │ │ live: true, has_media: true } │ │ ] │ └─────────────────────────────────────────┘ │ │ Broadcast update ↓ ┌─────────────┐ │ ALL CLIENTS│ └─────────────┘ │ │ Receive participants update ↓ PlayerList rerenders with "Alice" shown ``` ## Data Flow: Joining Video Call ``` ┌─────────────┐ │ CLIENT │ └─────────────┘ │ │ 1. MediaAgent mounts │ 2. Gets user media (camera/mic) │ ↓ sendJsonMessage({ type: "join", data: { has_media: true } }) │ │ WebSocket ↓ ┌──────────────────────────────────────────┐ │ SERVER │ │ │ │ Infrastructure Layer (WebRTC): │ │ ├─ join(peers, session, { has_media }) │ │ │ │ │ │ For each existing peer: │ │ │ ├─ Send addPeer to existing peer │ │ │ │ { peer_id: "Alice", │ │ │ │ peer_name: "Alice", │ │ │ │ has_media: true, │ │ │ │ should_create_offer: false } │ │ │ │ │ │ │ └─ Send addPeer to new peer │ │ │ { peer_id: "Bob", │ │ │ peer_name: "Bob", │ │ │ has_media: true, │ │ │ should_create_offer: true } │ │ │ │ │ └─ Add to peer registry: │ │ peers["Alice"] = { │ │ ws, has_media: true │ │ } │ │ │ │ └─ Send join_status: │ │ { type: "join_status", │ │ status: "Joined" } │ └──────────────────────────────────────────┘ │ │ Relay messages ↓ ┌─────────────┐ │ ALL CLIENTS│ └─────────────┘ │ │ Each client: ├─ Creates RTCPeerConnection ├─ Adds local media tracks ├─ Creates offer/answer └─ Exchanges ICE candidates │ ↓ Peer-to-peer video/audio flows ``` ## Data Flow: Game-Specific Action ``` ┌─────────────┐ │ GAME CLIENT│ └─────────────┘ │ │ Player clicks "Blue" color │ ↓ sendJsonMessage({ type: "set", field: "color", value: "blue" }) │ │ WebSocket ↓ ┌───────────────────────────────────────────┐ │ SERVER │ │ │ │ Infrastructure Layer: │ │ ├─ Route message to app handler │ │ └─ session object available │ │ │ │ Adapter Layer (optional): │ │ └─ Wraps session with proxy │ │ │ │ Application Layer (Game): │ │ ├─ setPlayerColor(game, session, "blue")│ │ │ ├─ Validate color available │ │ │ ├─ session.color = "blue" │ ← Direct access │ │ │ (or session.metadata.color) │ ← New arch │ │ ├─ session.player = gamePlayer │ │ │ └─ Update game.metadata.players │ │ │ │ │ └─ Broadcast update: │ │ participants: [ │ │ { │ │ ...baseParticipant, │ ← Infrastructure │ color: "blue" │ ← App-specific │ } │ │ ] │ └───────────────────────────────────────────┘ │ │ Broadcast ↓ ┌─────────────┐ │ ALL CLIENTS│ └─────────────┘ │ │ Update UI ↓ PlayerList shows "Alice" with blue color ``` ## Metadata Access Patterns ### Without Adapter (New Code) ```typescript // Explicit metadata access const color = session.metadata?.color; session.metadata = { ...session.metadata, color: 'blue' }; const players = room.metadata.players; room.metadata.players['blue'] = newPlayer; ``` ### With Adapter (Backward Compatible) ```typescript // Same as before - adapter proxies to metadata const color = session.color; session.color = 'blue'; const players = room.players; room.players['blue'] = newPlayer; ``` Both work! Adapter allows gradual migration. ## Reusability Layers ``` Application A (Settlers) Application B (Chat) Application C (Whiteboard) │ │ │ ├── GameSessionMeta ├── ChatSessionMeta ├── WhiteboardSessionMeta │ - color │ - status │ - cursorColor │ - player │ - messageCount │ - selectedTool │ │ │ └─────────────┬────────────┴────────────────────────┘ │ │ All apps extend base types ↓ ┌─────────────────────────────────┐ │ INFRASTRUCTURE (Shared) │ │ • Session │ │ • Room │ │ • MediaControl (WebRTC) │ │ • getParticipants() │ │ • Session management │ └─────────────────────────────────┘ ↑ Single implementation, works for all apps! ``` ## Summary This architecture provides: ✅ **Clean separation** between infrastructure and application ✅ **Type-safe metadata** for app-specific data ✅ **Reusable components** that work across applications ✅ **Backward compatibility** via adapter layer ✅ **Clear data flows** from client to server to all clients ✅ **Proven patterns** ready for production use Any new application can plug into the infrastructure and get: - Multi-user rooms - WebSocket connection management - WebRTC video/audio signaling - Participant tracking - UI components (MediaControl) All for free! Just define your metadata types and business logic.