I built an AI job-search agent solo — here's the full stack
I spent the last couple of months building Reclaim — an AI job-search agent for engineers, done solo, taking up nights and weekends. It reads your résumé, scores it honestly, and matches you against real open roles. It's live at reclaim.careers (free scan, no signup). This isn't a launch post — it's a breakdown of the stack and, more usefully, the things that broke. Here's how it's built. The stack Frontend — Next.js on Vercel. App Router, server components where it made sense. Vercel for hosting because the deploy-on-push loop is frictionless and I was optimizing for solo velocity, not infra control. Backend — FastAPI on Render. I split the Python backend out rather than doing everything in Next API routes, because the heavy lifting (résumé parsing, the matching pipeline, scraping) is Python-native and I wanted it isolated from the frontend's request lifecycle. Database — Supabase + Prisma. Postgres under the hood. Prisma for the schema and type-safe queries; Supabase for the managed Postgres and some auth-adjacent data. Auth — Clerk. Handles sign-up, sessions, the whole identity layer. More on Clerk below, because it's where I lost the most hours. Payments — Stripe. Live mode, subscription tiers with a trial. Lookup keys drive tier resolution in the webhook so pricing changes don't require code changes. The actual "AI" — Gemini. This is the interesting part, so it gets its own section. Gemini does the real work The thing I care about most: the AI isn't a chatbot bolted on the side. Gemini makes the actual product decisions. Résumé reading: parse the PDF, extract real structure, and score it — not against keyword density, but against whether the claims are substantiated. The whole premise is honesty: most AI résumé tools keyword-stuff to beat the ATS, which backfires the second you're in an interview and can't back up your own résumé. Reclaim does the opposite — it flags where you're genuinely strong and where you're stretching. Matching: scores the résumé against