<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rakesh Paul</title>
    <description>The latest articles on DEV Community by Rakesh Paul (@rakesh_paul).</description>
    <link>https://dev.to/rakesh_paul</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F201316%2Fceb07d6a-e533-4e19-b791-eec6e7f57554.jpg</url>
      <title>DEV Community: Rakesh Paul</title>
      <link>https://dev.to/rakesh_paul</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rakesh_paul"/>
    <language>en</language>
    <item>
      <title>I Built a Full-Stack F1 Fantasy Platform in 4 Weeks — Solo, With AI Agents</title>
      <dc:creator>Rakesh Paul</dc:creator>
      <pubDate>Sun, 08 Feb 2026 02:27:00 +0000</pubDate>
      <link>https://dev.to/rakesh_paul/i-built-a-full-stack-f1-fantasy-platform-in-4-weeks-solo-with-ai-agents-3195</link>
      <guid>https://dev.to/rakesh_paul/i-built-a-full-stack-f1-fantasy-platform-in-4-weeks-solo-with-ai-agents-3195</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwe10lymgb16c7jjbeip.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwe10lymgb16c7jjbeip.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;This post was originally published on &lt;a href="https://binaryroute.com/blog/building-formula1-plus-solo-with-ai-agents" rel="noopener noreferrer"&gt;binaryroute.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In late December 2025, during a short holiday break, I opened my laptop with a simple idea — build the F1 fantasy league platform I'd always wanted as a fan.&lt;/p&gt;

&lt;p&gt;Four weeks later, &lt;a href="https://formula1.plus" rel="noopener noreferrer"&gt;Formula1.Plus&lt;/a&gt; is live. 70+ database tables. 30+ API modules. Race predictions, live leaderboards, private leagues, telemetry dashboards, news aggregation, community features, and a full admin panel.&lt;/p&gt;

&lt;p&gt;Built and shipped by one developer.&lt;/p&gt;

&lt;p&gt;This post is a technical walkthrough of how I pulled it off — the framework I built first, the stack I chose, the AI workflow that made it possible, and what I'd do differently.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/your-screenshot-url" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/your-screenshot-url" alt="Formula1.Plus Dashboard" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The Problem With Building Solo
&lt;/h2&gt;

&lt;p&gt;If you've tried building a full-stack product alone, you know the pain. You're the architect, the frontend dev, the backend dev, the DBA, the DevOps person, and the QA — all at once.&lt;/p&gt;

&lt;p&gt;Every context switch costs you. You spend more time on plumbing than on the product. Projects stall, scope shrinks, or you burn out halfway through.&lt;/p&gt;

&lt;p&gt;A project with this scope — predictions engine, scoring system, leaderboards, leagues, news aggregation with semantic search, telemetry dashboards, background job processing, passkey auth — would have been a 6-month grind. Probably abandoned by month 3.&lt;/p&gt;

&lt;p&gt;Two things changed the math: &lt;strong&gt;a framework I built to eliminate boilerplate&lt;/strong&gt; and &lt;strong&gt;AI agents as pair programmers&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 1: Build the Framework First
&lt;/h2&gt;

&lt;p&gt;Before writing a single line of F1 code, I built &lt;strong&gt;ProjectX&lt;/strong&gt; — an opinionated full-stack TypeScript framework with a CLI.&lt;/p&gt;

&lt;p&gt;The idea: define your database schema once, run one command, and get everything generated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;projectx crud &lt;span class="nt"&gt;--models&lt;/span&gt; drivers,races,predictions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That single command generates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API routes&lt;/strong&gt; with Hono, including input validation via Zod&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service layer&lt;/strong&gt; with business logic and authorization hooks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository layer&lt;/strong&gt; with Drizzle ORM queries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TanStack Query hooks&lt;/strong&gt; for the frontend with proper cache keys&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unit test scaffolds&lt;/strong&gt; for the service layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All type-safe. All wired up with dependency injection. No manual API type definitions — the frontend imports route types from the backend via Hono's typed client.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Architecture
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP Layer (Hono Routes)
    ↓
Middleware (Auth, Rate Limiting, Logging, Caching)
    ↓
DI Container
    ↓
Service Layer (Business Logic + Authorization)
    ↓
Repository Layer (Drizzle ORM)
    ↓
