This document describes the architecture of a web-based implementation of the Secret Hitler board game. The system consists of a client-side SolidJS application that communicates with a game server via WebSockets. The game supports multiple roles including Liberals, Fascists, Hitler, and optional special roles like Communist, Anarchist, Monarchist, Capitalist, and Centrist.
graph TB
subgraph "Client Side"
B[Board Interface<br/>/board]
P[Player Interface<br/>/player]
C[Console Interface<br/>/console]
end
subgraph "Communication Layer"
WS[WebSocket Connection]
end
subgraph "Server Side"
GS[Game Server]
GM[Game Manager]
GST[Game State]
end
B <--> WS
P <--> WS
C <--> WS
WS <--> GS
GS --> GM
GM --> GST
- Frontend Framework: SolidJS with TypeScript
- Build Tool: Vite
- Routing: @solidjs/router
- State Management: SolidJS signals and stores
- Communication: WebSockets (websocket-ts library)
- Validation: Zod schema validation
- Styling: CSS Modules
- Animation: Motion One (@motionone/solid)
The client application is organized into three main interfaces:
- Board Interface (
/board) - Displays the game state for all players to see - Player Interface (
/player) - Individual player's private view and controls - Console Interface (
/console) - Administrative or debugging interface
src/
├── assets/ # Game images and sounds
├── board/ # Board interface components
│ └── modals/ # Board-specific modal dialogs
├── components/ # Shared components
├── dm/ # Domain models and types
├── pages/ # Route page components
├── player/ # Player interface components
└── util/ # Utility functions
BoardApp.tsx- Main board application containerBoardContent.tsx- Game board display logicPlayerRail.tsx- Display of all playersPolicyTracker.tsx- Tracks enacted policies- Various modal components for game phases
PlayerApp.tsx- Main player application containerPrompt.tsx- Handles player action promptsCardSelector.tsx- Policy card selection UIRoleTab.tsx- Displays player's secret roleLobby.tsx- Pre-game lobby interface
sequenceDiagram
participant C as Client
participant S as Server
Note over C,S: Connection Phase
C->>S: Connect to WebSocket
C->>S: JoinAsPlayer/JoinAsBoard
S->>C: Update (GameState)
Note over C,S: Game Phase
C->>S: PlayerAction/BoardAction
S->>C: Update (GameState)
Note over C,S: Error Handling
C->>S: Invalid Action
S->>C: Error Message
-
Connection Messages
CreateGame- Create a new game with optionsJoinAsPlayer- Join as a player with nameJoinAsBoard- Join as the board displayLeaveGame- Leave the current game
-
Game Control Messages
StartGame- Start the game (from lobby)EndGame- End the current game
-
Action Messages
PlayerAction- Player-specific actionsBoardAction- Board-specific actions
-
State Updates
{ type: 'update', state: GameState }
-
Error Messages
{ type: 'error', error: string }
The game state is managed through a discriminated union pattern with different state types:
graph TD
GS[GameState]
GS --> CON[Connecting]
GS --> LOB[Lobby]
GS --> BRD[Board]
GS --> PLY[Player]
GS --> END[Ended]
GS --> ERR[Error]
BRD --> BP[Board Prompt]
PLY --> PP[Player Prompt]
-
GameState - Root state containing:
game_id: Unique game identifiername: Player name (null for board)players: Array of public player informationstate: Current game phase state
-
BoardState - Public game state visible to all:
- Election tracker
- Policy cards (Liberal, Fascist, Communist)
- Draw pile count
- Presidential turn order
- Last government
- Current prompt
-
PlayerState - Private player state:
- Player name
- Secret role
- Investigation results
- Current prompt
stateDiagram-v2
[*] --> Connecting
Connecting --> Lobby: Players Join
Connecting --> Error: Connection Failed
Lobby --> Board: Start Game
Lobby --> Player: Start Game
Board --> Board: Game Actions
Player --> Player: Game Actions
Board --> Ended: Game Over
Player --> Ended: Game Over
Ended --> [*]
Error --> [*]
graph LR
N[Night Phase] --> E[Election]
E --> LS[Legislative Session]
LS --> CR[Card Reveal]
CR --> EA[Executive Action]
EA --> N
CR --> GO[Game Over]
EndNightRound- Acknowledge night phaseChoosePlayer- Select another playerCastVote- Vote Ja or NeinDiscard- Discard a policy cardVetoAgenda- Request veto (Chancellor)AcceptVeto/RejectVeto- President's veto response- Special actions for variant roles
EndVoting- Complete voting phaseEndCardReveal- Complete policy revealEndExecutiveAction- Complete executive actionEndLegislativeSession- Complete legislation- Special actions for variant game modes
<Router>
<Route path="/board" component={BoardPage} />
<Route path="/player" component={PlayerPage} />
<Route path="/console" component={ConsolePage} />
</Router>- Board:
/board?game={gameId} - Player:
/player?game={gameId}&name={playerName}
- State Isolation: Player states are isolated - each player only receives their own private information
- Action Validation: All actions are validated server-side
- Game ID: Uses validated 4-character game IDs
- No Authentication: Relies on game ID and player name for access
- Sound effects for game events
- Background music support
- Audio context management for browser compatibility
- Animated transitions using Motion One
- Confetti effects for game victories
- Responsive design for various screen sizes
- QR code generation for easy game sharing
The system supports multiple game variants through configurable options:
- Communist expansion
- Monarchist role
- Anarchist role
- Capitalist role
- Centrist role
- Extensive use of TypeScript
- Zod schemas for runtime validation
- Discriminated unions for state management
- Separation of concerns (UI, state, communication)
- Modular component structure
- Shared utilities and hooks
- Efficient WebSocket reconnection with backoff
- Lazy loading of assets
- Optimized build configuration
Based on the TODO file, planned improvements include:
- Anarchist role interactions
- Enhanced Communist session UI
- Radicalisation reveal UI
- Confession UI improvements
- Better support for 10+ players
- Console autoplay feature
- Hitler zone warnings
- Improved president/chancellor icons