Scan any Lichess or Chess.com player's online games and see their actual opening repertoire β frequency, win rate, weak spots, and gaps vs. curated theory.
Everything runs client-side in your browser. No account, no server, no database. Games stream straight from the platform APIs, classification happens in a Web Worker, and the most recent scan is cached locally via IndexedDB so a refresh doesn't lose your work.
π Live app: https://openingscanner.com
- Live streaming scan of up to 2000 games from Lichess (NDJSON) or Chess.com (monthly archives), newest-first, cancelable mid-stream.
- Full ECO classification against the Lichess chess-openings database (~3000+ entries, EPD-keyed so transpositions merge).
- Interactive repertoire dashboard: grouped by family, drill into variants, board preview with arrow-key navigation, continuation tree, per-position results (W/D/L, avg opponent Elo).
- Weak spots β openings and variations where the player scores the worst.
- Gap analysis β curated openings the player barely touches; scoped to the selected family when drilling in.
- Exports β raw games PGN (filtered to the current variation) or a study-ready repertoire PGN with every continuation as a nested variation.
- URL-as-state via
nuqsso every scan is shareable and bookmarkable. - Local persistence (Dexie/IndexedDB) β refresh keeps the last scan.
- i18n β 13 languages out of the box (EN, ES, FR, DE, IT, PT-BR, NL, PL, TR, RU, UK, JA, ZH-CN).
ScanFormwrites filter state to the URL.useScannerspawns a module Worker (workers/scanner.worker.ts) and talks to it via Comlink.- The worker picks a streamer based on platform:
lib/sources/lichess.tsβ NDJSON fromhttps://lichess.org/api/games/user/:namewith server-side filtering.lib/sources/chesscom.tsβ walks monthly archives from newest to oldest, client-side filtering.
- Each game is classified by
classifyByEco(lib/catalog/eco-classify.ts), which replays up to 24 plies through chess.js, computing an EPD at each step and keeping the deepest ECO entry that matches. RepertoireAccumulatoraggregates per-opening stats + a per-opening move tree (player's own continuation past the ECO match point, so transpositions share the same subtree).- Progress events ship to the main thread every 25 games; final
RepertoireStatsis returned when the generator ends and cached to IndexedDB.
Zero server state. There are no API routes and no backend. pnpm build produces a fully static SPA-ish Next.js app.
- Next.js 16 (App Router) Β· React 19
- Tailwind CSS v4 + shadcn/ui
- chess.js Β· react-chessboard
- comlink (Worker RPC)
- nuqs (URL state) Β· zustand (local state)
- dexie (IndexedDB)
Requires Node 20+ and pnpm.
git clone https://github.com/atamano/openingscanner.git
cd openingscanner
pnpm install
pnpm devOpen http://localhost:3000.
| Command | Description |
|---|---|
pnpm dev |
Next dev server on :3000 |
pnpm build / pnpm start |
Production build and serve |
pnpm lint |
next lint (ESLint 9) |
pnpm typecheck |
tsc --noEmit β the only way to validate types |
node scripts/build-eco.mjs |
Regenerate lib/catalog/eco-data.ts from Lichess chess-openings TSVs |
Download the Lichess chess-openings TSVs to /tmp/eco-data/{a,b,c,d,e}.tsv, then:
node scripts/build-eco.mjsSource: https://github.com/lichess-org/chess-openings.
app/[locale]/ Next.js App Router, i18n-scoped
components/
chess/ Board + continuations table
scanner/ Form, progress, dashboard, exports, gap/weak analysis
ui/ shadcn primitives
hooks/ useScanner, dictionary hooks
lib/
catalog/ ECO data + classifier
i18n/ Dictionaries + context
landing/ Popular players directory
pgn/ PGN serializers + parser
repertoire/ Aggregation, gaps, weaknesses
sources/ Lichess + Chess.com streamers
storage/ Dexie wrapper
workers/
scanner.worker.ts Comlink-exposed scan engine
See CLAUDE.md for a deeper architectural walkthrough.
PRs welcome. See CONTRIBUTING.md for guidelines. A few places that are easy to jump in on:
- Curating
lib/landing/players.tsβ verifying handles, adding regional streamers, fixing country codes. - Improving the gap / weak-spot scoring.
- Adding translations (copy
lib/i18n/dictionaries/en.jsonto your locale). - Performance work on the ECO classifier or tree aggregation.
Nothing leaves your browser. The app calls the Lichess and Chess.com public APIs directly from the client β we never proxy or log your requests. The last scan is persisted to your browser's IndexedDB and can be cleared by clicking "New scan".
- Lichess chess-openings (CC0) β the authoritative ECO database powering classification.
- Lichess API and Chess.com Published-Data API for game streams.
- Everyone who tests the tool and reports broken handles.
OpeningScanner is part of a small family of free, player-first chess tools:
