Inspiration

We had a goal to find any Basketball shot that we wanted using a sleek graphical court interface, but couldn't find a tool that let us explore shot data visually. Stats sites give you numbers and tables, but we (and many others) want to see where LeBron takes his shots!

What it does

ShotFinder lets you explore every single NBA shot from the last 30 years on an interactive court. Filter by player, team, season, quarter, or clutch moments. Click any modern era shot to watch the actual broadcast clip inside the court view. With it's incredibly simple UX, it bridges the gap between someone interested in the game for fun and actual statisticians building models and trying to find an edge in the fast-paced environment that is the modern NBA.

How we built it

Python/Flask API backend serving a local SQLite database with 6+ million shots. The frontend uses D3.js for high-performance SVG rendering. We pulled all the data with a simple script using the NBA's public API and cached it locally for speed.

Challenges we ran into

Database Performance at Scale With 6.2 million shot records, naive queries were taking 10+ seconds. We solved this by creating composite indexes on the most common filter combinations (season, player, team) and using SQLite's query optimizer hints. Query times dropped to under 100ms. Frontend Rendering Bottleneck Rendering thousands of SVG circles caused the browser to choke. We implemented:

  • Smart pagination (default 500 shots, up to 5000)
  • D3.js data joins to minimize DOM mutations
  • CSS will-change hints for GPU acceleration Hover Precision in Dense Areas When 50+ shots overlap in the paint, standard hover detection fails. We built a quadtree spatial index that finds the nearest shot to your cursor in O(log n) time, with a 75ms dwell delay to prevent flickering when moving between nearby shots. ## Accomplishments that we're proud of Probably the polish, dynamic team theming, smooth animations, and a broadcast-quality feel. It looks and feels like something a professional sports network would use alongside hobbyists like us. ## What we learned That frontend performance matters as much as backend. Also that NBA video clips aren't available before 2016, which was learned the hard way, however we addressed this by gracefully disabling the "Watch Clip" button and showing a tooltip explaining why.. ## What's next for ShotFinder We have already deployed to a simple app deployer with what we built today, but the aim is deploying to AWS infrastructure so anyone in the world can access it seamlessly, using scheduled Lambdas to pull in fresh data every day in line with the season, and deploying a container via a serverless ECS task served active-active multi-region. In terms of what the user interacts with, we also want to add heat maps and advanced analytics overlays as further UI enhancements.
Share this project:

Updates