In 33 days, the first race of the 2026 F1 season starts in Bahrain. Thousands of fans will be making predictions, voting in polls, and competing on leaderboards — all through widgets embedded on publisher websites. Here's how we're building the infrastructure to make that work.
The Two-Plane Architecture
Paddock.talk has two very different workloads. The dashboard is low traffic, high value — publishers creating events, configuring campaigns, checking analytics. The widget delivery plane is high traffic, cost sensitive — thousands of concurrent fans interacting with embedded widgets on publisher websites.
We keep these planes strictly separated. The dashboard uses full Supabase Realtime for live updates. The widget plane uses a "ping + fetch" pattern: when something changes, we broadcast a tiny message (just the event ID and version number), and the widget fetches the latest state. This means we never push full state updates to thousands of clients simultaneously.
The Stack
We run a TypeScript monorepo with pnpm workspaces and Turborepo. The core pieces:
- •API: Fastify on Node.js, deployed to Railway. Handles all embed endpoints, admin routes, and webhook processing.
- •Dashboard: Next.js 15 (App Router) on Vercel. Server-rendered pages with real-time data from Supabase.
- •Widgets: Vanilla TypeScript Web Components with Shadow DOM. Built with tsup, served from the API as a static file. Currently 43 KB gzipped with all 9 widget types bundled together.
- •Database: Supabase (hosted Postgres) with Row Level Security, real-time subscriptions, and generated TypeScript types.
- •Email: Resend for transactional emails — magic links, campaign recaps, result notifications, and campaign launch announcements.
What Makes Race Day Different
Normal web traffic is predictable. Race day traffic is not. When qualifying starts, thousands of fans open articles simultaneously. They all load the prediction widget. They all submit their grid predictions within a few minutes. Then they wait for results.
We've built for this in a few ways:
- •Rate limiting: 100 requests/minute global, 30/minute for interactions, 60/minute for analytics. Enough for real users, too tight for abuse.
- •Lazy realtime: Widgets only subscribe to real-time channels when they're visible in the viewport. When you scroll past, they unsubscribe. When the tab is hidden, they disconnect entirely.
- •Optimistic UI: When a fan votes, the widget updates immediately without waiting for the server response. If the server rejects it (duplicate vote, locked event), we roll back gracefully.
- •Denormalized leaderboards: Instead of computing rankings on every read, we maintain a
leaderboard_entriestable that gets updated by server logic after each interaction.
The Widget Bundle Challenge
Our widget bundle is loaded on publisher pages — pages we don't control. Every kilobyte matters. Currently we're at 43 KB gzipped with all 9 widget types included. That's healthy, but we have a clear path to reduce it further:
The next optimization is code-splitting per widget type. If an article only has a poll, the reader shouldn't download the grid prediction code. This is an architectural change we'll tackle after launch, targeting under 30 KB for the most common widget types.
What's Next
Between now and the Bahrain GP on March 14, our focus is entirely on reliability. No new features — only hardening:
- •Cloudflare CDN in front of the API for edge caching and DDoS protection
- •Cross-browser testing — Safari iOS, Samsung Internet, Chrome Android
- •Load testing to simulate 50K concurrent widget impressions
- •Publisher onboarding — hands-on integration support for our first beta partners
After the first race weekend, we'll have real data. Real engagement numbers from real fans on real publisher pages. That data will tell us what to build next — whether it's web push notifications, a public leaderboard widget, or custom branding per publisher.
The product is built to be data-driven. We track impressions, interactions, dwell time, CTA clicks, and return visits. Every feature we add post-launch will need to answer one question: does this keep fans on the page longer and bring them back?
Nick Hartley
Founder of Paddock.talk