PostgreSQL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every feature follows this pattern. Every feature gets its own folder. The AI agents I used later could navigate this structure instantly because it was consistent everywhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Monorepo
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;f1plus/
├── apps/
│   ├── api/          # Hono backend
│   └── web/          # TanStack Start frontend
├── packages/
│   ├── db/           # Drizzle schemas + migrations
│   ├── db-sync/      # F1 data synchronization
│   ├── types/        # Shared TypeScript types
│   ├── ui/           # shadcn/ui component library
│   ├── emails/       # React Email templates
│   ├── env/          # Zod-based env validation
│   └── tsconfig/     # Shared TS configs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seven shared packages. Two apps. One &lt;code&gt;pnpm&lt;/code&gt; workspace. Everything shares types, nothing drifts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This structure was the single most important decision.&lt;/strong&gt; Not because it's novel — because it gave me and the AI agents a predictable codebase from day one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: The Stack
&lt;/h2&gt;

&lt;p&gt;I chose each piece deliberately. Here's what and why.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend: TanStack Start + React 19
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://tanstack.com/start" rel="noopener noreferrer"&gt;TanStack Start&lt;/a&gt; is still relatively new, but it clicked for this project. SSR-ready, file-based routing via TanStack Router, and TanStack Query baked in for data fetching.&lt;/p&gt;

&lt;p&gt;The routing is fully type-safe — route params, search params, loaders — all typed. Combined with Hono's typed client on the backend, I get end-to-end type safety from the database to the component without writing a single manual type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Frontend hook — generated by ProjectX CLI&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useDriverStandings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;seasonId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;driver-standings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;seasonId&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;standings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;drivers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$get&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;seasonId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The query function is typed from the Hono route definition. Change the API response shape and TypeScript catches it in the frontend immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  Styling: Tailwind CSS v4 + shadcn/ui
&lt;/h3&gt;

&lt;p&gt;Tailwind v4 with CSS custom properties for theming. I defined a set of design tokens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;--f1-bg-card&lt;/span&gt;
&lt;span class="nt"&gt;--f1-bg-secondary&lt;/span&gt;
&lt;span class="nt"&gt;--f1-border&lt;/span&gt;
&lt;span class="nt"&gt;--f1-text&lt;/span&gt;
&lt;span class="nt"&gt;--f1-text-muted&lt;/span&gt;
&lt;span class="nt"&gt;--f1-red&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These resolve to different values in light and dark mode. Every component uses these tokens instead of hardcoded colors. This made the entire UI theme-able with zero per-component overrides.&lt;/p&gt;

&lt;p&gt;shadcn/ui gives you accessible, unstyled primitives that you own. No dependency lock-in. I customized every component to match the F1 aesthetic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend: Hono
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://hono.dev" rel="noopener noreferrer"&gt;Hono&lt;/a&gt; is a 15KB web framework that runs everywhere — Node, Cloudflare Workers, Deno, Bun. I chose it for three reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Typed routes&lt;/strong&gt; — The &lt;code&gt;hono/client&lt;/code&gt; package gives you zero-runtime-overhead type inference. The frontend knows every route's request/response shape.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Middleware composition&lt;/strong&gt; — Rate limiting, auth, logging, body limits, CORS — all composable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt; — It's fast. Measurably fast.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Rate limiting tiers&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rateLimits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;mutations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;expensive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Database: Drizzle ORM + PostgreSQL + pgvector
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://orm.drizzle.team" rel="noopener noreferrer"&gt;Drizzle ORM&lt;/a&gt; is the sweet spot between raw SQL and heavy ORMs. Type-safe queries, zero runtime overhead, and the schema definitions are plain TypeScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;drivers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pgTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;drivers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;abbreviation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abbreviation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;nationality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nationality&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;dateOfBirth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;date_of_birth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I added &lt;code&gt;pgvector&lt;/code&gt; for semantic search on news articles — embedding articles with HuggingFace Transformers and querying by similarity. This lets users search F1 news by meaning, not just keywords.&lt;/p&gt;

&lt;h3&gt;
  
  
  Background Jobs: BullMQ + Redis
&lt;/h3&gt;

&lt;p&gt;Five job workers handle async processing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scoring worker&lt;/strong&gt; — calculates race scores and updates leaderboards&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;News sync&lt;/strong&gt; — fetches and processes F1 news articles&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email worker&lt;/strong&gt; — transactional emails via &lt;a href="https://react.email" rel="noopener noreferrer"&gt;React Email&lt;/a&gt; + &lt;a href="https://resend.com" rel="noopener noreferrer"&gt;Resend&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;F1DB sync&lt;/strong&gt; — auto-syncs historical data from &lt;a href="https://github.com/f1db/f1db" rel="noopener noreferrer"&gt;F1DB&lt;/a&gt;, the community-maintained open-source F1 dataset on GitHub&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task worker&lt;/strong&gt; — generic async tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bull Board provides an admin dashboard for monitoring all queues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Auth: BetterAuth + Passkeys
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://better-auth.com" rel="noopener noreferrer"&gt;BetterAuth&lt;/a&gt; handles OAuth (Google, Discord, X) and passkey/WebAuthn support. Passkeys are the future of auth — no passwords, phishing-resistant, biometric. It took one afternoon to set up.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: AI Agents as the Development Team
&lt;/h2&gt;

