XMoravec
Project

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
Playground Lab chess match with board, clocks, and move history
Playground Lab Wordle game interface with personalized progress
Playground Lab chess interface with active game state

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_value

wordle-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, None

Current 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.