Job Radar

A daily job-intelligence pipeline that merges hundreds of remote postings, filters them with config-driven rules and scores the survivors against my profile with an explainable formula.

Role
Solo: design, build, deployment
Period
2026
Status
Deployed on a GCP Always Free VM, scheduled daily at 07:00 Tunis time
Stack
n8n, Docker, GCP e2-micro, Google Sheets, Groq, Gemini, Discord, REST APIs, RSS

The problem

Remote junior roles in automation and GTM engineering are scattered across a dozen boards, most postings are a poor fit (wrong seniority, wrong region, a language I do not speak), and reading them by hand every morning does not scale. I wanted a ranked shortlist with reasons, built at no cost, that I could tune without touching code.

What I built

One n8n workflow, deployed on a free cloud VM, runs every morning.

  1. Sources
  2. Filter before the model
  3. Extract and score
  4. DeliverWrites matches, ops, Discord
  5. My reviewI give every match a verdict (good, false positive, applied). The verdicts drive the next tuning change.

Config tabThresholds, keyword lists and weights, with a revision number for every change.

One workflow, run every morning.
  1. Ingest. 12 sources are wired and 11 enabledSource: workflow export and config tab. October 2026.: public APIs, RSS feeds and community job boards. Each source has its own mapper and its own filters, because each has its own noise.
  2. Filter before the LLM. Deduplication by URL, a posting-age window, remote-only, a senior-title veto and banned phrases. Only a capped batch moves on: at most 15 postings per runSource: config tab slice_cap (v4). October 2026..
  3. Extract and score. An LLM returns strict JSON (seniority, work policy, languages, visa mention, contract-friendliness). A weighted formula combines it with rule-based fit and recency: 0.40 match, 0.25 filter fit, 0.20 feasibility and 0.15 recency, with a pass mark of 65Source: SPEC v3.2 section 8. September 2026..
  4. Deliver. Matches go to a sheet with the reason and red flags for each, telemetry goes to an ops tab, and a Discord digest lists the best ones.

All thresholds, keyword lists and weights live in a config tab. Tuning is a sheet edit with a revision number, never a code change.

Decisions that mattered

ADR-JR-08Dynamic config in a sheet tab
Context
Thresholds and keyword lists changed weekly during tuning.
Decision
A key/value config tab, parsed by a Load Config node with typed coercion, defaults and a warnings list.
Trade-offs
Every behavior change is a sheet edit; a bad value falls back to its default with a warning instead of breaking the run.

Open ADR-JR-08 in the decision log

ADR-JR-17Calibration as data
Context
Output quality tuning tempted code edits.
Decision
All quality tuning happens in the config tab with a rev bump: one variable per change, one ops row as evidence.
Trade-offs
Slower tuning, but every change is traceable to a run.

Open ADR-JR-17 in the decision log

ADR-JR-16GCP Always Free VM for deployment
Context
The pipeline must run daily at $0 without the laptop on.
Decision
Docker on a GCP e2-micro Always Free VM, port bound to localhost and reached through an SSH tunnel, with a $1 budget alert as an alarm.
Trade-offs
Small VM (swap required); no public UI exposure by design.

Open ADR-JR-16 in the decision log

What broke, and what I changed

A provider outage. On 15 September Groq returned 401 and one Gemini model returned 404, and the remaining route scored 24 of 24 postingsSource: ops tab 2026-09-15 09:33. 15 September 2026.. The run finished on the last route in the chain, which is why the chain exists.

An n8n update blocked environment variables. On 21 September a run failed with ‘access to env vars denied’ for every provider, and it was fixed and re-run 14 minutes later with 25 of 25 scoredSource: ops tab 2026-09-21. 21 September 2026.. The ops row showed the exact error for every provider, so the fix took one setting, not a debugging session.

Results

active job sources (12 wired)
11Source: workflow export and config tab. October 2026.
postings merged per full run
466 to 617Source: ops tab, full runs. September 2026.
at most this many reach the LLM per run
15Source: config tab slice_cap (v4). October 2026.
infrastructure cost
$0Source: SPEC v3.2. September 2026.

What I would do next

  • Finish calibration: one week of reviewed matches, then set the score threshold at the elbow of the distribution.
  • Reuse the router and config pattern in other workflows (the Personal GTM Engine already does).