OSCAR ROJASDATA ENGINEERING | FINANCE

2026 · DATA ENGINEERING | FINANCE

NBA Salary Cap Tracker

Where every NBA team's payroll stands, what they owe in luxury tax, and what they're allowed to do next — backed by the actual CBA bracket math.

NBA Salary Cap Tracker dashboard

Tech Stack

PythonFastAPIReactTypeScriptViteTailwind CSSRenderVercelGitHub Actionspytest

Overview

The NBA luxury tax works like income tax: each bracket rate applies only to salary within that band, not the total. That distinction matters — it's why Phoenix owes $101M in tax while other teams just over the line owe a fraction of that. I built a Python engine that implements the full CBA formula and verified it with 27 unit tests against known boundary values. The frontend shows where each team sits relative to the cap, tax line, and both aprons, and lists what they can and can't do based on their tier.

What I Built

  • Custom luxury tax bracket engine — mathematically correct CBA bracket calculations with 27 passing unit tests
  • All 30 teams with full player salary tables across 3 seasons (2026-27, 2027-28, 2028-29)
  • SVG CapThresholdBar — visual payroll position relative to cap, tax line, 1st apron, and 2nd apron
  • Per-team restriction engine — dynamically lists what each team can and cannot do based on their tier
  • League summary dashboard — total payroll, total tax collected, teams in each tier
  • 3-year payroll projection per team as contracts expire
  • GitHub Actions daily validation — 30-team seed data validated and engine tests run every 24 hours
  • Sort and filter by payroll, tax bill, cap space, conference, and tier

Screenshots

NBA Salary Cap Tracker — Dashboard Overview

Dashboard Overview

NBA Salary Cap Tracker — Filter Controls

Filter Controls

What I Learned

The NBA luxury tax is an incremental bracket system like income tax — each rate applies only to salary within that band, not the total

Repeater tax adds $1.00 to every bracket rate for teams that paid tax in 3 of the prior 4 seasons — this is what drives Phoenix's $101M bill

Vite non-interactive scaffolding silently no-ops when the target directory isn't empty — always verify file count before reporting build success

GitHub Actions exit-code gating: validation exits 1 on bad data, stopping the workflow before stale data reaches cache

Render prefers .python-version over runtime.txt — include both for reliability across deploy environments