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.

DiscoveryMetric designTrade-offsShipped & verified

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.

IdeaWhy it looked goodWhy I killed it
A shareable “chess personality” card, in the style of Spotify WrappedProven viral mechanic, easy to buildOne-and-done by design. Fun once, forgotten immediately.
A weakness report: your three biggest leaks, rankedActionable and data-drivenAlready 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.

the unit of analysis: every game a player has, poured into one shape

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.

ComponentThe question it answers
CoverageOf the situations you are regularly forced into, how many do you have a prepared answer for?
SolidityHow much of your play stays out of losing matchups, the openings you score below a coin flip in?
ConfidenceWhat share of your games happen in lines you actually know?
PerformanceAre your chosen openings winning you games?
Repertoire debtHow 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.

one rubric, two very different repertoires
Prioritization is the product.

05 · Trade-offs

The trade-offs

ConstraintDecision and rationale
Engine analysis would grade every move precisely, but costs server compute per gameUse 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 architectureDefer 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.

samaritn · 1500s club player63health
Coverage40
Solidity54
Confidence89
Performance45
Repertoire debt86

Fix first: the reply to 1.e4, losing 59% of games as Black

Elite-player comparison84health
Performance100
Solidity95

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.