Back to projects

In plain English

Apply AI finds you a job. You give it your CV and the kinds of roles you want, and it searches job sites across the web, ranks the ones that actually fit you, and even writes a first draft of your cover letter. Hours of searching become a few minutes.

AI job-search tool · Solo build

Apply AI

An AI tool that takes the grind out of job hunting. Upload your CV, choose the titles and roles you're after, and it scans 11 sources across the web (Jobindex, The Hub, LinkedIn, Greenhouse, Lever, HN "Who is hiring", +5 more), scores every result against your CV via Claude, drafts cover letters, and surfaces what to learn next from the roles you're closest to landing. Runs locally, so your CV never leaves your machine.

ProductAI engineering
Apply AI job scanner showing 185 jobs ranked against the CV, with filters and AI-role tags
The scanner: every job ranked against your CV. This run found 185 jobs, 179 AI-relevant, 60 strong matches, each with one-click analyze.

How it works

Upload your CV, pick your targets, let it scan

Drop in your CV, set the titles and roles you want plus filters like comp floor and dealbreakers, and Apply AI scans the web, scores each job against your CV, and drafts the cover letters. Everything runs locally, so your data stays yours.

By the numbers (latest scan)

Raw scraped

2,743

Across 11 sources in 30-45s

After dedup

993

URL canonicalisation, ~64% noise removed

Scored

185

Word-boundary keyword match + role tier weights

Stack cost

~$3/mo

Claude via OpenRouter, prompt caching on

Why I built this

Job hunting is mostly tedious filtering. The same roles get cross-posted across Jobindex, The Hub, LinkedIn and a dozen ATS platforms, half the "AI" jobs aren't actually AI-central, and reading every description to judge fit eats hours. I wanted to compress that loop.

So I built a tool that does it for you. Point it at your CV and the roles you want, and in about 30 seconds it pulls jobs from 11 sources, scores each one against your CV, and drops anything off-target like crypto or gambling. Claude then reads the strongest matches, writes a fit verdict and a cover-letter draft, and the dashboard shows you which skills keep coming up in the roles you should be landing.

Local-only by design: your CV and search data never leave your machine. And the build itself is the point, a small showcase of how I approach a messy problem: automate the tedious part, keep a human in the loop for the judgment calls.

How the pipeline works

Five stages from raw job feeds to a ranked list with cover letters drafted and skill-gap insights surfaced.

1

Scan 11 sources at once

