Ask F1
Natural-language questions over 75 seasons of Formula 1 data
Personal project · 2026 · Full-stack
C#
.NET 10
EF Core
PostgreSQL
Google Gemini
Clerk
React
TypeScript
Vite
TanStack Query
Tailwind CSS
Python
Docker
Railway
Neon
GitHub Actions
- Ask a question in plain English — "Who won the most races at Monza?" — and get a natural-language answer backed by real data, generated on the fly from a 75-season F1 database via text-to-SQL
- Kept the LLM's blast radius small with a guarded pipeline: Gemini, via Microsoft.Extensions.AI, produces a single SELECT, a SqlGuard step rejects multi-statement input and any write or DDL keyword, and execution runs as a read-only Postgres role inside a READ ONLY transaction with a 5-second statement timeout and an enforced LIMIT, before Gemini summarizes the rows
- Built the API in ASP.NET Core on .NET 10 with Clerk JWT authentication and first-sign-in user provisioning, EF Core used to author migrations that ship as reviewed idempotent SQL, and HybridCache answer caching keyed by a version bumped whenever prompts or the dataset change
- Guarded cost and abuse with a per-user daily question quota plus fixed-window rate limiting in front of the LLM, and persisted every question so users can review their history
- Wrote a two-stage offline data pipeline: a Python script cleans the raw Kaggle CSVs (null normalization, country and status canonicalization, lap-time parsing with anomaly cross-checks, referential-integrity validation and a generated report), then a .NET CLI bulk-loads them through Npgsql binary COPY in foreign-key-safe order inside one re-runnable transaction — about 700k rows across 14 tables
- Shipped a chat-style React 19 frontend on Vite with Clerk and TanStack Query, and deployed both apps on Railway with Neon Postgres — the backend as a multi-stage Docker image, the frontend as a static build, both with GitHub Actions CI