Most "simple" productivity apps want an account before you can write one line. I wanted the opposite: open a page, start typing, close the tab, and find everything still there tomorrow, without a server ever seeing it.

Here's the small pattern I used for a set of free browser apps on Toolverse.

1. Save on every change, debounced

let t; function save(state){ clearTimeout(t); t = setTimeout(() => localStorage.setItem('journal-v1', JSON.stringify(state)), 400); } 

A 400 ms debounce keeps typing smooth and still feels instant.

2. Version your key

Using journal-v1 instead of journal means you can migrate the shape later without breaking old saves.

3. Load defensively

function load(){ try { return JSON.parse(localStorage.getItem('journal-v1')) || {entries: []}; } catch { return {entries: []}; } } 

Corrupted or hand-edited storage should never crash the app.

4. Give people an export button

localStorage is per-browser. A one-click JSON export (a Blob plus a download link) lets people back up or move their data, which matters more than any sync feature.

5. For secrets, encrypt first

For the password manager I used the Web Crypto API (PBKDF2 to derive a key, AES-GCM to encrypt), so only ciphertext ever touches storage.

Try them

Open one, add something, reload, and it's still there. Feedback on the pattern is welcome.