This guide describes the high-level architecture of the Poker Engine: its layers, tech stack, data flows, and directory structure.
Layer Overview
┌─────────────────────────────────────────────────────────┐
│ CLIENTS │
│ React App (Lobby, Game, Profile) │ Admin Panel │
│ React Native Mobile App │ Developer API │
└─────────────────────┬───────────────────────────────────┘
│ HTTP / WebSocket
┌─────────────────────┴───────────────────────────────────┐
│ APPLICATION LAYER │
│ ┌─────────────┐ ┌──────────────┐ ┌───────────────┐ │
│ │ REST API │ │ Socket.io │ │ Middleware │ │
│ │ (Express) │ │ (Real-time) │ │ (Auth/Val) │ │
│ └─────────────┘ └──────────────┘ └───────────────┘ │
└─────────────────────┬───────────────────────────────────┘
│
┌─────────────────────┴───────────────────────────────────┐
│ SERVICE LAYER │
│ User │ Table │ Tournament │ Cashier │ Bonus │ Payment │
└─────────────────────┬───────────────────────────────────┘
│
┌─────────────────────┴───────────────────────────────────┐
│ GAME ENGINE │
│ Poker Table │ Hand Evaluator │ Betting │ State Machine │
│ Bot AI │ Turn Manager │ Pot/Rake│ Dealing Engine │
└─────────────────────┬───────────────────────────────────┘
│
┌─────────────────────┴───────────────────────────────────┐
│ DATA LAYER │
│ PostgreSQL (Prisma ORM) │ File Storage │
└─────────────────────────────────────────────────────────┘
Technology Stack
| Component | Technology | Purpose |
|---|---|---|
| Backend runtime | Node.js 20+ | Server execution |
| Language | TypeScript | Type safety |
| HTTP framework | Express | REST API routing |
| WebSocket | Socket.io | Real-time communication |
| ORM | Prisma | Database access |
| Database | PostgreSQL | Data persistence |
| Validation | Zod | Schema validation (API + env) |
| Authentication | JWT + bcrypt | Token-based auth |
| Testing | Vitest + fast-check | Unit, integration, property-based tests |
| Frontend | React + TypeScript | Web UI |
| Mobile | React Native | Mobile app |
| Styling | Tailwind CSS | UI styling |
| State management | Zustand | Frontend store |
| Error tracking | Sentry (optional) | Production error monitoring |
| Cache/pub-sub | Redis (optional) | Multi-instance support |
Directory Structure
poker-engine/
├── src/ # Backend source code
│ ├── index.ts # Application entry point
│ ├── app.ts # Express app setup
│ │
│ ├── api/ # REST API layer
│ │ ├── routes/ # Route handlers by domain
│ │ │ ├── auth.routes.ts
│ │ │ ├── user.routes.ts
│ │ │ ├── lobby.routes.ts
│ │ │ ├── tournament.routes.ts
│ │ │ ├── cashier.routes.ts
│ │ │ ├── analytics.routes.ts
│ │ │ ├── user/ # User sub-routes
│ │ │ ├── developer/ # Developer Integration API
│ │ │ └── admin/ # Admin-only routes
│ │ └── middleware/
│ │ ├── auth.ts # JWT authentication
│ │ ├── validation.ts # Zod-based request validation
│ │ ├── csrf.ts # CSRF protection
│ │ ├── error-handler.ts
│ │ └── ...
│ ├── core/ # Plugin system and hook registry
│ │ ├── plugins/
│ │ └── hooks/
│ │
│ ├── game/ # Poker game engine
│ │ ├── engine/ # Card, deck, dealing
│ │ │ ├── card.ts
│ │ │ ├── deck.ts
│ │ │ └── dealing-engine.ts
│ │ ├── hand-evaluator/ # Hand ranking per variant
│ │ │ ├── evaluator.ts # evaluate5CardHand, evaluate7CardHand
│ │ │ ├── evaluator-factory.ts # HandEvaluatorFactory
│ │ │ ├── low-evaluator.ts # Hi-Lo (8-or-better)
│ │ │ └── hand-rank.ts
│ │ ├── betting/ # Pot, rake, action validation
│ │ │ ├── pot.ts
│ │ │ ├── rake.ts
│ │ │ ├── action-validator.ts
│ │ │ ├── bet-validator.ts
│ │ │ └── betting-limit-utils.ts
│ │ ├── flow/ # Game state machine and hand phases
│ │ │ ├── state-machine.ts
│ │ │ ├── game-state.ts
│ │ │ ├── showdown.ts
│ │ │ ├── turn-manager.ts
│ │ │ ├── blinds.ts
│ │ │ ├── ante.ts
│ │ │ ├── action-timer.ts
│ │ │ ├── variant-state-config.ts
│ │ │ ├── stud-dealing.ts
│ │ │ └── mixed-game-engine.ts
│ │ ├── procedure/ # Deck procedure
│ │ ├── table/ # Table state, actions and game scheduler
│ │ ├── verification/ # Gameplay verification suite
│ │ ├── audit/ # Game-rule audit tests
│ │ ├── integration/ # Game-flow integration tests
│ │ └── bot/ # Bot AI system
│ │ ├── bot-player.ts
│ │ └── strategies/
│ │
│ ├── services/ # Business logic
│ │ ├── user.service.ts
│ │ ├── tournament.service.ts
│ │ ├── cashier-settings.service.ts
│ │ ├── payment-gateway.service.ts
│ │ ├── game-settings.service.ts # DB-backed game config
│ │ └── ...
│ │
│ ├── websocket/ # WebSocket layer
│ │ ├── index.ts # Socket.io setup + connection handling
│ │ ├── connection-handler.ts
│ │ ├── table-manager.ts # In-memory game state
│ │ ├── typed-socket.ts # Type-safe emit wrapper
│ │ ├── game-events/ # Event handlers (actions, chat, spectators…)
│ │ ├── schemas/ # Zod schemas for client events
│ │ ├── pipeline/ # Event processing pipeline
│ │ │ ├── game-pipeline.ts
│ │ │ ├── lobby-pipeline.ts
│ │ │ ├── state-sync-pipeline.ts
│ │ │ ├── idempotency-stage.ts
│ │ │ ├── rate-limit-stage.ts
│ │ │ ├── guaranteed-delivery-stage.ts
│ │ │ └── tracing-stage.ts
│ │ └── types/
│ │ └── events.ts # Single source of truth for WS event types
│ │
│ ├── models/ # Shared types
│ │ ├── types.ts
│ │ ├── schemas.ts # Zod request schemas
│ │ └── errors.ts # PokerError, ValidationError, etc.
│ │
│ ├── config/
│ │ ├── env-schema.ts # Zod schema for environment variables
│ │ ├── env.ts # Validated env config
│ │ └── database.ts # Prisma client singleton
│ │
│ ├── cache/ # Redis cache and settings cache
│ ├── observability/ # Metrics
│ ├── load/ # Load-test harness
│ │
│ └── utils/ # Shared utilities
│ ├── logger.ts # Pino-based logger
│ └── ...
│
├── client/ # React web frontend
│ └── src/
│ ├── components/ # Reusable UI components
│ ├── pages/ # Route pages
│ ├── hooks/ # Custom hooks (useGameSocket, useLobbySocket…)
│ ├── store/ # Zustand state stores
│ ├── api/ # Typed API client (fetch wrappers)
│ └── lib/
│ └── socket.ts # Socket.io singleton
│
├── prisma/
│ ├── schema.prisma # Database schema
│ ├── migrations/ # Migration history
│ ├── seed.ts # Development seed data
│ └── setup.ts # Production/staging bootstrap (npm run db:setup)
│
├── packages/ # Shared monorepo packages
│ ├── shared/ # Types, stores and hooks shared between web and mobile
│ ├── mobile/ # React Native mobile app
│ └── vendor/ # Local dependency replacements
│
├── plugins/ # Bundled plugins
├── tests/ # Cross-package tests (most tests sit next to their source)
│
└── docs/ # Documentation
Request Flow — REST API
Client HTTP Request
│
▼
Express Router (src/api/routes/)
│
▼
Middleware chain:
- HTTPS redirect (production, applied globally)
- JWT authentication (authenticate middleware)
- Zod request validation (validateBody / validateQuery / validateParams)
- Rate limiting and CSRF verification (per route)
│
▼
Route Handler
│
▼
Service Layer (src/services/)
│
▼
Prisma ORM
│
▼
PostgreSQL
│
▼
JSON response { success: true, data: ... }
or error handler → { success: false, error: { code, message } }
Request Flow — WebSocket Events
Client WebSocket Event (e.g., "player_action")
│
▼
Socket.io middleware (JWT auth)
│
▼
Event Pipeline (src/websocket/pipeline/game-pipeline.ts), wrapped in tracing stages:
1. Validation stage — verify request data and authentication
2. Authorization stage — check the player may perform the action
3. Rate limit stage — prevent flooding
4. Idempotency stage — deduplicate retried events
5. Logging stage
6. Completion stage — record processing time
│
▼
Event handler (src/websocket/game-events/)
│
▼
Table Manager (in-memory game state)
│
▼
Game Engine (src/game/)
│
▼
Prisma (persist results)
│
▼
Broadcast: "table_state" sent to each player and spectator socket at the table
Configuration Architecture
Environment variables (src/config/env-schema.ts) hold infrastructure settings and secrets only:
- Database URL, JWT secrets, CSRF secret, CORS origins
- Redis URL, Sentry DSN, encryption key
Everything else lives in the database and is managed via the Admin Panel:
- Game settings (rake, blinds, buy-in limits, timeouts)
- Feature flags (maintenance mode, registration, KYC)
- SMTP configuration
- Payment provider settings
- Bot scheduling
- Bonus rules
This allows runtime configuration changes without redeployment.
Import Conventions
// 1. Node/external packages
import express from 'express';
import { z } from 'zod';
// 2. Internal modules (use relative paths with .js extension)
import { prisma } from '../../config/database.js';
import { createLogger } from '../../utils/logger.js';
// 3. Local module types
import type { PlayerAction } from './types.js';
Note: .js extensions are required in imports due to ESM configuration, even for .ts source files.
Back to Developer Guide