&lt;p&gt;This is the part that made 4 weeks possible.&lt;/p&gt;

&lt;p&gt;I used &lt;strong&gt;Claude Code&lt;/strong&gt;, &lt;strong&gt;OpenAI Codex&lt;/strong&gt;, and &lt;strong&gt;Gemini&lt;/strong&gt; throughout the entire build — not as autocomplete, but as collaborators that could hold the full codebase in context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt; was the core developer — writing, refactoring, and debugging code directly in the codebase. &lt;strong&gt;Claude, Codex, and Gemini&lt;/strong&gt; served as architects: every non-trivial feature went through an extensive design process where I'd gather perspectives from multiple models before settling on a final implementation plan. Different models catch different edge cases, and the overlap builds confidence.&lt;/p&gt;

&lt;h3&gt;
  
  
  What AI agents actually did
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Feature scaffolding.&lt;/strong&gt; I'd describe a feature ("add a predictions system where users pick drivers for each race, with a lock-of-the-week mechanic for bonus points"), and the agent would generate the schema, the service, the routes, the validation, and the frontend hooks. Not perfect on the first pass, but 80% there. I'd review, adjust, and iterate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parallel code reviews.&lt;/strong&gt; When I needed to migrate 50+ component files from hardcoded &lt;code&gt;bg-white/10&lt;/code&gt; opacity patterns to CSS custom properties for light mode support, I launched three AI agents in parallel — each handling a batch of files, following the same mapping guide. What would have been a full day of tedious find-and-replace was done in minutes with consistent results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debugging.&lt;/strong&gt; One example: the track circuit SVG component had a blur effect from 8 stacked CSS &lt;code&gt;drop-shadow&lt;/code&gt; filters that were compounding exponentially. The agent identified the root cause (each filter applies to the cumulative result of all previous filters), removed the outline system, and adjusted stroke widths — a fix I might have spent an hour on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency.&lt;/strong&gt; As the codebase grew past 50+ components, the AI kept patterns consistent — same naming conventions, same file structure, same validation approach. This is where solo developers usually start cutting corners.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why structure matters for AI
&lt;/h3&gt;

&lt;p&gt;Here's the key insight: &lt;strong&gt;AI agents are only as good as the patterns you give them.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ProjectX's opinionated architecture meant the AI always had guardrails:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It knew services go in &lt;code&gt;features/&amp;lt;name&amp;gt;/&amp;lt;name&amp;gt;.service.ts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;It knew validation uses Zod schemas in &lt;code&gt;features/&amp;lt;name&amp;gt;/validations.ts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;It knew routes are thin — they delegate to services&lt;/li&gt;
&lt;li&gt;It knew the frontend hooks follow TanStack Query conventions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without that consistency, you're just generating spaghetti faster. The framework wasn't just for me — it was for the AI too.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Deployment — Cheaper Than You Think
&lt;/h2&gt;

&lt;p&gt;The deployment story is one of my favorite parts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend: Cloudflare Workers
&lt;/h3&gt;

&lt;p&gt;TanStack Start builds to Cloudflare Workers via the Vite plugin. The frontend runs at the edge, globally distributed, with near-zero cold starts.&lt;/p&gt;

&lt;p&gt;Cost: practically free at this scale. Cloudflare's free tier is generous.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend: Railway
&lt;/h3&gt;

&lt;p&gt;Railway runs the Hono API, PostgreSQL, and Redis. Docker multi-stage build keeps the image lean. Health checks, auto-restarts, and deploy previews are built in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# railway.toml&lt;/span&gt;
&lt;span class="nn"&gt;[deploy]&lt;/span&gt;
&lt;span class="py"&gt;healthcheckPath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/health/ready"&lt;/span&gt;
&lt;span class="py"&gt;healthcheckTimeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;span class="py"&gt;restartPolicyType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"on_failure"&lt;/span&gt;
&lt;span class="py"&gt;restartPolicyMaxRetries&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CI/CD: GitHub Actions
&lt;/h3&gt;

