§1The problem
The password vault already existed and worked, but the desktop program's interface was impractical day to day. I wanted a modern screen without changing format or giving up the physical key.
§2What I built
- Web interfaceReads and writes the KeePass file itself (the file is the database, with no other database behind it).
- YubiKey unlockChallenge-response with a touch and no button: the screen waits for the touch and stops when the window loses focus.
- Vault featuresFolders, protected fields, free-form item types and a trash bin, all stored inside the KeePass format.
- Auto-lockLocks after inactivity.
- End-to-end testAgainst a fake vault (fixture) with a software-simulated key.
§3The hard parts
4 entries- 01
Unlocking compatibly with KeePassXC
Key derivation with Argon2 assembled by hand in WebAssembly, and the YubiKey response handled the way the format expects.
- 02
Every save needs a new touch
Each write generates a new seed and requires a new key touch, so there is batch deletion (one write, one touch).
- 03
Safe file writes
Write to a temp file and rename, keep rotating backups, and if the file changed outside the app the write is refused and the app locks.
- 04
Testing without ever touching the real vault
A test vault and a software YubiKey.
§4Result
In production since August 2026, tested and proven compatible with the real KeePassXC vault. The app only runs locally; on purpose, it is not exposed to the network.
§5Stack
- Next.js 16
- React 19
- TypeScript 7
- Tailwind 4
- kdbxweb (KeePass / KDBX 4.1)
- hash-wasm (Argon2)
- YubiKey (ykman)
- Own design system
- pm2