2025 · Personal build
Archived
Athlytics
NBA player analytics — career stats from the NBA's own API, awards history from a targeted headless-browser scrape, both served through a two-tier cache.

A basketball research tool built to answer the arguments that come up constantly and get settled badly: who actually had the better peak, how a season stacks up historically, what the award voting really looked like.
Athlytics was engineered to transform raw, unstructured fitness telemetry into sub-second visual performance analytics. Most of what the app needs — game logs, shot charts, advanced stats, bios — comes straight from the NBA's own stats API. Awards and voting history don't: that page is JavaScript-rendered, so a headless Chrome instance loads it and BeautifulSoup parses what comes back. Both paths land in the same two-tier cache — a Flask-Caching layer in front, and a disk-first JSON cache underneath that checks for a saved record before the scraper ever runs again.
Archived at the point where the data layer worked and the interface had not caught up. Left up because the caching approach — and knowing when to scrape versus when to call an API — is the part worth showing.
What it does
- Game logs, shot charts, and advanced stats pulled from the NBA's own stats API
- Awards and voting history scraped from Basketball-Reference via headless Chrome, since that page is JS-rendered
- Two-tier cache: a Flask-Caching layer plus a disk-first JSON cache keyed by player ID
- A small utility reconstructs Basketball-Reference's own ID format from a player's name, bridging the NBA API's numeric IDs with the one route that needs BR's slug scheme
- Client-side fuzzy search (Fuse.js) layered over a server-side search endpoint
- Recharts line charts for career trends, a Chart.js scatter plot for shot location
What it taught me
- Reach for scraping only where a real API doesn't cover it, not by default
- Two caching layers earn their keep when the upstream is both slow and inconsistent
- Knowing when to archive a side project instead of finishing it