Case study
Job-Search Intelligence App
A single-user Python and SQLite application that ingests job postings through a third-party data API, scores them against a weighted rubric that shows its reasoning, and tracks the pipeline through a single confirmed-write path.
- Role
- Sole developer
- Organization
- Personal project
- Status
- Shipped
- Python
- SQLite
- SQL
- JavaScript
- HTML5
- CSS
Walkthrough
Screens

The morning view. Headline numbers, filters, and a Needs Action list that says why each posting is there. Company names in every screenshot are anonymized to Employer NN placeholders. 
Every score comes with its reasons. The four components and their denominators are stored with the row and shown here, so a number can be argued with. 
The pipeline board. Drag a card to change its status; the drop is the confirmation and undo is one click away. Every transition is logged by a database trigger. 
Scan telemetry and score distribution. Every chart has a table twin, and a scan that has never run is shown explicitly rather than missing. 
The analytics describe and never recommend. The guard rail is stated in the interface, and breakdowns refuse to report a percentage below a minimum sample.
In one minute
A local desktop app that replaced a broken Excel job tracker. Every weekday morning it pulls new postings, scores each one against a rubric that explains itself, and puts the ones worth acting on at the top of a board.
The problem
- An Excel workbook fed by third-party scheduled scans. Both halves failed at once: the scan triggers were deleted, and the workbook could not be written to while it was open.
- No record of status changes, so funnel and velocity questions could not be answered.
- Match scores were an opaque number nobody could interrogate or correct.
What I built
- Own the acquisition. Postings are ingested through a third-party data API on a schedule, with spend treated as a correctness concern: a monthly budget pre-flight can refuse a run, and a dry-run mode prints the worst-case cost before spending anything.
- A rubric that shows its work. 100 points across title (45), skills (35), seniority (10) and location (10). The score and its reasons are stored together and shown in the UI and every export. Missing evidence lowers confidence rather than raising the score.
- One way to change a row. Status edits, drag-and-drop and undo all go through the same
backend
plan → confirm → applypath; a database trigger writes the history so no code path can skip it. - Analytics that know when to stay quiet. Conversion rates return “not available” with a reason instead of 0% over an empty sample, and the composition panel describes the pipeline without recommending anything.
- Application materials from a locked template. Documents are assembled by copying a template and rewriting only the wording paragraphs; the fact paragraphs are locked and the assembler raises if anything tries to write to them.
Rules the whole system enforces
- A number never travels without its denominator.
- Unknown is a state, not a zero.
- History is never rewritten: a posting keeps the search title that found it, permanently.
- Anything irreversible needs confirmation; anything reversible gets undo instead.
Outcome
- Its own export produced the market read behind this site’s positioning: Power BI and SQL led the tracked postings, and governance vocabulary (NIST, GRC, SOX, ISO 27001) appeared often enough to be the differentiator rather than a footnote.
- Runs unattended on weekday mornings; every planned item shipped.
- No accuracy or time-saved figure is claimed, because nothing in the app measures one. That is the same rule the app applies to itself.
Stack
Python 3.13 · SQLite (WAL, triggers, CHECK constraints) · hand-written HTML/CSS/JS with no
framework · pywebview desktop window · no build step.