All work
Case Study — Job Search Crawler  ·  7 min read
AI Product Side Project Automation

I Built My Own Way Out

I went looking for a UX role in one of the roughest tech markets in years. Instead of grinding LinkedIn every morning, I built an AI tool to run the search for me, end to end: data pipeline, job-fit scoring, daily email digest, all designed and built solo.

Poke at the real thing

Not a mockup. Launch the full, live app loaded with read-only demo data: real listings, real AI job-fit scores, and the actual interface I open every morning.

Launch the live demo (read-only) ↗
$1–2/mo
AI scoring cost, down from about $50 a month
12+
Data sources scanned, tens of thousands of companies daily
5
Factor job-fit score, fully transparent and inspectable
8am
A ranked, AI-evaluated email digest, every morning
Role Solo: product, design, and build
Stack React, Next.js, TypeScript, Supabase, Vercel, scheduled crawl via GitHub Actions + cron-job.org
Built with Claude Code, Claude, and ChatGPT for the build; ATS, aggregator, and board APIs (Ashby, Greenhouse, Lever, Workday, BambooHR, iCIMS, Adzuna, JSearch, The Muse, Dribbble, Built In)

Scratch your own itch

I went looking for a UX role in one of the roughest tech markets in years. The obvious move was to open LinkedIn every morning and start scrolling. Instead I asked a different question: I'm a product designer who works on AI products all day. Could I build my own?

So I did. The Job Search Crawler kicks off every morning at 8am, takes around twenty minutes to scan more than a dozen job sources, scores every role against my actual experience, and emails me a ranked, AI-evaluated shortlist. I designed it, specced it, and built it solo, using a stack of APIs and tools I had never touched before. AI wrote most of the code. I made the decisions.

Product manager for a team of one

I scoped this the way I'd scope any product: the smallest thing that proves the idea. A search feed, basic filters, a database. I ideated the architecture with Claude and ChatGPT, weighing options I didn't fully understand at first and learning enough to make an informed call on each one.

The stack came together fast, and most of it was free. Supabase for the database, GitHub to host the repo, Vercel for the app, React, Next.js, and TypeScript for the UI. The crawl runs on a schedule, kicked off by cron-job.org, an external timer service that pings the job on time, after the scheduler I started with kept drifting and skipping runs. Hosting, database, and email all sit on free tiers, which still feels a little like magic after years of paying a hundred dollars a year just to host a basic site. The real costs are the parts doing the thinking: a $20 a month Claude subscription that powers the build through Claude Code, plus the data and AI APIs I get to below.

TRIGGER Timer cron-job.org · 8am daily WORKFLOW GitHub Actions runs the crawl in the repo 12+ SOURCES Mixed Sources ATS · aggregators · boards 80K → 7K Dedup drop duplicate listings FIRST PASS Keyword Scoring title, salary, AI keywords LLM Job-Fit Scoring 0–100 across 5 factors STORE Supabase Postgres database DELIVER Dashboard Daily email digest One scheduled run, about 20 minutes end to end, every morning.
The pipeline: a timer kicks off a scheduled crawl across a dozen sources, then dedup, keyword and AI job-fit scoring, into Supabase and out to the dashboard and a daily email.

The hard part was the data

The feed is only as good as what feeds it. My first version pulled from a small, hardcoded list of companies and ran them one at a time. Fine for a demo. Useless for an actual search.

So the real engineering challenge became sourcing. The crawler pulls from more than a dozen sources of three kinds: the major applicant tracking systems companies post through directly (Ashby, Greenhouse, Lever, Workday, BambooHR, iCIMS), aggregator APIs like Adzuna, JSearch, and The Muse, and design-specific boards like Dribbble and Built In. The ATS pages matter most. They're the canonical source, before a listing ever syndicates out to LinkedIn or Indeed and goes stale. I scaled the company list from a few dozen to tens of thousands across the ATS platforms and added a concurrency pool so the crawl fires dozens of requests in parallel instead of plodding through them one by one. One of the aggregator APIs runs about $25 a month, and I blew past its request cap once before I added usage tracking. Going from a handful of companies to tens of thousands is the difference between a toy and a tool, and most of the hard problems lived right here.

Post directly · canonical
ATS platforms
AshbyGreenhouseLeverWorkdayBambooHRiCIMS
Broad coverage
Aggregator APIs
AdzunaJSearchThe Muse
Design-specific
Design boards
DribbbleBuilt In
More than a dozen sources of three kinds. The ATS platforms matter most: the canonical source companies post to directly, before listings syndicate out and go stale.
Before dedup
~80,000
listings, many duplicated
After dedup
~7,000
unique roles
Tightening the dedup pass collapsed the database from around 80,000 listings to roughly 7,000 unique roles.

