Password Vault
An offline-first password manager that runs entirely in your browser. No server, no cloud, no tracking — your vault lives on your machine.
Features
- AES-256-GCM encryption — All credentials encrypted with a key derived from your master password via PBKDF2 (100,000 iterations). The key exists only in memory.
- Zero network calls — Works from
file://orlocalhost. No APIs, no analytics, no telemetry. - Group management — Organize entries into color-coded groups. Create, rename, delete.
- Full-text search — Instant search across title, username, URL, and notes.
- Password generator — Configurable length (4–64), character types, custom exclusions, strength indicator.
- Copy to clipboard — One-click copy with 15-second auto-clear.
- JSON import/export — Export your entire vault as encrypted JSON. Import with merge or replace mode.
- Auto-lock — Vault locks automatically on tab switch, visibility change, or configurable inactivity timer.
- Dark theme — Responsive layout that works on desktop and mobile.
Quick Start
npm install
npm run dev # http://localhost:5173
Production Build
npm run build # → dist/ (static files)
npm run preview # test the production build locally
The dist/ folder contains fully static HTML/CSS/JS that works from:
file://protocol (opendist/index.htmldirectly)- Any static web server (nginx, Apache, GitHub Pages, etc.)
Architecture
src/
├── App.svelte # Root — toggles LockScreen ↔ MainLayout
├── main.js # Entry point
├── components/
│ ├── LockScreen.svelte # Vault creation & password unlock
│ ├── MainLayout.svelte # Dashboard shell (sidebar + content)
│ ├── Sidebar.svelte # Group list, search, group CRUD
│ ├── EntryList.svelte # Searchable/filterable entry table
│ ├── EntryDetail.svelte # View single entry, copy, delete
│ ├── EntryForm.svelte # Create/edit entry with validation
│ ├── PasswordGenerator.svelte # Standalone generator panel
│ └── ImportExport.svelte # JSON import/export modals
├── lib/
│ ├── crypto/crypto.js # PBKDF2 key derivation, AES-GCM, generator
│ ├── models/schema.js # Data factories, validation, ID generation
│ ├── storage/db.js # IndexedDB wrapper (idb library)
│ └── stores/
│ ├── app.svelte.js # Reactive app state (lock/unlock)
│ ├── search.svelte.js # Shared search + filter state
│ └── security.svelte.js # Auto-lock timer, visibility detection
└── styles/
└── main.css # Dark theme, CSS variables, responsive
Encryption Flow
Master Password ──PBKDF2──→ 256-bit Key ──AES-GCM──→ Encrypted Credential
(100k iters)
│
└── Salt stored in IndexedDB (not encrypted)
- The encryption key is never persisted — it lives only in JavaScript memory.
- A test payload (random string) is encrypted on vault creation and stored alongside the salt. On unlock, the entered password is used to derive a key and decrypt the test payload — if decryption succeeds, the password is correct.
- On tab close or auto-lock, the key is cleared from memory.
Storage Schema (IndexedDB)
| Store | Fields |
|---|---|
entries |
id, title, username, password (encrypted), url, notes (encrypted), groupId, createdAt, updatedAt |
groups |
id, name, color, createdAt |
meta |
salt, testEncrypted, testPlaintext |
Security Considerations
| Threat | Mitigation |
|---|---|
| Key persistence | Key stored only in $state, cleared on lock/close |
| Weak passwords | Strength indicator on generator; no minimum enforced (user's choice) |
| Clipboard leakage | Auto-clear after 15 seconds |
| Tab left open | Auto-lock on visibility change (tab switch) |
| Database tampering | All sensitive data encrypted at rest with AES-256-GCM |
| Brute force | PBKDF2 with 100,000 iterations slows offline attacks |
Known limitations
- No browser fingerprinting or anti-keylogger — This is a local tool, not a hardened security appliance.
- IndexedDB can be inspected — Encrypted data is safe, but metadata (titles, usernames, URLs) may be visible if not encrypted. Currently only
passwordandnotesare encrypted; titles/usernames/URLs are stored in plaintext for searchability. - No automatic backups — Use the JSON export feature to back up your vault regularly.
Development
npm run dev # Start dev server with HMR
npm run build # Production build (zero warnings target)
npm run preview # Preview production build
Stack
- Svelte 5 — Runes-based reactivity (
$state,$derived,$effect) - Vite 8 — Build tool and dev server
- idb — Promise-based IndexedDB wrapper
- Web Crypto API — Native browser cryptography (no external crypto libraries)
- Vanilla CSS — Dark theme with CSS custom properties, no preprocessors
License
MIT
Description
Languages
JavaScript
52.4%
Svelte
44.9%
CSS
2.5%
HTML
0.2%