Technical Architecture

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:

  1. Client sends action to server
  2. Server validates action against game rules
  3. If valid, server updates state and broadcasts to all clients
  4. 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

  1. Creation: Room created with game type and settings
  2. Joining: Players join via unique room codes
  3. Game Start: Host starts when ready; game state initialized
  4. Gameplay: Players take turns; state synchronized
  5. Game End: Winner determined; stats recorded
  6. 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

  1. Shared library compiled (TypeScript → JavaScript)
  2. Client built (React → static assets)
  3. Server compiled (TypeScript → JavaScript)
  4. 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

Want to play? Visit games.stephenharlow.com to experience the platform firsthand. All games are free to play!