Some files deserve their own space: personal photos, important documents, and notes you want to keep private.
I’m building Haven Vault, an open source personal vault that encrypts your content in the browser and runs in your own Firebase project.
The goal is to make private storage comfortable enough for everyday use, with code you can inspect, run, and improve.
Each installation is designed for a single owner. You control the deployment, and a separate vault passphrase is used to derive the key that decrypts your content locally.
The app already includes:
- Encrypted files and notes, including filenames, item metadata, and thumbnails.
- Collections, search, and favorites to help you find things again.
- Photo zoom and panning, PDF previews, and text previews inside the app.
- Grid and list views, plus trash for managing deleted items.
- Passkey sign-in and configurable automatic locking.
One design decision worth sharing is the separation between signing in and unlocking the vault.
A passkey authenticates you and establishes access to the backend. Your vault passphrase decrypts the data in your browser. Being authenticated does not mean the encryption key is available.
That gives Haven three distinct states:
- Signed out.
- Signed in, with the vault locked.
- Signed in, with the vault unlocked.
This distinction also makes the experience less repetitive. Locking the vault clears local secrets and decrypted content while keeping an unexpired authentication session active. You can unlock again with your passphrase. Signing out ends the local authenticated session and attempts to revoke it on the server.
Automatic locking follows the same idea. Content is concealed immediately when the app goes into the background. A configurable grace period determines when the key is cleared and the vault locks; during that grace period, decrypted data remains in memory. There is also a separate inactivity timeout.
I want opening a document, checking another app, and returning to the vault to feel natural.
Haven uses React, TypeScript, Vite, Firebase, SimpleWebAuthn, and the Web Crypto API. The project’s source code is MIT licensed.
If you want to explore the interface, you can run the fictional demo without a Firebase account or environment file. With Node 22.12+ within the Node 22 release line and pnpm 12 installed:
git clone https://github.com/i-am-jyotirmaya/haven-vault.git
cd haven-vault
pnpm install --frozen-lockfile
pnpm dev
Then open the local demo.
The demo uses fictional content and cannot upload real files. To test the actual encrypted vault locally, there is a Firebase emulator workflow. Production deployment currently requires your own Firebase project with Blaze billing; the setup guide walks through it.
Haven is still evolving and has not received an independent security audit. There is no passphrase reset or built-in backup/export workflow, so keep independent originals. The security documentation explains the threat model and limitations, including the need to trust the browser and deployed application code.
I’m sharing it now because feedback from people using different devices, browsers, and workflows can shape what it becomes.
If you take it for a spin, I’d especially value:
- A confusing setup step explained from a fresh perspective.
- A mobile interaction or keyboard flow that could feel better.
- A reproducible bug with fictional test data.
- A small improvement to the documentation, accessibility, or tests.
A useful contribution can start with “this took me longer to figure out than it should have.” And if you spot something you’d enjoy fixing, the contribution guide is there to help you get started. For suspected vulnerabilities, please use the private reporting route described in the security documentation.
If this sounds like a project you’d enjoy using or building, have a look at the repository. I’d love to see which small improvements the community notices first.
What’s the one thing a personal vault needs to get right before you’d use it regularly?
Top comments (0)