- JavaScript 69%
- CSS 18.6%
- HTML 12.4%
| icons | ||
| src | ||
| vendor | ||
| .gitignore | ||
| background.js | ||
| manifest.json | ||
| README.md | ||
Job Application Tracker
A Brave/Chrome (Manifest V3) extension that tracks your job applications in a local SQLite database (SQLite-WASM + OPFS) with a full analytics dashboard, smart capture, follow-up nudges, and one-click backups. No server, no account — everything stays on your machine.
Load / reload it in Brave
- Open
brave://extensions(Chrome:chrome://extensions) - Turn on Developer mode (top-right)
- Load unpacked → select this folder (
JobExt) — or click Reload on the card after pulling changes (permissions: alarms, notifications) - Close any old dashboard tabs after reloading
Your existing data is safe across reloads — the database migrates itself.
Features
Popup (toolbar icon, on any job page)
- Auto-detect + autofill — reads the page's JSON-LD job card first (works on thousands of sites), then LinkedIn/Indeed/Naukri selectors, then og:/h1 fallbacks. Detected fields get an accent border.
- ⚠️ Already-applied banner if the URL is already in your database
- 🎯 Pick from page — launches the in-page capture panel: press a target, click the text on the page (works on ANY site, drag the panel anywhere)
- Recent applications — change status or add a note without opening the dashboard
- Today / Week / Total pulse
Dashboard
- Tiles: Total · Today · This week · This month · Avg reply time
- 🔔 Needs follow-up — everything sitting in No reply/Waiting longer than your threshold (configurable, saved in the DB)
- 📅 Upcoming interviews — with a browser notification at 8am on the day
- Charts: per-day bar · status doughnut · monthly trend · funnel (Applied → Replied → Interview → Offer with %)
- Activity heatmap — GitHub-style, last 6 months
- Reply rate by source / category — see where applications actually convert
- Table: filter (search/dates/status/category/country/source), sort, one-click status change, edit, delete with Undo
- First response date is recorded automatically the first time a status leaves "No reply" — that powers avg reply time.
Data safety
- Backup / Restore real
.dbfiles (restore validates the file and downloads a backup of your current data first) - CSV export (opens in Excel) and CSV import (flexible headers, status normalization, date coercion)
- Toolbar badge shows today's application count
Security
- All scraped/imported text is sanitized (control chars stripped, length-capped) and HTML-escaped at render time
- Least-privilege permissions (no
tabs, no host permissions —activeTabonly) - No external requests; all libraries bundled
Architecture
The SQLite database has a single owner — a hidden offscreen document — so
multiple windows never fight over the OPFS file. Everything else talks to it via
chrome.runtime messaging (DB bytes cross as base64; raw messaging would mangle
them). Mutations broadcast data-changed so the badge and open dashboards
refresh live.
background.js service worker: offscreen owner, badge,
interview notifications, dashboard tab focus
src/offscreen.* the single DB owner (spawns the SQLite worker)
src/db-worker.js SQLite (WASM) + OPFS; schema migration; all SQL
src/db.js messaging client used by popup + dashboard (with retry)
src/common.js shared: esc/clean/dates/CSV/base64/toast/status maps
src/popup.* toolbar popup (detect, autofill, quick save, recents)
src/picker.js in-page click-to-capture panel (Shadow DOM, self-contained)
src/dashboard.* analytics dashboard
src/theme.css shared design system
vendor/ sqlite-wasm + chart.js (bundled, no CDN)
Data safety model
Data lives in OPFS (durable browser storage — survives restarts and hard
refreshes; wiped only by uninstalling the extension or clearing site data).
Cover that gap with manual backups — Data → Backup database (.db) on the
dashboard saves jobs-backup-<date>.db. Nothing is backed up automatically.
Backups are plain SQLite files — open them with DB Browser for SQLite.