Hoop State Gameflows
Hoop State Gameflows is a data-gathering and presentation framework that turns NBA game data into visual, contextual breakdowns — lineup rotations, score-margin trends, shot charts, and full box scores.
The Idea
For years I've been a fan of the NBA stats site popcornmachine.net — a project that, remarkably, dates back to 2003 and quietly built one of the longest-running, free game-level stat viewers on the web. (Its name comes from a quip by legendary Lakers announcer Chick Hearn: "He put him in the popcorn machine...he's got salt and butter all over him.") After the site went quiet at the beginning of 2026 — and after waiting a few months in hopes it would return — I decided to build a modern take on the idea it championed: a visual, stats-first look at NBA games.
System Outline
The site is constructed in three parts: the Ingest Layer, the Presentation Layer, and the Orchestration Layer.
Ingest Layer
- The presentation layer is designed to be cleanly minimal, easy to browse and compare, and fast.
- Each game is pre-rendered into its own lightweight (~700KB) static webpage, eliminating API fetches and hydration lag while maximizing page-load speed and browser caching.
Presentation Layer
- The presentation layer is designed to be cleanly minimal, easy to browse and compare, and fast.
- Each game is pre-rendered into its own lightweight (~700KB) static webpage, eliminating API fetches and hydration lag while maximizing page-load speed and browser caching.
- Chart components (bar chart, game-flow, shot chart) were built and tested in isolation via Storybook.js before being wired into the static page templates.
Orchestration Layer
- Using a persistent macOS LaunchAgent, scripts are automatically executed every morning to poll the latest game data, build the game pages, test the build, and deploy the update.
Key Decisions
The volume of data I process is staggering. For each season there are approximately 600,000 rows of data, with as many as 32 factors per row. That scale creates a few key decisions.
Balancing site speed and page weight
Instead of keeping a live SQLite database to hydrate pages at browse-time, I opted to pre-build pages. This eliminates the need for a Node.js server to operate the site and database, so I'm able to run a simple static website on S3 (and CloudFront).
Presenting the data clearly without overwhelming the user
With the amount and granularity of data I have, it's important to make every piece of it as useful as possible — opting for a comparison-based narrative that frames the adversarial nature of inter-team competition.
Instead of treating each filing as a single event, the system splits each filing into transaction-level rows. This allows downstream analysis to focus on the individual aspects of the transaction.

Bar charts to explain raw, numeric comparisons.

A time-based score-margin chart paired with lineup plus/minus, to explain the push and pull of intra-game battles.

Shot charts that give a visual representation of a court and where shots were made or missed, with the ability to filter shots by distance.