
Headless Commerce at B2B Scale
Under Armour · 35% ticket-resolution reduction
Case Study

A side project I keep coming back to
In 2019, as a thesis for my first graduate program, I built a fantasy draft game. It was split across two repos — a Laravel 6 GraphQL API and a React 16 SPA — and when I turned it in, it worked. It also never shipped to a single real user.
Six years later, that thesis has become Draft Slot. It runs live drafts across the NFL, NBA, MLB, and NHL. It has real users and infrastructure that scales up for draft night and back down for the offseason. It's the project I keep teaching myself new things on — and the one I've never once paid to market.

The original version was two repos, both dated early 2019. The API was Laravel 6 with Lighthouse GraphQL and Passport for OAuth. The frontend was React 16 with Apollo Client for data and Redux for local UI state, bundled with a hand-rolled Webpack config.
I picked every piece for a reason: GraphQL was new, Apollo was new, and picking them meant I'd learn them. That was the entire point of a thesis project.
It delivered the thesis. It did not deliver a product. I submitted the work, graduated, and the repos went quiet for almost two years.

When I came back to it, I didn't port the old code. I rebuilt the whole thing in a single Laravel monolith with Blade templates, Alpine.js for interactivity, and Tailwind for styling. The GraphQL layer was gone. The SPA was gone.
The choice looked unfashionable on paper. In practice, it was the only one that made sense. I had no team, no budget, no investors, and a full-time job. Every hour I spent tuning a bundler or fighting hydration was an hour I wasn't spending on features my users could actually see.
This was the version that actually shipped. Real users, a real database, a real draft night — the baseline the rest of this story is built on top of. The tradeoff was real too: I gave up some of the polish a proper SPA offers. What I got back was velocity. Shipping something on a Sunday night became normal again.

The Reset shipped, but it didn't do everything I wanted. I took the app that was already live and rebuilt its frontend and backend through an agentic engineering loop — requirements first, agent build, validation before merge. The product never restarted; the codebase did. Today the Laravel codebase is 100% built with Claude.
The goal of the rebuild was concrete: take the single-sport, server-rendered baseline and build the draft out into a real multi-sport, real-time product that scales. I got there by combining three threads, run through the same loop over and over.
The numbers are the shape of a codebase someone has actually lived with through an agentic loop: 1,800+ commits, 347 Pest tests, and not a single missed draft night since the rebuild. The product predates this era. The code that runs it doesn't.


















What the rebuild produced is a real product running across the NFL, NBA, MLB, and NHL. The work splits into three jobs that all have to hold at once: keep draft night live, treat the unglamorous plumbing seriously, and keep the bill sane in the months nobody is here.
Live drafts, in real time. On draft night every user watches the same board, and every pick has to reach every connected browser in seconds.
Built like a real product. The plumbing users never see is the plumbing that decides whether this thing survives.
Paying for the quiet months. A draft game has a brutal traffic shape — dead most of the year, mobbed for a few days in April, June, July, and October. I encoded the calendar into the deployment itself.
It's the kind of cost optimization a small company would do for real money. For me, it's what keeps the project inside the budget of a personal side project.
The next chapter moves off a single Laravel monolith and toward microservices that scale independently — the parts that spike on draft night decoupled from the parts that don't. Alongside that, I'm planning a transition to FastAPI, pulling the heavier service work into Python where the async story and the typing fit the direction the platform is headed.
The product splits in two as well. One side becomes a focused mock-draft app — the prediction game at its core. The other becomes a contest app called draftrm, where the competition and the sponsorship live: prize pools, sponsor configuration, and the Draft for a Cause rooms that let brands fund the payout.
The best thing about a side project is that it moves on your schedule. The scary thing about a side project is that it moves on your schedule. The work now is keeping the craft intact while finally letting more people in.