&lt;p&gt;Two workflows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;CI&lt;/strong&gt; — lint, type-check, build, test on every PR&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy&lt;/strong&gt; — manual trigger, runs migrations first, then deploys API to Railway and frontend to Cloudflare
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Push to main → CI passes → Trigger deploy →
  Run migrations → Deploy API (Railway) → Deploy Web (Cloudflare)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Total monthly cost
&lt;/h3&gt;

&lt;p&gt;The entire production infrastructure — API server, PostgreSQL, Redis, edge-deployed frontend, CI/CD — costs approximately &lt;strong&gt;\$20/month&lt;/strong&gt; — or closer to ~\$10/month with serverless database and Redis options. No Kubernetes. No Terraform. No DevOps engineer.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Inside Formula1.Plus
&lt;/h2&gt;

&lt;p&gt;Here's what shipped in 4 weeks:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Predictions &amp;amp; Scoring&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Race predictions with driver and constructor picks&lt;/li&gt;
&lt;li&gt;Lock-of-the-week mechanic for bold predictions (bonus points)&lt;/li&gt;
&lt;li&gt;Last place picks, constructor top-3, bonus picks&lt;/li&gt;
&lt;li&gt;Automated scoring engine via background workers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Leaderboards &amp;amp; Leagues&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Live leaderboards with all-time and per-championship rankings&lt;/li&gt;
&lt;li&gt;Private leagues with invite codes&lt;/li&gt;
&lt;li&gt;League-specific leaderboards and standings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Telemetry &amp;amp; Data&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Driver DNA breakdowns and performance analysis&lt;/li&gt;
&lt;li&gt;Historical data auto-synced from &lt;a href="https://github.com/f1db/f1db" rel="noopener noreferrer"&gt;F1DB&lt;/a&gt;, a community-maintained open-source dataset&lt;/li&gt;
&lt;li&gt;Circuit profiles with past results and statistics&lt;/li&gt;
&lt;li&gt;Recharts-powered visualizations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Community&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grand Stand — polls, discussions, community engagement&lt;/li&gt;
&lt;li&gt;News aggregation with semantic search (pgvector)&lt;/li&gt;
&lt;li&gt;Activity feeds and social features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Admin&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Event management and prediction configuration&lt;/li&gt;
&lt;li&gt;Queue monitoring via Bull Board&lt;/li&gt;
&lt;li&gt;Audit logs, contact management, poll templates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Auth &amp;amp; Infrastructure&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OAuth (Google, Discord, X) + passkey/WebAuthn&lt;/li&gt;
&lt;li&gt;Rate limiting (tiered: global, mutations, expensive queries)&lt;/li&gt;
&lt;li&gt;OpenTelemetry for distributed tracing&lt;/li&gt;
&lt;li&gt;Structured logging with Pino&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/your-feature-screenshots" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/your-feature-screenshots" alt="Feature Overview" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The F1 season is approaching, and I'm getting early users in before Round 1.&lt;/p&gt;

&lt;p&gt;More importantly: &lt;strong&gt;ProjectX — the framework that made this possible — is going open source soon.&lt;/strong&gt; A single monorepo CLI that scaffolds web, mobile, and browser extensions with the full architecture out of the box.&lt;/p&gt;

&lt;p&gt;The plugin system, the CRUD generator, the Railway and Cloudflare deployment presets — all of it.&lt;/p&gt;

&lt;p&gt;If you want to follow the open source drop, I'll be posting updates on &lt;a href="https://dev.toyour-x-url"&gt;X/Twitter&lt;/a&gt; and the repo will be at &lt;a href="https://dev.toyour-github-url"&gt;github.com/your-handle/projectx&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Built a full F1 fantasy platform in 4 weeks, solo&lt;/li&gt;
&lt;li&gt;Built a CLI framework first to eliminate boilerplate (ProjectX)&lt;/li&gt;
&lt;li&gt;Used AI agents as pair programmers, not just autocomplete&lt;/li&gt;
&lt;li&gt;Stack: TanStack Start + Hono + Drizzle + PostgreSQL + Redis&lt;/li&gt;
&lt;li&gt;Deployed to Cloudflare Workers + Railway for approximately \$20/month (~\$10 with serverless options)&lt;/li&gt;
&lt;li&gt;ProjectX going open source soon&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://formula1.plus" rel="noopener noreferrer"&gt;formula1.plus&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What questions do you have about the build, the stack, or AI-assisted development? I'll be in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>typescript</category>
      <category>react</category>
    </item>
  </channel>
</rss>
