# Overlay Manager & Player List Implementation Plan > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** Refactor the OBS overlay from a monolithic single-file design to a modular state-machine architecture, fix the audio restart bug, add a player list component, and handle all new shard-based WebSocket events. **Architecture:** Central `OverlayManager` state machine coordinates registered components (room code display, audio controller, player list) through explicit lifecycle transitions. WebSocket client routes events to the manager. Components implement a standard `activate`/`deactivate`/`update` interface. **Tech Stack:** Vanilla JS (ES modules), no build step, loaded via ` ``` **Step 6: Verify in browser** 1. Open the HTML file in a browser 2. Open DevTools console — should see no import errors 3. Open controls panel — should see all existing settings plus new Player List and Overlay Manager sections 4. Type a code in First/Second Line inputs, click Update — room code animation should play with audio 5. Check `window.__overlay.manager.state` — should be `'lobby'` 6. Click Hide Display — should transition to `'idle'` and stop everything **Step 7: Commit** ```bash git add optimized-controls.html git commit -m "feat: integrate module system, add player list + dashboard DOM" ``` --- ## Task 8: End-to-End Verification & Polish **Files:** - Possibly modify: any of the above files for bug fixes **Step 1: Test the full WebSocket flow** If you have access to a running Game Picker API instance: 1. Connect via the overlay's Connection Settings 2. Verify `Connected` status 3. Add a game with a room code in the Game Picker 4. Verify: room code appears, audio plays, player list shows empty slots 5. If shard monitor is running, verify players populate the list as they join 6. When game starts: verify everything hides 7. Add another game: verify full reset and clean restart If no API instance is available, test manually: 1. Open DevTools console 2. Run: `window.__overlay.manager.handleEvent('game.added', { session: { id: 1 }, game: { room_code: 'ABCD', title: 'Test Game', max_players: 6 } })` 3. Verify: room code displays "AB" / "CD", audio plays, 6 empty player slots appear 4. Run: `window.__overlay.manager.handleEvent('lobby.player-joined', { players: ['Alice'], playerCount: 1, maxPlayers: 6, playerName: 'Alice' })` 5. Verify: first slot fills with "Alice" 6. Run: `window.__overlay.manager.handleEvent('game.started', { playerCount: 1, players: ['Alice'] })` 7. Verify: everything hides 8. Run the `game.added` event again — verify audio restarts cleanly **Step 2: Test overrides** 1. Set Room Code override to "Force Show" 2. Verify it stays visible even when state transitions to `idle` 3. Set Audio override to "Force Hide" 4. Trigger a lobby — verify room code and player list appear but audio does not play 5. Reset all overrides to "Auto" **Step 3: Test edge cases** - Rapid `game.added` events (new code while animation is running) - `room.disconnected` during lobby - `session.ended` during lobby - Player list with 0 maxPlayers (should default to 8) - Player list disabled in settings **Step 4: Fix any issues found** Address bugs discovered during testing. **Step 5: Final commit** ```bash git add -A git commit -m "fix: address issues found during end-to-end testing" ``` --- ## Summary of Changes | File | Action | Purpose | |------|--------|---------| | `js/state-manager.js` | Create | OverlayManager state machine | | `js/websocket-client.js` | Create | Extracted WebSocket auth/connect/events | | `js/room-code-display.js` | Create | Extracted room code animation component | | `js/audio-controller.js` | Create | Extracted audio lifecycle (fixes restart bug) | | `js/player-list.js` | Create | New player slot list component | | `js/controls.js` | Create | Settings bindings + debug dashboard | | `optimized-controls.html` | Modify | Add player list/dashboard DOM + CSS, replace inline JS with module bootstrap |