~/blog
back to index
post

Building TradeFinder, an NBA trade sandbox

TradeFinder started as a way to test NBA trade ideas against a useful subset of roster and salary rules without turning it into a giant cap simulator.

TradeFinder started from a pretty simple itch: I wanted a faster way to test trade ideas than bouncing between cap tables, roster pages, and half-finished notes.

Not a full front-office simulator. Just a small sandbox where I could pick a team, throw a few contracts on the block, and get back legal two-team ideas that were at least somewhat grounded in reality.

What the app actually does

The stack is small on purpose.

The backend is FastAPI. The frontend is React with Vite. The data lives locally in seed files for all 30 NBA teams, so the app can answer quickly without dragging in a database before it earns one.

The core flow is straightforward:

  • pick a team
  • mark specific players as tradeable
  • optionally narrow the search by conference or one target partner
  • search legal two-team trades using simplified salary-matching rules

That "simplified" part matters.

I did not try to model every edge case in the CBA. The project is much more useful as a fast sandbox than as a fake promise of perfect cap-law accuracy. The trade engine checks the parts that change the answer most often: salary matching, roster size after the deal, no-trade clause warnings, and second-apron aggregation restrictions.

The part that made it worth building

The most interesting piece was ranking.

Finding legal trades is only half the job. A giant list of technically valid deals is not very helpful if the top results are nonsense. So the results are ranked realism-first, with separate fields for realism, balance, fit, contract value, and a complexity penalty.

That let me keep the output honest about what it is. It is not saying "this trade will happen." It is saying "among the legal structures this search found, these look less ridiculous than the others."

I also liked keeping the UI stateful in a very boring way. The selected team, trade block, and search controls live in local storage, which means refreshing the page does not wipe out the setup. For a tool like this, that matters more than adding another feature.

Why the deployment setup fits the project

The repo deploys cleanly to Cloudflare with a Worker serving the built frontend and the /api routes.

That is a good match for this app because the search request is stateless. The API can accept selected player IDs directly instead of relying on a server-side session, which keeps the whole thing easier to host and reason about.

What I would push next

The obvious next step is better realism inputs.

Right now the scoring already blends current and previous season stats with age and contract context, which is enough to make the results feel meaningfully sorted instead of random. But there is still room to make team fit more specific, add clearer explanations for why a trade scored the way it did, and keep expanding the rule coverage without losing the speed that makes the project fun to use.

That is probably the line I want to hold with TradeFinder in general: more useful, not more bloated.