Playground Lab: Full-Stack Browser Games Platform
02/22/2026 · 10 min read
A production-oriented game and tools platform: decoupled Next.js + FastAPI services, account-aware gameplay, and extensible module boundaries.
Next.jsFastAPIMongoDBDockerChessWordleArchitecture



Project Intent
Playground Lab is a real product baseline, not just a demo collection. It ships personalized Wordle, full Chess modes, tools, leaderboards, and account-aware flows with explicit trust boundaries, operational controls, and deployment-ready infrastructure. Public project reference: lab.xmoravec.com.
- Build a feature-rich platform where games and tools can be added without architectural rewrites.
- Separate frontend UX concerns from backend domain logic and persistence while keeping contracts explicit.
- Preserve product velocity without sacrificing production habits: startup checks, observability, and security controls.
Architecture Snapshot
- • Decoupled runtime architecture: Next.js frontend (Vercel) + FastAPI backend (Railway) + MongoDB Atlas + Cloudflare DNS/edge.
- • Docker-first monorepo split by responsibility (`frontend/`, `backend/`, `docker/`, `docs/`) with production-like local orchestration.
- • Backend layering by concern (`api`, `services`, `schemas`, `core`) with fail-fast startup lifecycle and index/data initialization.
- • Frontend App Router with typed contracts and authenticated route-handler proxies for account-sensitive actions.
- • Internal trust boundary: internal auth headers for server-to-server flows, plus explicit admin role + admin-mode gates.
Shipped Feature Set
- • Personalized Wordle state and history, controlled hint behavior, and dictionary fallback metadata when source loading fails.
- • Complete Chess module with multiplayer, self-play, bot levels, invitation flow, persisted match state, and server-authoritative clocks.
- • Public Wordle Solver tool and dedicated tools surface for future module growth.
- • Rules-based Wordle leaderboard endpoint and global leaderboard UI.
- • Rate limiting with transparent response headers and retry hints for client-side debuggability.
- • Deterministic startup/status reporting to avoid partially healthy runtime boot states.
Implementation Examples
Reusable code surfaces mirror the style used in project previews and deeper technical pages.
chess-bot-minimax.py
1def evaluate_board(*, board: Any, bot_color: bool) -> int:
2 if board.is_checkmate():
3 return -100_000 if board.turn == bot_color else 100_000
4 if board.is_stalemate() or board.is_insufficient_material() or board.can_claim_draw():
5 return 0
6
7 score = 0
8 piece_map = board.piece_map()
9 for piece in piece_map.values():
10 value = PIECE_VALUES.get(piece.piece_type, 0)
11 if piece.color == bot_color:
12 score += value
13 else:
14 score -= value
15 return score
16
17
18def minimax(*, board: Any, depth: int, alpha: int, beta: int, maximizing: bool, bot_color: bool) -> int:
19 if depth <= 0 or board.is_game_over(claim_draw=True):
20 return evaluate_board(board=board, bot_color=bot_color)
21
22 ordered_moves = order_moves(board, list(board.legal_moves))
23 if maximizing:
24 best_value = -1_000_000
25 for move in ordered_moves:
26 board.push(move)
27 value = minimax(board=board, depth=depth - 1, alpha=alpha, beta=beta, maximizing=False, bot_color=bot_color)
28 board.pop()
29 best_value = max(best_value, value)
30 alpha = max(alpha, value)
31 if beta <= alpha:
32 break
33 return best_value
34
35 best_value = 1_000_000
36 for move in ordered_moves:
37 board.push(move)
38 value = minimax(board=board, depth=depth - 1, alpha=alpha, beta=beta, maximizing=True, bot_color=bot_color)
39 board.pop()
40 best_value = min(best_value, value)
41 beta = min(beta, value)
42 if beta <= alpha:
43 break
44 return best_valuewordle-ranked-dictionary-loader.py
1@lru_cache(maxsize=1)
2def _load_ranked_words() -> tuple[list[str], str, bool, str | None]:
3 try:
4 ranked = top_n_list("en", EXTENDED_POOL_SIZE * 3)
5 except Exception as error: # noqa: BLE001
6 logger.warning("wordfreq top_n_list failed; using fallback list error=%s", error)
7 return _fallback_result(type(error).__name__)
8
9 normalized = _normalize_words(ranked)
10 if not normalized:
11 logger.warning("wordfreq produced no valid 5-letter words; using fallback list")
12 return _fallback_result("empty-wordfreq-result")
13
14 return normalized, "wordfreq", False, NoneCurrent Focus
- • Expand game/tool catalog beyond the currently seeded baseline while preserving module boundaries.
- • Increase automated contract and integration coverage around identity, multiplayer flows, and rate-limit behavior.
- • Evolve multiplayer responsiveness with incremental real-time transport upgrades.