Sorting signal from noise

Early on the feed was a mess. I'd ask for senior roles and get junior ones. I'd ask for product designer and get product managers, because the word "product" sat in the title.

I built a first-pass scoring layer with Claude to push the stronger listings up: correct titles, salary listed, benefits mentioned, AI in the mix. It was mostly keyword matching, and it did its job. It screened out the obvious noise. But the top of the stack was still haphazard. Every promising role still needed me to read it and judge whether my background actually fit. That was the next problem worth solving.

Opening the black box

This is the part I care about most, because it's the same problem I design for professionally.

I added an AI job-fit evaluation layer. Every promising role gets read by an LLM and compared against a detailed record of my experience that lives in the project. The model returns a 0 to 100 job-fit score, and suddenly the roles I'd actually want were rising to the top on their own.

But a single number is a black box. What does an 80 even mean? Why 80 and not 65? Any user would ask that, so I did the work to make the score defensible. I researched how to evaluate job fit more rigorously, then broke the score into five dimensions: Role and skills, Company health, Compensation, Industry fit, and Growth signals. I added a short AI summary on each listing and a full breakdown on the detail page, so the score isn't a verdict handed down. It's a transparent argument I can inspect.

This is LLM-as-judge work, and it's the same evaluation-interface and model-trust design I do at the day job: deciding what the model scores, how it explains itself, and where the human stays in control. I just pointed it at my own problem.

Where the AI made odd choices

Letting AI write the code was a genuine accelerant. Whenever I hit something I didn't know how to do, the answer came back in seconds. But AI doesn't flag its own bad decisions. You only find them by paying attention.

Two of them cost me real money. The app was re-scoring my entire database on every crawl, thousands of paid API calls to re-evaluate roles it had already scored. I rewrote the logic to check for an existing score before calling the model. The bigger one was duplicates. My first dedup pass looked robust and wasn't. When I tightened it, the database dropped from around 80,000 listings to roughly 7,000. I'd been storing, scoring, and paying for the same jobs over and over.

Then I right-sized the model. I'd started on Claude Opus 4.7, a top-tier model that was overkill for comparing a job post to a resume and was burning $30 to $50 a month. I moved to Claude Haiku for the same quality at a fraction of the cost, then to ChatGPT nano, which dropped it again. The scoring now runs for a dollar or two a month.

MONTHLY AI SPEND $30–50 / mo Claude Opus 4.7 top-tier, overkill $10–20 / mo Claude Haiku same quality $1–2 / mo ChatGPT nano runs here now Right-sizing the model took scoring from $30–50 to $1–2 a month.
Monthly AI spend dropped across model swaps: Claude Opus 4.7, then Claude Haiku, then ChatGPT nano.

Making it mine

The first UI was a generic component-library default, and it felt like one. For a tool I'd open every morning, that wasn't good enough. I rebuilt it in the dark, glassmorphic style of my portfolio, with the small interaction details that make something feel considered. If I was going to live in it, I wanted it to be something I was proud of.

The real problem isn't finding jobs

Finding roles turned out to be the easy half. The hard half is reaching a human on the other side. Applications vanish into a black hole of hundreds or thousands of applicants, where no feedback comes back save the automated rejection email. Referrals and recruiter conversations are what actually move.

So that's where the product goes next. The roadmap maps a user's network against companies that are hiring, surfacing where a warm referral is one introduction away, and drafts personalized recruiter follow-ups after you apply. One rule sits underneath all of it: the AI drafts, it never sends. That's the same human-in-control principle I hold to in my professional AI work. The tool does the legwork. The person owns every message that goes out.

Did it work?

Yes, with an honest caveat. Every morning I review a ranked, scored, pre-summarized shortlist in a few minutes instead of scrolling job boards for an hour. The signal-to-noise is dramatically better, and the time it hands back is real.

What it hasn't solved is the brutal math of the current market. A strong tech role still draws hundreds of applicants, and a better-organized search doesn't change those odds on its own. That's exactly why the next chapter is about people, not listings.

But the project answered the question I started with. As a product designer, can I independently scope, design, and ship a working AI product? This is the proof. Not a prototype, not a mockup. Something I use every single day.

← Back to all work
AI Model Training Concept preview

Let's
talk.

Open to Senior or Staff UX design roles in enterprise, AI, or consumer. Available now.