May The Job Be With You
Platform · Chrome Extension
Stop retyping your life into forty different job portals. Keep your job-search profile once, in your browser, and fill applications in one click.
The problem
Every job application asks roughly the same twelve questions: full name, email, phone, graduation year, degree, university, LinkedIn, GitHub, resume, work authorisation, notice period, one sentence about yourself. A student with forty applications to make is going to type those forty times, into forty different portals, each with different field names, different markup, and no shared profile anywhere.
It is the most tedious possible problem: no expertise required, no ambiguity about the goal, and yet the solution people are left with is a spreadsheet and a lot of copy-paste. Which is also why nobody has bothered to fix it properly — there is no single employer to sell to, and the pain is spread thin across thousands of individuals.
The trap is building this as an account-based SaaS. A job seeker will not create an account to fill a form, will not upload their personal data to a stranger's server, and will abandon it the moment the site is down. The privacy-sensitive, high-intent, low-trust category demands local-first — and that constraint, once accepted, is what makes the product fast, free to run, and trustworthy enough to keep.
What I built
- A website and a Chrome extension designed as one product, sharing a data model rather than an API — the site explains and installs, the extension does the work.
- A local-first job-search profile stored in the browser. No account, no server, no sync; the data is the user's and it stays on their machine.
- A field-detection engine that inspects a job application form and works out which profile field belongs in which input, with per-platform rules and a confidence score so a bad guess is never silently applied.
- One-click assisted autofill driven from the Chrome Side Panel: detect the form, preview what will be filled, fill it, and let the user review before submitting.
- A deliberately non-automatic submit path. The extension removes typing; the user makes every decision and presses every button.
- An application tracker and productivity layer on top of the same local database, so the profile is not a one-off form-filler.
- Support for multiple job platforms through an extensible rule layer, so adding a portal is a contained change rather than a rewrite.
- A path toward placement-team visibility built on aggregated, opt-in data — useful to universities, but only in a form that does not compromise the individual user.
Key features
Profile
- A single job-search profile kept in the browser
- Local-first: the profile never leaves the device
- No account, no sign-up, nothing to leak
- Export and import so the profile is durable, not hostage to browser storage
Autofill
- Automatic form-field detection on supported job platforms
- Per-platform rules layered over general heuristics
- Confidence scoring, so a low-confidence match is flagged rather than filled
- One-click assisted fill from the Side Panel
- The user always reviews and always presses submit
Productivity
- Application tracking built on the same local database
- Chronology of what was applied to, and where
- Chrome Side Panel interface that stays alongside the job posting
- Multiple job platforms supported, with an extensible rule layer
Platform
- Website and extension as one product, not two things
- Local-first architecture with a browser-local source of truth
- Aggregated, opt-in analytics concepts aimed at placement teams
- Designed for individual seekers first, institutional value second
Technical architecture
There is no backend, and that is the architecture. The browser's IndexedDB is the source of truth, the extension is the interface, and the website is the front door. Everything above that line — the website — is a consumer of a product that works entirely on the user's machine.
-
Storage
IndexedDB through Dexie as the single local source of truth: the profile, detected fields, application records, and settings. Explicit schema versions, because browser storage can be cleared and migrations are what keep a user's profile from becoming garbage.
-
Content script — detection
Runs on supported job portals, inspects the form, and produces a candidate mapping of input elements to profile fields. Heuristics handle the general case; per-platform rules handle the specific case; a confidence score keeps the two honest with each other.
-
Fill engine
Applies a confirmed mapping, dispatches the events the page's framework actually listens for — setting a value is not filling a React input — and never touches the submit control. Assisted, deliberately.
-
Service worker
MV3 messaging and lifecycle. Because the worker is killed and restarted constantly, it holds no durable state: everything it needs is read from IndexedDB on demand.
-
Side Panel
The primary interface. The profile, the detected form, a preview of what would be filled, the one-click action, and the application tracker — all in a panel that stays next to the job posting instead of stealing focus.
-
Website
The product's front door and explanation, sharing the extension's data model conceptually rather than technically. It exists to make the local-first promise legible, because "your data never leaves your machine" is a claim a user has to be convinced of.
- No backend, no accounts, no user data at rest anywhere but the user's own browser.
- Adding support for a new job platform is a rule file — not a rewrite.
Visuals
What was technically hard
Field detection is the actual product
Job portals have no usable labels, no consistent names, and a different DOM framework each. The same logical field is called half a dozen different things. Any naive "search the placeholder for email" approach breaks the first time a portal adds a tooltip. This needed layered heuristics, per-platform rules, and a confidence score — because the worst outcome is not a missed match, it is a confidently wrong value typed into a field the user did not notice.
Filling a React-controlled input is not setting its value
Most job portals are React or similar, and a framework that controls an input will silently discard a value you set programmatically. Filling means setting the value and dispatching the exact sequence of input and change events the framework listens for, per field type. Get this wrong and the form looks filled and submits blanks.
Assisted, never automatic
Submitting applications on someone's behalf is a liability and technically fragile — it breaks the moment a portal changes, and it can send a real application to a real employer with wrong data. The product is much stronger for drawing that line explicitly: fill the boring parts, show the user exactly what will happen, and let them press the button.
Local-first has costs as well as benefits
No server means no sync, no cross-device profile, and no recovery if the user clears site data. Those are real limitations, and the honest answer is export/import plus a migration story that survives every schema change. A local-first product still owes the user a durability guarantee.
MV3 kills your service worker on a schedule
Any state living in a worker's memory is state you will lose mid-operation. Everything durable had to be pushed into IndexedDB and read back on demand, which is a different mental model from MV2 and touches every feature that seemed to "just work".
Institutional value without compromising the individual
Placement-team analytics are the obvious growth path and also the fastest way to destroy the trust that makes the product usable. Aggregated, opt-in, and structurally incapable of exposing an individual applicant is a product constraint that has to hold in the data model, not just in the copy.
Testing & reliability
Detection is the part that can rot, so it gets the regression suite: each supported platform is pinned to a saved DOM fixture, and the mapping it produces is asserted. Everything downstream of detection is tested against a fake but realistic form, which is far faster and more reliable than driving live job portals.
End-to-end assertion chain
- 01 User opens a job application
- 02 Fields detected & mapped
- 03 Mapping shown for review
- 04 One-click fill applied
- 05 Profile / records updated
- 06 Side Panel reflects state
- 07 User reviews and submits
A test passes only when every link above is observed. When one breaks, the failure names the link instead of saying the feature is broken.
Per-platform detection fixtures
Each supported job platform is pinned to a saved DOM snapshot with an asserted field mapping, so a portal redesign shows up as a failing test rather than a user report that autofill stopped working.
Confidence and conflict tests
Ambiguous, missing, and duplicate matches are asserted explicitly. The rule being tested is that the extension never silently writes a value it is not confident about.
Fill correctness against framework-controlled inputs
Filling is verified against inputs that react to programmatic value changes, asserting the resulting form state — not just that the DOM node has text in it.
Service worker restart
The worker is killed and relaunched mid-operation to prove the extension reads its state back from IndexedDB instead of assuming it is still in memory.
Schema migrations
Every storage schema change is tested by upgrading an older database version, because a user who loses their profile on upgrade has lost the entire value of the product.
End-to-end product flow
Profile created, job application filled, record tracked, and the Side Panel reflecting all of it — the full chain from a blank browser to a tracked application.
My contribution
Solo — product, extension, architecture, website
Solo. I designed the product, built the website and the Manifest V3 extension, designed the local-first storage model and its migrations, built the field-detection and fill engines, and defined the trust boundaries the analytics story has to respect.
The decision I would defend hardest: keeping the profile local and refusing to automate submission. It is a smaller, more boring, more trustworthy product than the automated one — and it is the one people will actually keep installed while job hunting.