If you've played competitive chess, you've probably hit this moment:
Neither side has a tactic. Nothing is hanging. No forced combination to calculate. But a strong player glances at the board for three seconds and says:
"White is clearly better here."
That judgment — fast, confident, pre-calculation — is one of the hardest skills in chess to practice deliberately.
So I built ChessIQ to fix that.
♟️ What is ChessIQ?
ChessIQ is a positional evaluation trainer. Instead of asking you to find the best move like a typical puzzle site, it shows you a real game position and asks one question:
White is better / Equal / Black is better
You commit to your answer before seeing the engine. Then ChessIQ shows you the Stockfish evaluation and a pre-generated AI explanation of the positional ideas behind it.
You can try it without an account at chessiqapp.com.
🤔 Why train positional evaluation?
Traditional chess puzzles are great at training calculation. You see a position, find a tactic, calculate variations, get the move.
But real games aren't always like that. A huge portion of chess is spent in positions where there's no immediate tactic — and you're instead asking:
- Which side has more useful space?
- Are there weak squares to exploit?
- Which pieces are better placed?
- Who has the initiative?
- Which position is easier to play?
Strong players answer these almost intuitively. ChessIQ is designed to make that intuition something you can practice, measure, and improve.
The three-way format matters here — it's fast enough to do many positions per session while still producing a meaningful signal about your positional judgment.
⚙️ How the data pipeline works
The frontend is conventional HTML/CSS/JS backed by Firebase. The interesting part is upstream.
The preprocessing pipeline looks roughly like this:
Lichess games
→ candidate position extraction
→ filtering
→ Stockfish analysis
→ metadata generation
→ AI explanation (pre-generated)
→ Firebase
→ ChessIQ
A few design decisions I'm glad I made early:
AI explanations are generated ahead of time. No LLM call sits in the training loop. Feedback is instant, and API costs don't scale with user interactions.
The AI explanation is feedback, not ground truth. Stockfish is still the underlying evaluation signal. The model's job is to turn that signal and position metadata into something a player can actually learn from.
🏷️ The theme normalization problem
Every puzzle gets tagged with positional themes — things like Piece Activity, King Safety, Weak Squares, Outposts, Passed Pawns.
The problem: an LLM doesn't naturally produce a consistent taxonomy.
One explanation might say "weak squares". Another says "weak dark squares". Another says "strong knight outpost". Fine individually — but if each generated phrase becomes its own category, your analytics become useless.
My solution: a normalization layer that maps generated themes into a canonical vocabulary of 73 positional concepts.
AI explanation text
→ raw themes extracted
→ mapped to canonical 73-theme vocabulary
→ stored as structured data
The explanation stays natural and descriptive. The rest of the app gets stable, consistent identifiers it can actually use for thematic training and analytics.
📊 Two separate rating problems
ChessIQ has two different rating concepts, and they're genuinely different problems.
Player Position Rating (PR)
The player's long-term progression metric. Designed to answer: how consistently good am I at evaluating chess positions? It uses compression curves, provisional periods, streak bonuses, and inactivity decay to reward genuine sustained improvement — not luck.
Puzzle difficulty rating
A static Easy/Medium/Hard label goes stale as real player data accumulates. A position that looked Hard during preprocessing might consistently get answered correctly by real players.
So ChessIQ tracks community performance on individual positions and updates their difficulty ratings adaptively over time. I'm treating this as an ongoing experiment — sparse data and selection effects are real problems at this scale, and I'd rather have a smaller dataset I can inspect than a huge one I can't reason about.
🔁 Completion-based spaced repetition
Missed positions enter a personal review queue — but on a completion-based schedule, not a time-based one.
If someone does 100 puzzles in one session, and someone else does 5 puzzles over a week, they should get a similar training experience. Tying review to the calendar would make the first person's experience wildly different from the second's.
Current open question I'm sitting with: is reviewing the exact same position the right unit? Or should review surface a structurally similar position that tests the same concept in a new setting?
🚀 Current feature set
ChessIQ v1.4.8 ships with:
- Position Rating (PR) — earned through consistent accuracy, not grinding
- Adaptive puzzle difficulty — per-puzzle ratings that update with community data
- Thematic training — filter by any of the 73 positional themes
- AI positional explanations — pre-cached, instant feedback after every puzzle
- Theme-accuracy radar — analytics showing your strengths/weaknesses by theme
- Spaced repetition — missed puzzles re-enter your queue
- Daily puzzle — one shared community challenge per day
- 47 achievements across performance, consistency, and progression milestones
- Global leaderboard
- Admin Control Center — operational dashboard for puzzle health and theme coverage
🤷 What I'm still figuring out
A few open problems I'd love input on:
1. Calibrating "Equal"
Engine evaluations are continuous. Turning them into three discrete buckets is lossy. Where should the Equal boundaries sit — and should they change based on position type or player strength?
2. Fixed taxonomy vs. embeddings
Is a canonical 73-theme vocabulary the right abstraction for personalization? Or would embeddings and clustering eventually produce better, more nuanced results?
3. What to measure for actual improvement
PR going up is a proxy metric. What I'd really like to know: does ChessIQ make someone's positional evaluations more accurate on positions they've never seen before? That's a much harder measurement problem.
🙏 Try it out
If you're into chess, training systems, rating design, or just want to see how a Stockfish + Firebase + Python data pipeline fits together — I'd love feedback.
Accounts are free and add PR tracking, history, achievements, and your personal review queue. Or just play anonymously.
Happy to answer questions about the data pipeline, the PR algorithm, the theme normalization layer, or anything else in the comments. 🏆
Top comments (0)