← Back to projects

Devlog

Notes on the decisions behind each build, including what was cut and why. Newest first.

Shipping a CV link tracker in a weekend

An application goes out and the only signal that comes back is a reply or silence. I wanted the layer underneath that: whether the links on my CV were being opened at all.

The result is a small Node/Express service sitting behind one tracked link. The same URL works as a scannable QR code on a printed CV and as a plain hyperlink in the PDF version, with a via flag in the querystring telling the two apart once the data lands.

Scoping the build

Postgres was disproportionate for a handful of opens a day, so the data goes into a Google Sheet through a small Apps Script endpoint. It serves as both the dashboard and a one-click CSV export at no cost. Notifications followed the same reasoning: Telegram's Bot API requires no business approval and carries no per-message charge, while WhatsApp's Business API would have introduced real cost for a personal tool.

Each conventional choice would have added cost or setup time to serve roughly thirty events a month.

The QR codes took the most iteration. Each carries the destination platform's logo in the centre — LinkedIn on one, Instagram on the other — because an unmarked QR block on a CV gives the reader no indication of where it leads. Covering the centre of a code requires generating it at "H" error correction, which reserves enough redundancy for roughly a third of the code to be obscured and still scan. Below that level, the logo breaks it.

What it logs

  • Time of the open, and which link was opened
  • Rough location and device, from the request
  • Source — scan versus PDF click — off the via flag

Placement on the CV mattered more than expected. Rather than grouping the codes in a corner, each sits beside the section it relates to: LinkedIn next to Experience, Instagram next to Side Projects, so it appears at the point the reader is already engaged with that section.

It is live and tracking opens on the CV in circulation. The next version makes tracking dynamic per application, so each CV sent to a specific company is a separate tracked object rather than aggregating into a single counter.

Live site → Code → All projects →
In progress: notes on Sourceter's successive rewrites, and on R.E.M. moving from estimated REM to wearable-read sleep staging.