Spicy League is a recurring tournament series I run for friends — captains-draft format, round-robin group stage, single-elimination playoffs. For the first few seasons I managed everything in spreadsheets. It worked until it didn't.
I built a dedicated platform to handle the full tournament lifecycle: signup and waitlist, captain selection, a live snake draft with a per-pick clock streamed via Server-Sent Events, automated round-robin scheduling, match reporting, standings with tiebreak logic, and a playoff bracket generator.
The stack is Next.js with a Neon Postgres database and Drizzle ORM. Auth is handled by Better Auth with email verification via Resend. For League of Legends seasons, player profiles pull live stats from the Riot Games API on a daily Vercel Cron refresh. Rate limiting uses Upstash Redis with a graceful fallback so the app stays up even if Redis is unavailable.
The live draft view is the most technically interesting piece — multiple participants need to see the same state in real time without a WebSocket server. SSE from a Next.js route handler handles it cleanly with no infrastructure overhead.