Case 01 · Radar

A CRM of my own for the job search

I ran my job search like a sales pipeline. When the tool got too heavy, I built my own.

811 applications migrated, with history, notes and CVs From plan to a live system holding the whole history: 2 days 0 tables left in HubSpot after the migration
The problem

Since August I have tracked applications in a real CRM, with stages, a reason for every closed one and a note per contact, because a serious search has the same problem as a sales pipeline: volume, dispersion and silence. HubSpot solved that for two months.

Then it stopped serving. Every application took too many clicks, the fields that mattered to me did not exist in the default, and the fit evaluation an AI agent was already doing for each job had nowhere to live.

What stood
Applications migrated811, with 980 notes and 245 PDFs verified
From plan to the whole history live2 days (October 12 to 13, 2026)
DeployA push to the main branch publishes to production
BackupDaily, server plus cloud, verified
What I decided
  • Separate and temporary. Radar lasts as long as the search does. It was born with a written shutdown plan on day one: export everything, take the last backup, remove the container. A system that knows when it will die is a system that never becomes debt.
  • Small on purpose. One process, a SQLite database on a volume, 200 MB of memory on a shared server. Postgres would have been one more container and one more backup to look after. An operating decision, not a taste.
  • Migrate with reconciliation, never dual-write. HubSpot stayed as a mirror until switch day. The import was checked item by item: 811 deals became 793 applications and 18 merged duplicates, with 980 notes and 245 CVs in PDF.
  • Fit as a system field. Every job comes in with a 0 to 100 fit score, calculated by an agent that reads the description and applies my elimination criteria before any CV work. Radar keeps the number and the reason.
  • Gmail comes in, but never takes over. Google login restricted to one e-mail, read and send through OAuth. The system never moves, labels or deletes anything in the inbox.
  • New application from a link. Pasting the job URL fills in company, role, location, work mode and description. What the site does not expose as structured data, the system reads from the HTML.
  • Backup before features. A daily copy on the server and on B2, encrypted, with an integrity check. That was live before the second screen existed.
The human part

The previous CRM showed me something uncomfortable: I was applying to jobs outside my target, and I only noticed a month later, in an audit. Radar exists so that this shows up on the spot. A low fit closes the job before the CV. An elimination criterion closes it before the fit.

Funnel discipline is the same thing in a sales team and in a career. Only the person on the other side changes.

Next.jsReactSQLiteDockerNginxGitHub ActionsGoogle OAuthBackblaze B2Claude Code

The demo runs the same code as my real instance, with fictional companies and people. Anything you change is reset every hour.