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.
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.
A few hours here and there over six months โ including the week the whole thing quietly broke.
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.
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.
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.
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.
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).
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.
Every one of these started as "that should be easy" and taught me otherwise.
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.
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.
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.
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.
color-mix, custom properties, backdrop blur. Why: a polished UI without shipping a styling framework to do it.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.