Last updated: December 10, 2025
The games platform at games.stephenharlow.com is a real-time multiplayer system supporting 10 different games, AI opponents, league rankings, and various play modes. This page covers how the platform is built.
Technology Stack
Frontend
- React - Component-based UI with TypeScript for type safety
- Socket.IO Client - Real-time bidirectional communication
- CSS Variables - Theme system supporting multiple visual themes
- Vite - Fast development server with hot module replacement
Backend
- Node.js + Express - HTTP server and API endpoints
- Socket.IO Server - WebSocket-based real-time communication
- TypeScript - Full type safety across the entire codebase
- MongoDB Atlas - Cloud database for persistence
- Mongoose ODM - Object modeling for MongoDB
Shared Library
- Game Logic - Core game rules shared between client and server
- AI Strategies - Computer player decision-making
- Type Definitions - Shared interfaces ensuring consistency
- Validation - Move validation used on both ends
Infrastructure
- Railway - Cloud hosting with CI/CD deployment
- Git-based Deployment - Push to main triggers automatic deployment
- Web Push API - Native browser notifications via VAPID
Real-Time Multiplayer Architecture
WebSocket Communication
All game interactions use Socket.IO for real-time bidirectional communication. This provides several advantages over traditional HTTP:
- Low latency: Persistent connections eliminate HTTP overhead
- Server push: Server can send updates immediately without polling
- Automatic reconnection: Socket.IO handles connection drops gracefully
- Room-based broadcasting: Efficiently send updates to specific game rooms
State Management
The server maintains authoritative game state:
┌─────────────────────────────────────────────────────────┐
│ SERVER │
│ ┌─────────────────────────────────────────────────┐ │
│ │ GameRoom Instance │ │
│ │ ┌──────────────┐ ┌──────────────────────────┐ │ │
│ │ │ Game State │ │ Player Manager │ │ │
│ │ │ - Cards │ │ - Active players │ │ │
│ │ │ - Scores │ │ - Spectators │ │ │
│ │ │ - Turn │ │ - Waiting queue │ │ │
│ │ └──────────────┘ └──────────────────────────┘ │ │
│ │ ┌──────────────┐ ┌──────────────────────────┐ │ │
│ │ │ Game Handler │ │ State Filter │ │ │
│ │ │ (per-game │ │ (hide opponent cards) │ │ │
│ │ │ logic) │ │ │ │ │
│ │ └──────────────┘ └──────────────────────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Client A │ │ Client B │ │ Client C │
│ (Player) │ │ (Player) │ │(Spectator)│
└──────────┘ └──────────┘ └──────────┘
State Filtering
Not all game state should be visible to all players. The StateFilter component ensures information hiding:
- Hidden cards: Opponent hand cards are never sent to other clients
- Deck composition: Remaining cards in deck are hidden
- Per-player views: Each client receives only information they should see
Optimistic Updates vs. Server Authority
The platform uses server-authoritative state with client prediction for responsiveness:
- Client sends action to server
- Server validates action against game rules
- If valid, server updates state and broadcasts to all clients
- Clients receive authoritative state update
This prevents cheating while maintaining responsive gameplay.
Game Room System
The GameRoom class is the core abstraction managing multiplayer games:
Room Lifecycle
- Creation: Room created with game type and settings
- Joining: Players join via unique room codes
- Game Start: Host starts when ready; game state initialized
- Gameplay: Players take turns; state synchronized
- Game End: Winner determined; stats recorded
- Cleanup: Room destroyed after inactivity
Player Status System
Players can have different statuses within a room:
| Status | Description | Can Play |
|---|---|---|
| Active | Currently participating in the game | Yes |
| Waiting | In queue to join when spot opens | No |
| Sitting Out | Temporarily paused participation | No |
| Spectating | Watching without playing | No |
Late Joining and Room Locking
Depending on game configuration:
- Players can join mid-game (some games support this)
- Rooms can be locked to prevent new players
- Waiting queue auto-promotes players when spots open
Game Handler Architecture
Each game type has its own handler implementing game-specific logic:
Factory Pattern
The GameHandlerFactory creates appropriate handlers based on game type:
GameHandlerFactory.create(gameType)
│
├── "gin-rummy" → GinRummyHandler
├── "scrabble" → ScrabbleHandler
├── "texas-holdem" → TexasHoldemHandler
├── "uno" → UnoHandler
├── "cribbage" → CribbageHandler
├── "trash" → TrashHandler
├── "war" → WarHandler
├── "solitaire" → SolitaireHandler
└── "pong" → PongHandler
Handler Responsibilities
- State initialization: Set up initial game state
- Move validation: Ensure moves are legal
- State transitions: Apply valid moves to state
- Win detection: Determine when game ends and who wins
- Scoring: Calculate points according to game rules
Game Registry
Each game registers its capabilities:
- Minimum and maximum players
- AI support availability
- Late joining allowed
- Sitting out support
- Spectator support
- Hot seat mode compatibility
AI System
The platform includes AI opponents for most games:
Strategy Architecture
Each game has a dedicated AI strategy class:
- GinRummyAIStrategy: Evaluates hand potential, tracks discards, optimizes meld formation
- ScrabbleAIStrategy: Exhaustive word finding, board position evaluation, difficulty scaling
- TexasHoldemAIStrategy: Hand strength calculation, pot odds, bluffing decisions
- UnoAIStrategy: Color tracking, action card timing, opponent hand size awareness
Difficulty Levels
| Level | Behavior |
|---|---|
| Easy | Random selection from valid moves; minimal strategy |
| Medium | Considers top options with some randomness; balanced play |
| Hard | Optimal play; always chooses best calculated move |
Deterministic AI
AI decisions use seeded random number generation:
- Same seed produces identical game sequences
- Enables reproducible testing and debugging
- Game replays work correctly with AI players
AI Scheduler
AI moves are scheduled with configurable delays:
- Prevents instant responses that feel unnatural
- Difficulty level affects thinking time
- Handles turn management for multiple AI players
League System
Competitive players can participate in ranked leagues:
ELO Rating System
The platform uses the ELO rating system, originally developed for chess:
Expected Score: E = 1 / (1 + 10^((opponent_rating - player_rating) / 400))
New Rating: R' = R + K × (actual_score - expected_score)
K-Factor: 32 (configurable)
ELO Properties
- Zero-sum: Points gained by winner equal points lost by loser
- Upset bonus: Beating higher-rated players yields more points
- Convergence: Ratings stabilize at true skill level over time
League Features
- Match Recording: Results tracked with timestamps
- Dispute Resolution: Players can dispute match results
- Statistics: Win rates, head-to-head records, rating history
- Leaderboards: Ranked by ELO per game type
- Tournaments: Bracket-based tournaments with seeding
Tournament System
- Bracket generation based on ELO seeding
- Single and double elimination formats
- Round management and scheduling
- Guest accounts for tournament-only participation
Special Features
Hot Seat Mode
Local multiplayer on a single device:
- No server connection required
- Game state managed entirely on client
- Privacy screens between turns
- AI can fill remaining slots
Voting System
Democratic mid-game rule changes:
- Any player can propose changes
- Majority vote required
- Room creator can veto/force-approve
- Changes take effect immediately
Push Notifications
Browser notifications when it's your turn:
- Web Push API with VAPID protocol
- Service worker handles background messages
- Works even when browser tab is closed
Theme System
Visual customization:
- Three themes: Classic, Dark, Purple
- CSS custom properties for easy theming
- Per-game theme compatibility tested
Pong: Real-Time Physics
Pong requires special handling for real-time gameplay:
Server-Side Physics
- 60 FPS game loop running on server
- Ball position, velocity, and acceleration calculated server-side
- Paddle physics with speed and spin effects
- Collision detection for walls and paddles
Synchronization
- State updates sent at regular intervals
- Sequence numbers prevent out-of-order updates
- Client interpolation smooths movement
- Server validates all paddle positions
Testing Infrastructure
Unit Tests
- ~1,000 Jest tests for game logic
- Card operations, move validation, scoring
- AI strategy correctness
- ELO calculations
Integration Tests
- ~400 server-side E2E tests
- Player join/leave flows
- Invalid move rejection
- WebSocket event handling
Visual/Accessibility Tests
- ~170 Playwright tests
- UI state verification
- WCAG accessibility compliance
- Theme rendering across games
- Responsive design testing
Quality Assurance
- Pre-commit hooks: Tests must pass before commits
- Pre-push hooks: Full accessibility suite runs before push
- No flaky tests: Root causes fixed, never skipped
- TypeScript strict mode: Maximum type safety
Accessibility
The platform is built with accessibility as a core requirement:
- Semantic HTML: Proper heading hierarchy, landmarks, lists
- ARIA labels: Screen reader descriptions for interactive elements
- Keyboard navigation: All features accessible without mouse
- Color contrast: WCAG AA compliance for text and controls
- Focus management: Visible focus indicators, logical tab order
- Automated testing: axe-core integration catches regressions
Deployment Pipeline
Development Workflow
Local Development
│
▼
┌─────────────────┐
│ npm run dev │ ← Runs client (Vite) + server concurrently
└─────────────────┘
│
▼
┌─────────────────┐
│ Run tests │ ← npm run build && npm test
└─────────────────┘
│
▼
┌─────────────────┐
│ Git commit │ ← Pre-commit hooks verify tests pass
└─────────────────┘
│
▼
┌─────────────────┐
│ Git push │ ← Pre-push hooks run accessibility tests
└─────────────────┘
│
▼
┌─────────────────┐
│ Railway CI/CD │ ← Auto-deploys on push to main
└─────────────────┘
Build Process
- Shared library compiled (TypeScript → JavaScript)
- Client built (React → static assets)
- Server compiled (TypeScript → JavaScript)
- Theme CSS generated
Code Statistics
| Component | Approximate Size | Notes |
|---|---|---|
| Shared Library | ~46,000 lines | Game logic, AI, types |
| Client | ~20,000+ lines | React components, styles |
| Server | ~172,000 lines | Handlers, services, API |
| Tests | ~1,500 tests | Jest + Playwright |
Future Roadmap
Planned features and improvements:
- Queue Play (Scrabble): Queue your next move while waiting for your turn
- Game Replays: Review completed games move-by-move
- Additional Games: More card and board games
- Mobile Apps: Native iOS/Android applications
- Tournament Automation: Scheduled tournaments with brackets
Related Articles
- Browse All Games - Try the games yourself
- Gaming Glossary - Learn technical and gaming terminology
- FAQ - Frequently asked questions about the platform
- About - Learn more about the developer
Want to play? Visit games.stephenharlow.com to experience the platform firsthand. All games are free to play!