om anand/ still building
← BACK
CASE STUDY · APR 2025 → NOW

cold emails that read like I actually looked at the company

I was applying to a lot of places badly. So I built the thing that reads my resume, reads the company, and writes the email I would have written if I had two more hours.

drop the main screenshot for this project
1 minRESUME UPLOAD → PERSONALISED DRAFT

Upload, parse, enrich with company context, generate. The rate limiter exists because the first version could have made me a spammer in an afternoon, and I'd rather the tool have a conscience than not.

PDF→JSONRESUME PARSING
per-domainRATE LIMITING
FastAPIBACKEND
draftsNEVER AUTO-SENDS
FIG.2 — FROM A PDF TO SOMETHING WORTH SENDING
01uploadresume inPDF, whatever format02parserstructure itskills, projects,dates03contextread the companywhat they build, whofor04llmwrite the draftspecific, short, notfawning05limiterthrottle mecaps per domain perday
01upload
resume inPDF, whatever format
02parser
structure itskills, projects, dates
03context
read the companywhat they build, who for
04llm
write the draftspecific, short, not fawning
05limiter
throttle mecaps per domain per day
  • fastapi — upload, parse, generate
  • worker — parsing and enrichment off the request path
  • store — drafts and per-domain send counters
DECISIONS, AND WHAT THEY COST ME
nothing here was free
I CHOSE
drafts only, never auto-send
BECAUSE
An automated system emailing strangers in my name is a reputational risk I'm not taking for convenience.
IT COST ME
I still have to press send, which means I sometimes don't
I CHOSE
rate limiting from day one
BECAUSE
The honest version of this tool sends fewer, better emails. Volume is what makes it spam.
IT COST ME
deliberately capped the thing's main capability
I CHOSE
parse to structured JSON first
BECAUSE
Handing a raw PDF to a model gave vague emails. Structure made the output specific.
IT COST ME
parsing is brittle across odd resume layouts
I CHOSE
company context before generation
BECAUSE
"I admire your work" is worthless. Naming what they actually build isn't.
IT COST ME
another API call and a cache to keep it cheap