๐Ÿ““ About the project

The story of a tool I built so I'd never type my phone number again.

Autofill Vault started as a 1 a.m. shortcut and turned into a genuinely interesting engineering problem. Here's the why, the build, and the part that broke everything.

The why

It started with an itch, not a roadmap.

I was deep in a job-application stretch โ€” the kind where you fill the same six fields into a slightly different form forty times a week. Name. Email. Phone. City. LinkedIn. Portfolio. Browsers have built-in autofill, sure, but it's a black box: it fires when it feels like it, fumbles modern single-page apps, and you can't see or shape what it knows.

Password managers nailed this for logins. Nobody nailed it for everything else. So I built the thing I wanted: a vault I fully control, that fills any form on command, and that never sends a single byte to anyone's server. Local-first wasn't a feature decision โ€” it was the whole point.

How it came together

A realistic build timeline

A few hours here and there over six months โ€” including the week the whole thing quietly broke.

January 2026 ยท The itch

Ideation

Sketched it after one too many application forms. One rule from day one: everything stays on-device. If it needs a server, it's the wrong design.

February 2026 ยท Scoping

Design & constraints

Chose Manifest V3, no framework, no build step โ€” just the platform. Decided the vault would be category-based (Personal, Address, Education, Professional) so it maps to how forms actually group fields.

March 2026 ยท It exists

MVP โ€” the vault & copy buttons

Built the dashboard: editable categories, inline autosave, a copy button on every field. Useful on its own before a single form was auto-filled. Shipped this to myself and started using it daily.

April 2026 ยท The part that broke everything

The autofill engine โ€” and the React wall

Wrote the field-scoring engine, felt great, tested on a React job board โ€” and watched every filled value vanish on submit. Setting el.value updates the DOM but not React's internal state, so the form submitted empty. Two evenings of confusion later: call the native value setter on the element prototype, then dispatch real input/change events. That one function is the reason this works at all.

May 2026 ยท Rounding it out

Accounts, popup & shortcuts

Added saved logins (with smart username detection for multi-step forms), the toolbar popup with search-and-copy, the right-click menu, and keyboard shortcuts (Alt+Shift+F to fill, Alt+Shift+V to open).

June 2026 ยท Polish & launch

Backup, theming & this site

JSON export/import, light/dark themes, the aurora-glass UI, and the showcase site you're reading โ€” so the project could live somewhere other than my chrome://extensions page.

The interesting bits

Decisions & challenges worth talking about

Every one of these started as "that should be easy" and taught me otherwise.

Challenge

Filling forms that fight back

React and Vue track input state internally, so a plain value assignment gets discarded. Solved by invoking the prototype's native setter, then firing bubbling input/change/blur events โ€” indistinguishable from real typing.

Decision

Scoring instead of one rule

Rather than trust field names, the engine builds a weighted score: autocomplete token (100) > native input type (60) > exact label/synonym (25โ€“50). A threshold keeps it from filling fields it isn't sure about.

Challenge

Finding the username on a lonely page

Multi-step logins show the username field on one screen and the password on the next. The engine picks the text/email input nearest before the password in document order โ€” and falls back to a regex on the page's signals when there's no password at all.

Decision

One shared brain, three contexts

common.js โ€” the data model, field dictionary and storage helpers โ€” loads identically in the dashboard, the popup, the content script and the service worker. One source of truth, zero duplication, no bundler.

Tech stack

Why each piece earned its place

Manifest V3
The current, future-proof extension model โ€” service worker + scripting API. Why: it's where Chrome is going, full stop.
Vanilla JS, no build
Edit a file, hit reload. Why: a privacy tool should be trivially auditable โ€” no bundle to read through, nothing hidden.
chrome.storage.local
On-device, per-profile, event-driven. Why: it's the honest answer to "where's my data?" โ€” right here, nowhere else.
Modern CSS only
color-mix, custom properties, backdrop blur. Why: a polished UI without shipping a styling framework to do it.
Project links

Want to build something โ€” or collaborate?

The whole thing is open source. Read it, fork it, or tell me what you'd do differently. I'm always up for a good technical argument.

Get in touch

Let's talk.

Pick whichever's easiest.

More about me โ†’