Pulls jobs from 11 places at the same time (Jobindex, The Hub, LinkedIn, several ATS platforms, HN's "Who is hiring", and more). If one site is down, the rest still come through. A typical run gathers around 2,700 jobs in 30 to 45 seconds.

2

Remove the duplicates

The same role gets cross-posted everywhere, so it strips out the repeats and keeps one clean copy of each. On the last run that took about 2,700 raw listings down to under 1,000 real ones.

3

Score each job against your CV

Weights the roles you actually want more heavily, adds a bonus when a job is genuinely AI-focused, and drops anything in crypto, gambling, or defense to zero so it never wastes the budget on roles you'd skip anyway.

4

Claude reads and drafts

Claude reads the strongest matches against your CV, writes a fit verdict and a cover-letter draft, and skips anything it has already analysed. Caching keeps each one at roughly one to three cents.

5

Insights and apply tracking

A dashboard pulls it all together: the skills that keep coming up that you're missing, companies you keep meaning to apply to but never do, and a one-click way to mark what you've applied for.

Key features

11-source parallel scanner

Jobindex, The Hub, LinkedIn, IT Jobbank, Work in Denmark, AI Jobs, Remote OK, We Work Remotely, 5 ATS platforms, HN "Who is hiring". 30-45s wall time.

Hard-reject filter

Drops crypto / web3 / blockchain / gambling / weapons / surveillance jobs to 0 before they hit the analysis budget.

AI context bonus

Design or PM role + JD mentions ≥2 AI primary skills = +10. Lifts "Senior Product Designer at Lovable" above "Senior Product Designer at Maersk".

Claude with prompt caching

OpenRouter + Anthropic ephemeral cache on the system prompt. Content-hash skip on identical inputs. 3× retry with exponential backoff.

Cover letter drafts

Per-job cover letter using the 'strong' matched requirements only. Voice samples from your CV so the output sounds like you, not a template.

Insights + project recommender

45-skill ontology aggregates across all analyses. Surfaces weak skills with example roles, companies you keep analysing but never apply to, and Claude-generated weekend-sized projects to close the gaps.

Tech stack

Frontend

Next.js 16React 19TypeScriptMUI v9Tailwind 4

Material Design 3 dark theme (violet primary, MD3 surface tones), full migration from shadcn/ui to MUI v9 + Emotion. Tailwind kept for layout utilities.

Scanner

Node.jsxml2jsHN Algolia API

11 scrapers (RSS + HTML + JSON APIs). Direct ATS scraping for Greenhouse, Lever, Ashby, Teamtailor, Recruitee. Parallel via Promise.all with per-family try/catch.

AI

Claude (via OpenRouter)Anthropic prompt cache

cache_control: ephemeral on the static system prompt. 3× retry with 1/3/7s backoff. Content-hash cache via sha256(jdText + profile) to skip identical re-analyses.

Storage

JSON files

No database. Everything lives in data/*.json (profile, analyses, scanner jobs, seen URLs, scan status). One-user tool, file storage is enough.

Under the hood

Each job source is its own scraper and they all run in parallel, so one dead site never takes down a scan. Results get deduped, scored against your CV with layered rules, and only the strongest 30-50 are sent to Claude for the expensive part.

Claude calls reuse a cached prompt and skip anything already analysed, which keeps the whole thing running at a few dollars a month. Everything lives in plain local files, no database, because it's a one-person tool.

Brand & creative

Marketing posters and animated creative

Two brand posters and an animated 9:16 creative generated with Pomelli, Google's AI brand toolkit, to give the tool a real identity and test how far an AI brand kit can carry a product look from a single prompt.

Apply AI brand posterBrand poster
Apply AI value-prop posterValue prop
Animated MP4

Common questions

Why does it run locally?+

So your CV and job data never touch a server, mine or anyone else's. The whole profile, analyses, scraped jobs and seen-URL memory live in local JSON files on your machine. It also keeps running costs near zero, since the only paid call is the Claude analysis.

How much does it actually cost to run?+

Roughly $3/month at my volume. Scraping is free. Claude analysis is the only paid call, and prompt caching plus the content-hash skip mean most analyses cost $0.01-$0.03 each. I run a full scan + analyse maybe 3-4 times a week.

Does the scoring actually work?+

Yes after the word-boundary fix. Before that, 'ai' matched 'available' and 'said' and 'email', so every Salesforce job scored well. The hardest single bug to find: a regex that was technically working but producing nonsense rankings. After the fix + tiered role weights + AI context bonus, the top 10 every morning are roles I'd actually apply to.

What's the AI doing that a smart regex couldn't?+

Two things. (1) Reading the prose of a JD to extract requirements that aren't bullet-listed (a lot of senior roles bury the actual ask in a paragraph). (2) Generating a per-job cover letter that mentions the matched requirements specifically. The hard scoring + filtering is regex; the per-job analysis and writing is Claude.

Open source?+

Not yet, but it's built to generalise. The CV and target roles are the personalisation layer, so nothing is hardcoded to one person. If there's interest, packaging it up as something others can run is the obvious next step.

What I learned

  • ·A tiny detail can make or break the whole tool. One bad line in the scoring (matching "ai" inside "email") quietly ruined every ranking until I found it. With AI products, the boring plumbing matters more than the model.
  • ·Caching the AI calls is basically free money. Reusing the same prompt and skipping anything already analysed cut the cost by about 70%, the difference between a tool I keep running and one I'd switch off.
  • ·Keep a human in the loop where judgment matters. The tool ranks, filters, and drafts, but I still decide what to apply to. Automate the tedious 90%, leave the last 10% to a person, that's the pattern I keep coming back to.

What's next

Honest roadmap. Things I know are gaps, in priority order.

True CV upload + parsing

Right now the profile is structured by hand. Parsing an uploaded CV (PDF or LinkedIn export) straight into the profile + voice samples would make setup a 30-second job instead of a form.

Embeddings for skill matching

Skill ontology is 45 entries with manual alias lists. Embeddings (Voyage or OpenAI small) would catch the synonyms I forgot to add. Probably overkill at this corpus size, but the false-negatives bug me.

Hosted version with accounts

Today it's a local instance. A hosted version with per-user accounts and isolated storage would turn it from my workflow into something anyone could point at their own CV and targets.

Daily Telegram digest

Right now you open the dashboard. A daily push of 'today's 5 top-scored matches' would let you triage from your phone before the laptop opens.

Like the approach? Let's talk

More projects

Next.js 16React 19TypeScriptMUI v9Tailwind 4Framer MotionClaudeOpenRouterAnthropic prompt cachexml2jsNode.js