Product case study
Uru
How I turned messy chess-game data into a browser-only analytics product that finds the highest-impact gap in a player's opening repertoire.
01 · Context
A sharper problem than post-game analysis
Chess improvement tools usually diagnose individual games: where you blundered, which move was inaccurate, and what the engine preferred. Useful once, but often hard to turn into a lasting plan.
I wanted to build something more durable: a product that looks across a player's real game history and answers one practical question.
What part of your opening repertoire is costing you the most, and what should you fix first?
02 · Discovery
Changing the unit of analysis
My first two ideas were weaker than the problem deserved.
| Idea | Why it looked good | Why I killed it |
|---|---|---|
| A shareable “chess personality” card, in the style of Spotify Wrapped | Proven viral mechanic, easy to build | One-and-done by design. Fun once, forgotten immediately. |
| A weakness report: your three biggest leaks, ranked | Actionable and data-driven | Already familiar. I would be competing on execution, not insight. |
The better idea came from changing the unit of analysis. Instead of examining one finished game, I analysed the player's repertoire: the openings they repeatedly rely on.
A repertoire behaves like a portfolio. It has concentration risk, weak exposure, repeated losses, and technical debt from constant improvisation. That framing created the product.
03 · De-risking
Feasibility before features
Before designing the interface, I tested three things that could have killed the product.
Does the data exist? Chess.com and Lichess both expose recent games, openings, results, and player color through public APIs.
Can it run with zero infrastructure? Both sources can be read from the browser, so the product needs no backend, no database, and no running server cost.
Do the two data sources reconcile? The platforms describe openings differently, so I normalised them into one schema before building the scoring model.
04 · Metric design
Turning raw games into a health score
The core of the product is five metrics computed from a player's last few hundred games. Each answers a question anyone can understand.
| Component | The question it answers |
|---|---|
| Coverage | Of the situations you are regularly forced into, how many do you have a prepared answer for? |
| Solidity | How much of your play stays out of losing matchups, the openings you score below a coin flip in? |
| Confidence | What share of your games happen in lines you actually know? |
| Performance | Are your chosen openings winning you games? |
| Repertoire debt | How much of your play is one-off improvisation with no plan behind it? |
The score is useful, but the roadmap is the product. Each gap is ranked by exposure, pain, and evidence, so the player sees the one opening problem most worth fixing first.
Prioritization is the product.
05 · Trade-offs
The trade-offs
| Constraint | Decision and rationale |
|---|---|
| Engine analysis would grade every move precisely, but costs server compute per game | Use results-based heuristics instead. Recent outcomes are enough for repertoire-level claims, run instantly in the browser, and keep cost at zero. |
| Full career history or a recent window? | Use a sliding window of recent games. It captures the player now, not a version of them from years ago. |
| Progress tracking needs stored snapshots, the one feature that breaks the zero-backend architecture | Defer it until stored snapshots are worth the added database and privacy complexity. |
06 · Verification
Real data exposed the important bug
The first run on my own account returned a Coverage score of zero, claiming I had no prepared answer to anything. The root cause was a multi-source data issue: Chess.com and Lichess opening names were not matching cleanly, so the same lines split into fragments.
After the fix, the engine produced credible results for both a club-player account and an elite-player comparison account.
My account. Health 63 out of 100, with a Solidity of 54. The top finding was a weak reply to one of the most common first moves. Specific, evidence-backed, and consistent with my actual playing experience.
Elite-player comparison. Health 84 out of 100, with perfect Performance and a Solidity of 95. Same engine, same scale, clearly different profile.
Fix first: the reply to 1.e4, losing 59% of games as Black
Perfect results, almost no losing matchups: a rock-solid repertoire
07 · Takeaways
What this project demonstrates
Evidence over attachment. I killed two ideas before building because the evidence was weak.
Cross-domain insight. The useful framing came from portfolio risk, not from chess software conventions.
De-risking in sequence. Data access, architecture, normalisation, engine, then interface.
Cost-conscious architecture. One clear trade-off kept the product free to run.
Messy multi-source data. Two inconsistent sources became one usable product model.
After the first release, I added a study-plan feature that recommends openings matched to the player's inferred style, with free learning resources for each gap. Next on the roadmap: progress tracking, the feature that finally makes a database worth adding.