A Firefox WebExtension that integrates with the Job Relevance Filter backend. It scrapes LinkedIn job postings, listens for job applications, and matches jobs against your CV — all synced to a local API at http://localhost:8050.
- 📋 Auto-sync applied jobs — when you click "Apply" on LinkedIn, the job is automatically sent to the backend
- 📁 Sync job tracker history — opens the LinkedIn Jobs Tracker and paginates through all applied jobs, extracting job details from each page
- 🎯 Match jobs to your profile — calls the backend API to score a job's relevance against your extracted CV profile
- ⏰ Daily sync alarm — automatically opens the Jobs Tracker once per day (if more than 24 hours since last sync) to keep your applied jobs up to date
- 🔗 Works with the Job Relevance Filter dashboard — all synced data appears in the dashboard's job table and tracking board
- Firefox (uses Manifest V2 WebExtensions API)
- Job Relevance Filter backend running at
http://localhost:8050 - Node.js and npm (for building)
git clone https://github.com/udsey/linkedin-extension.git
cd linkedin-extension
# Install dependencies
npm install
# Build bundled scripts into dist/
npm run buildMake sure the Job Relevance Filter dashboard is running:
# In the job-relevance-filter directory
make dashboardThe API will be available at http://localhost:8050.
- Open Firefox and navigate to
about:debugging#/runtime/this-firefox - Click Load Temporary Add-on...
- Select
manifest.jsonfrom thelinkedin-extensiondirectory
The extension is now active. Navigate to any LinkedIn job search page to see it in action.
Injected on LinkedIn job search and job view pages (/jobs/search/*, /jobs/collections/recommended/*, /jobs/view/*). It:
- Waits for the "Apply" button to render on the page
- Parses the current job's details (title, company, location, posted time, description)
- Attaches a click listener to the apply button
- When clicked, sends the job data to
POST /api/sync-jobson the backend
Injected on the Jobs Tracker page (/jobs-tracker/*). It:
- Fetches the last sync timestamp from
GET /api/last-sync - Waits 3 seconds for the page to load
- Iterates through up to 15 pages of applied jobs
- Extracts job ID, title, company, location, applied-at date, and posted date from each listing
- Sends all extracted jobs to
POST /api/sync-jobs
Injected alongside sync_apply.js on job pages. It:
- Sends the parsed job details to
POST /api/match-jobon the backend - Returns the backend's relevance score, matching skills, missing requirements, and summary
- Throws an error if the API responds with a non-200 status code
Runs as a persistent background script. It:
- Creates a daily alarm (
periodInMinutes: 1440) - On each alarm tick, checks
GET /api/last-syncto see when the last sync occurred - If more than 24 hours have passed, opens the LinkedIn Jobs Tracker in a background tab to trigger
sync_applied.js
├── manifest.json # Extension manifest (Firefox Manifest V2)
├── package.json # npm config & build script
├── background.js # Background script (daily sync alarm)
├── utils.js # Shared utilities:
│ # parseRelativeTime(), postJobs(), waitForElement(),
│ # onUrlChange(), getLastSync()
├── sync_apply.js # Instant apply tracking content script
├── match_job.js # Job relevance scoring content script
├── sync_applied.js # Jobs Tracker bulk sync content script
├── dist/ # Bundled output (generated by npm run build)
├── icons/
│ ├── icon48.png # Extension icon (48px)
│ └── icon96.png # Extension icon (96px)
└── README.md # This file
| Endpoint | Method | Used by | Description |
|---|---|---|---|
/api/last-sync |
GET | background.js, utils.js |
Returns the last sync timestamp |
/api/sync-jobs |
POST | sync_apply.js, sync_applied.js |
Sends job data to the backend |
/api/match-job |
POST | match_job.js |
Scores a job against your CV profile |
All endpoints are hosted by the Job Relevance Filter backend at http://localhost:8050.
# Watch mode — rebuild on changes
npx esbuild sync_apply.js match_job.js sync_applied.js background.js --bundle --outdir=dist --watch
# Production build
npm run buildAfter rebuilding, reload the extension in about:debugging to pick up changes.