Expansion Draft Simulator Build the 2028 roster. Get the grade.
A production fan experience for the 2028 NBA expansion draft - draft an 8-player roster under real protected-player rules, get a deterministic letter grade, simulate a season, and share branded cards with AI commentary.
The Problem
I was working inside an experiential agency when the NBA expansion conversation started heating up. The question was everywhere — sports radio, Twitter threads, barbershop debates. Seattle wants its team back. Las Vegas has the market. Who do they even get?
The agencies and brand teams I was working with were trying to tap into that energy. Fan activations, content campaigns, something that gave people a reason to engage beyond just reading takes. But when you actually sat down to build that experience, there was nothing in the middle.
There was a spreadsheet someone had shared on Reddit that listed every exposed player under a rough expansion scenario. That was it. If you wanted to run a mock draft, you were doing it manually — copy-pasting names, making up rules as you went, then arguing in the comments about whether your picks were good.
"There was no tool that respected the real rules of how expansion drafts work, gave you an actual verdict on your choices, and let you put your roster on the internet in under five minutes."
Consumer sports apps were not built for this. They either required accounts, charged money, had their own branding all over your content, or simplified the experience to the point where it stopped feeling like a real draft. The fans who cared most — the ones who actually knew what a protected list was — wanted something that honored the real mechanics. The agencies building around those fans needed something polished enough to put in front of a client. Neither group had a tool. So I built one.
What it does
-
01
Real exposed-pool draft, two modes
Expansion Rules enforces the actual mechanics — each team protects most of its roster and you can only pick from the players left unprotected. Roughly 90 players across 30 teams, the same exposure scenarios the league would actually produce. Free Build drops all restrictions for dream-team arguments.
-
02
Deterministic grading engine
Every completed roster gets a letter grade from A+ to F. No machine learning, no randomness. The engine scores individual talent from real box-score stats and an age curve, position balance across all five spots, and roster fit across role diversity and age spread. The grade is the same every time you build the same roster.
-
03
AI analyst with a zero-cost fallback
When the roster is complete, Claude generates a one-liner analyst quote for the share card. If the API is missing, rate-limited, or over budget, the app falls back to a 30+ entry library of deterministic, contextual quips. The fallback knows the difference between a pick-1 star and a pick-7 veteran. Most users never notice the switch.
-
04
Season simulation
In parallel with the analyst call, the server projects a win-loss record, playoff seed, and narrative highlights. The projection is derived from the same grading engine that produced the letter grade. On LLM failure, the API still returns a complete response with deterministic outcomes — the share card populates either way.
-
05
Share cards in five themes
Every completed draft produces a downloadable PNG card with the letter grade, projected record, per-player stat lines, and team branding. Five themes: Minimal, Black, Sporty, Sonics, and Hardwood. One-tap sharing to Twitter, Instagram, Discord, Reddit, and native OS share sheets.
-
06
Editorial data pipeline
Player stats, badges, bios, salary context, and exposure status originate from a maintained Google Sheet exported as CSV. A sync script generates TypeScript source files that ship with the build. The team controlling player data is the creative director, not an API contract.
The core draft loop runs entirely in the browser for instant responsiveness — undo, pool filtering, and pick validation stay sub-100ms. Completing the 8th pick triggers a jackpot-style reveal: letter grade, season projection, and AI analyst quote land in sequence. The grade is always the same for the same roster. The story around it is never identical.
Playoff contender
Expansion ceiling · AI analyst reacts
Play-in bound
Solid foundation · room to argue
Rebuild territory
Back to the board · no mercy
Expansion mode caps the top grade at A- to reflect realistic expansion outcomes — no team has ever walked out of an expansion draft with a title roster. Free Build removes that cap but raises the cutoffs for A and A+, so a perfect score actually means something.
How it grew
-
The prototype
A single HTML file. No build step, no server, no database. The draft logic was client-side JavaScript, the player data was hardcoded, and the analyst feature pointed directly at the Anthropic API from the browser — which failed for most users due to CORS restrictions. The grade formula existed. The share experience did not.
-
Production architecture
The move to Astro established the foundation. Static shell from a CDN, serverless API layer for AI generation, external data, and email. The draft engine stayed client-side for instant responsiveness. Each API route got origin validation, IP-based rate limiting, and request-size guards. The analyst feature finally worked.
-
Data control
The Google Sheets pipeline replaced hardcoded player data. The creative team could update exposure, stats, bios, and badge flags in a spreadsheet, export CSV, run one command, and ship a new build. No engineering required for data changes.
-
AI cost controls
A daily budget cap tracked in Redis per UTC day. When estimated spend hits the cap, analyst routes return 503 and season-sim falls back to deterministic output. Setting the budget to exactly zero enables a test mode that blocks all Anthropic traffic without touching any other configuration.
-
The viral loop
Five share card themes because different audiences post differently — Discord uses Sporty, basketball Twitter uses Minimal, Sonics fans use Sonics. The ranked-mode email signup gives the team a contact list of the most engaged users, with each subscriber's roster card as proof of engagement.
Stack
- Astro 5
- React 19
- TypeScript
- Tailwind CSS 4
- Anthropic Claude
- Upstash Redis
- Neon Postgres
- Resend
- html2canvas
- Ball Don't Lie API
- Vercel
- Vitest
- Playwright