SaberIQ
Most stats apps dump numbers. This one explains them— because I wanted my nephew to actually understand the game.
SaberIQ is a full-stack sabermetrics app with Claude built into every data view. It doesn’t just show you a player’s BABIP or xFIP — it tells you what those numbers mean for this player, right now. A real app, built solo, for one very specific user first.
It started with wanting to teach my nephew the game.
I love baseball — not just the box score, the subtleties: why a pitcher’s ERA lies, why a hitter on a heater is about to cool off, what the numbers are quietly telling you. I wanted my nephew to see those things too. But every stats site I’d point him to just threw numbers at him with no story.
This is the whole pattern of how I build — I needed something, nothing did it well, so I made it. This one just happened to come from love of the game.
A number without a story doesn’t teach anyone anything.
Sabermetrics is full of meaning that a raw figure hides. BABIP tells you whether a hot streak is real or luck. An xFIP that diverges from ERA says a pitcher is over- or under-performing his actual command. Strand rate hints at regression coming. But you only learn that if someone explains it — and no dashboard does.
Here’s a table of numbers. Good luck. The meaning lives in the reader’s head, or nowhere.
Here’s the number — and here’s what it means for this player, in language a curious kid (or anyone) can follow.
Claude, inline in every view — five ways.
The AI isn’t a chatbot bolted on the side. It’s woven into the product as five distinct, context-aware explainers, each server-side so the model always has the real data.
Every metric explains itself.
Tap any number on a player page and Claude reads it for thisplayer’s actual season — grounded in the real stat line, never a generic definition. Here a .358 BABIP gets the honest verdict: partly earned, partly luck, a modest cooldown coming — not a cliff.
What’s likely to happen — and why.
For the matchup in front of you, the model lays out the probable outcomes, the pitcher’s put-away pitch and location, and the reasoning behind the edge. Skubal ahead 1–2 goes upstairs; Judge chases when he’s behind. The numbers become a scouting read.
Talk through the decision in front of you.
A live game-manager mode that reads the moment: score, base-out state, the count (rendered as an accessible role="meter" gauge), and the call. Stay with the tiring starter, or go to the lefty? Claude weighs velo drop, the platoon split, and career history, then commits to a recommendation.
Two players, and the story of how they differ.
Line two players up and the numbers get a narrator. Witt and Henderson are both elite young shortstops — but one wins on contact and speed, the other on power and plate discipline. The comparison ends with which build fits your league, not just who has the bigger number.
A real call on your real roster.
Wired to Yahoo Fantasy over OAuth, it reads tonight’s slate against your actual lineup and makes the start/sit calls — with the one swap that moves your night surfaced first. Bench the lefty-killer’s bad platoon spot; start the bat headed into Coors. One edge, clearly reasoned.
The AI teaches. The judgment is still mine.
The interesting part isn’t that it calls an API — it’s the guardrails around it. The stack:
Context, not vibes
Every AI route runs server-side with the real stat line in hand, so the explanation is grounded in this player’s actual numbers — never a generic definition.
Keys never leak
All five Claude routes live in one server module; the API key is never exposed to the client.
Runs on nothing
A full mock mode returns canned data with zero credentials — so the app boots and demos without a single real key. That’s an engineering choice, not an accident.
Debugged in the weeds
A Node.js 25 localStoragebug 500’d every page; I traced it to auth loading at module time and fixed it with a dynamic import + a polyfill.
AI as the teaching layer — on a real, accessible, shipped app.
SaberIQ is a whole product I designed and built solo: auth, database, a third-party OAuth integration, a live-game mode, and an AI layer that has a job to do rather than a demo to give.
Status: built and UAT-complete, not yet public — it’s waiting on a domain connection before I open it up. I’m not going to call it “launched” until it actually is.
The tools got faster. The love of the game is why I built it.
A hiring manager can read this as AI-in-product done with judgment. I read it as the app that finally lets me watch a game with my nephew and explain what’s really happening. Both are true — and that’s exactly how I like to build.