Since Jul 2025 · poker.soljt.ch · Personal project
Poker
Real-time multiplayer Texas Hold'em, built from scratch. Join a lobby, sit at a live table against friends or bots, and keep your chips between sessions.
Take a seat ↗Source on GitHub ↗Made for desktop
- Frontend
- React · TypeScript
- Realtime
- Flask-SocketIO
- Data
- PostgreSQL · Redis
- Bots
- Heuristic · Gemini
- Deploy
- Docker Compose · nginx
The game
Full hold'em rules: preflop, flop, turn and river, with side pots, all-ins and showdowns. Every player's table stays in sync over a WebSocket, and new players queue for a seat without interrupting the hand in progress.
- An inaction timer folds a player after 45 seconds and removes them from the game.
- Players who go broke are offered a rebuy before the next hand.
- Every hand is written to an append-only log with the full action history, board and hole cards.
A hand, end to end
- LobbyCreate or join a live game
- SeatQueued if a hand is running
- DealEach player gets only their own cards
- BetFour rounds, 45 s to act
- ShowdownSide pots split, ties broken
- SettleChips saved, hand logged
Architecture
Hard parts
Nobody sees your cards
Game state is serialised separately for each player, so a client only ever receives its own hole cards.
Getting the chips right
The hand evaluator and pot logic are covered by tests: ranking, comparison, tie-breaking, side pots and edge cases like the ace-low straight.
Bots behind one interface
Any decision engine can take a seat without touching the game loop. The heuristic bot weighs made-hand strength against draw potential, pot odds, kickers and preflop bonuses. The Gemini bot sends the full game state to the API and parses a structured JSON action, falling back to a random move if the call fails.
Security
JWTs live in httpOnly cookies with CSRF checks on every state-changing request. Auth endpoints are rate-limited through Redis, and admin routes sit behind role-based access control.
Next
In progress: a reinforcement-learning agent to fill empty seats.