Watch intelligence play.
ChessSim is an AI-powered chess simulation & entertainment platform. It is not another chess-playing site, not a Chess.com / Lichess clone. Two AI agents sit across the board, compete and reason — and ChessSim turns their game into something worth watching and understanding.
ChessSim explores how artificial intelligence behaves under rules, competition and strategy. Chess is the cleanest window into machine reasoning: a finite board, perfect information, and an endless supply of decisions that can be explained, evaluated and narrated.
v0.6.0 — Story-first, source-visible reading. Story chapters and Analysis share one board position, Demo Stories use White/Black rather than model-brand attribution, and every match exposes its game source, narrative source and verification status.
-
/chess960— Chess960 explorer: shuffle all 960 legal back ranks and launch the exact position in the Arena -
Complete Chess960 rules, including king-to-rook UCI castling and proper final king/rook castled squares
-
Variant-aware Stockfish, LLM prompts, replay narratives and PGN headers
-
/arena— AI Chess Arena: pick two agents, watch them fight live with engine evaluation, commentary, pause/pace control and PGN export -
LLM agents (DeepSeek, GPT, Claude, Qwen, Gemini) play through the ChessSim API when their keys are configured; without a key they honestly fall back to a local heuristic (clearly labelled — never fake)
-
Stockfish agents at configurable depth + greedy / random baseline bots
-
Finished games become full replays (Story Mode, bilingual narrative, engine analysis) built on the fly
-
Every move creates an immediate live story beat; users can explicitly opt in to asynchronous LLM refinement for important moments without pausing the game
-
Terminal positions skip unnecessary engine analysis, and a hard timeout automatically recovers a non-responsive Stockfish worker
-
Public persistence remains closed until a reviewed Neon data model, retention policy and authorization flow are approved
-
Three curated Demo Story matches:
/match/deepseek-vs-gpt(#001),/match/claude-vs-qwen(#002),/match/deepseek-vs-claude(#003) -
Browser-based Stockfish (WASM, Web Worker): live evaluation, recommended move, mistake / brilliant-move detection, full-game analysis with caching
-
A render-ready
MatchStory/NarrativeMomentmodel with move importance levels 0–5 and 4–8 meaningful moments per match -
Three synchronized narrative layers: what happened, why it matters and the story
-
Explicit Demo Story / Verified AI Match / Live Fallback provenance
-
White-perspective Stockfish scores and correct before-move best-move comparison
No accounts. Database persistence and LLM refinement are optional; the Arena, Stockfish, live template story and local replay all run with zero configuration.
Simulate → Analyze → Narrate → Render
- Simulate — the Arena runs real games: LLM models (with API keys) and the actual Stockfish engine play move by move in the browser.
- Analyze — Stockfish provides bounded evaluation, candidate moves and tactical signals.
- Narrate — ChessSim turns only the important moves into story beats and chapters.
- Render — the same structured data drives the synchronized board, story, evaluation and future voice/video surfaces.
ChessSim may eventually expand into:
- AI Agent competition
- AI benchmarks
- Simulation environments
- AI-generated sports and entertainment content
For now, the focus stays strictly on chess.
Requirements: Node.js 18.18+ (tested on Node 24).
npm install
npm run devOpen http://localhost:3000.
Other commands:
npm run build # production build
npm run start # serve the production build
npm run validate:pgn # verify all demo PGNs are legal & annotations align
npm run test:stockfish # Node smoke test of the vendored Stockfish engine
npm run test:simulation # arena layer tests (heuristics, LLM parsing, builders)The Arena works fully without any keys (Stockfish + baseline bots). To let
real language models play, set the provider keys as environment variables —
locally in .env.local, or in Vercel under Settings → Environment Variables:
DEEPSEEK_API_KEY=sk-... # DeepSeek → deepseek-chat
OPENAI_API_KEY=sk-... # OpenAI → gpt-4o
ANTHROPIC_API_KEY=sk-... # Anthropic → claude-3-7-sonnet-latest
GEMINI_API_KEY=... # Google → gemini-2.0-flash
DASHSCOPE_API_KEY=sk-... # Alibaba → qwen-maxAgents without a configured key are clearly labelled in the Arena and fall back to the local heuristic — the platform never fakes an LLM move.
Public model generation and match writes are closed by default. The existing Supabase adapter is legacy code and is not evidence of a production database. If durable dynamic publishing is approved, use reviewed Neon Postgres storage with retention and moderation rules. A first authorized real match may instead ship as one controlled static data record.
Server gates: CHESSSIM_LLM_RUNS_ENABLED, CHESSSIM_MATCH_WRITES_ENABLED and
CHESSSIM_GENERATION_TOKEN. Do not expose the token to the browser.
src/
├── app/ # Next.js App Router pages + API routes
│ ├── page.tsx # / homepage
│ ├── matches/page.tsx # /matches
│ ├── arena/page.tsx # /arena live simulation
│ ├── match/[slug]/page.tsx # /match/<slug> replay
│ ├── saved/[shareId]/page.tsx # /saved/<id> persisted replay
│ ├── about/page.tsx # /about
│ ├── updates/page.tsx # /updates
│ ├── api/agents/route.ts # agent registry + key status
│ ├── api/llm/move/route.ts # LLM move selection (server proxy)
│ ├── api/llm/narrate/route.ts # LLM narrative generation
│ ├── api/matches/route.ts # validated match persistence
│ ├── layout.tsx # root layout (nav + footer)
│ └── globals.css # Tailwind + design tokens
├── components/ # UI components
│ ├── ArenaSim.tsx # arena: setup, live game, result, replay, PGN
│ ├── BoardReplay.tsx # replay orchestrator (board, engine, panels, lang)
│ ├── BoardThumbnail.tsx # static mini board
│ ├── EvaluationBar.tsx # vertical eval bar with White/Black labels
│ ├── EvalSparkline.tsx # evaluation curve across the whole game
│ ├── MoveInfo.tsx # synchronized 3-layer story + engine truth panel
│ ├── MoveTimeline.tsx # move list with engine classifications
│ ├── StoryMode.tsx # six-chapter story mode (bilingual)
│ ├── MatchCard.tsx # featured + compact match cards
│ ├── Navbar.tsx / Footer.tsx / AgentAvatar.tsx / Badge.tsx
├── hooks/
│ ├── useStockfish.ts # lazy WASM Stockfish worker hook
│ └── useSimulation.ts # arena game loop (LLM / engine / heuristic moves)
├── data/ # curated matches (local TypeScript)
│ ├── agents.ts # player/agent registry + AI profiles
│ ├── matches/*.ts # one seed per match (PGN + annotations + narrative)
│ └── index.ts # builds Match objects, lookup helpers
├── lib/
│ ├── llm/ # server-side LLM layer
│ │ ├── providers.ts # DeepSeek / OpenAI / Anthropic / Gemini / DashScope
│ │ └── prompt.ts # move & narrative prompts + parsing (pure, tested)
│ ├── simulation/ # arena layer (client + server safe)
│ │ ├── agents.ts # agent registry (LLM / engine / heuristic)
│ │ ├── heuristics.ts # greedy + random baseline bots
│ │ └── build-match.ts # live game → replayable Match + auto narrative
│ ├── types.ts # Match / Move / Agent / Evaluation data model
│ ├── narrative.ts # chapter → render-ready story-moment builder
│ ├── build.ts # PGN expansion + annotation merge + eval curve
│ ├── stockfish.ts # UCI protocol client (worker-agnostic, testable)
│ ├── engine-cache.ts # localStorage cache for engine results
│ ├── classify.ts # move classifications (brilliant, blunder, …)
│ ├── eval.ts # evaluation formatting & win-probability math
│ └── chess-ui.ts # board helpers (king square, swing descriptions)
└── public/engine/ # vendored Stockfish (WASM + asm.js fallback)
scripts/
├── validate-pgn.ts # PGN legality + annotation alignment check
├── test-stockfish.mjs # engine smoke test (Node, vm-based worker shim)
└── test-simulation.ts # arena tests (heuristics, LLM parsing, builders)
- Match — id, slug, title, provenance, white/black players,
status, result, PGN, summary (EN/ZH), narrative (six chapters), positions
(FEN per ply), moves and a synchronized
MatchStory. - Move — ply, moveNumber, SAN, from/to, resulting FEN, evaluation (cp or mate), classification (book → brilliant), commentary (EN/ZH), reasoning, alternative, narrative tags (turning-point, sacrifice, …).
- NarrativeMoment — id,
startPly,endPly,anchorPly, exact FEN/SAN, importance, chapter, narrative layers and render-safe turning-point flags. - Agent — id, name, model, provider, description, avatar accent, plus an AI player profile: playing style, strength, strategy.
Matches are authored as seeds: a legal PGN plus sparse checkpoints
(evaluation curve) and move annotations keyed by "<moveNumber><color>"
(e.g. "17b"). src/lib/build.ts expands the PGN with chess.js, validates
legality, interpolates the evaluation curve and merges annotations — throwing
a descriptive error if any move is illegal.
At runtime, the browser loads Stockfish (WASM) in a Web Worker via
src/lib/stockfish.ts. The engine provides bounded analysis for a defined
search configuration (evaluation and recommended move); the authored narrative
explains those signals without treating them as infallible truth.
- Lightweight — minimal dependencies, no backend, no database
- Content first — the game and its story are the interface
- Simple over perfect; working prototype over feature completeness
- Editorial, high-end, chess-native aesthetic (black / white / grey / warm paper; low-saturation wooden board)
Next.js (App Router) · TypeScript · Tailwind CSS · chess.js · react-chessboard · ready to deploy on Vercel.
All three curated matches are Demo Stories: they use legal example games to demonstrate the experience and were not generated by the named models. Live matches earn the Verified AI Match label only when no named LLM was replaced by an offline fallback.