Local-First AI Productivity: Why Your Data Should Never Leave Your Device
Most AI apps upload everything to the cloud. Locked In is local-first — your chaos, plans, moods, and streaks stay on your device unless YOU choose to sync. Here's why it matters.
You type your deepest academic anxieties into an AI planner. Where does that go?
Most apps: Straight to their servers. Analyzed. Stored. Possibly sold. Used to train models. Subpoenable.
Locked In: Stays in your browser. Never leaves unless you explicitly sign in and sync.
What "local-first" actually means
Default: Zero network calls for your data
- Open app → loads from cache → works offline
- Type chaos → AI processes via API (only prompt + context) → plan returns
- Plan saves to
localStorage(lockedin-v2key) - Mood check-ins, timer sessions, streaks — all local
- Zero bytes of your personal data leave your device
Optional: Encrypted sync (you control)
- Sign in with Google or email → then Supabase sync activates
- Data encrypted before leaving device (AES-256-GCM)
- Pepper key gated by your JWT — not even Supabase can decrypt
- You can sign out → local data remains, cloud data untouched
- Clear all → wipes both local + cloud
What the AI sees (minimal context)
Each request sends only:
- Current message + last 10 messages
- Mode (Study/Chill/Crunch/Roast)
- Effort level (Low/Mid/Max)
- Aggregated stats only — streak, completion rate, avg mood, preferred modes
- Never: raw mood history, exact timestamps, specific plan content, personal identifiers
Why this architecture is rare (and hard)
| Challenge | Most Apps | Locked In |
|---|---|---|
| Offline support | ❌ Requires connection | ✅ Full offline after first load |
| Conflict resolution | ❌ Server wins | ✅ Local wins, cloud merges |
| Encryption | ❌ TLS only (server decrypts) | ✅ Client-side AES-256-GCM |
| User control | ❌ All-or-nothing | ✅ Guest → signed in → guest seamlessly |
| Data portability | ❌ Export requests | ✅ Share card, ICS, copy JSON |
Real privacy threats this prevents
| Threat | Cloud-first app | Locked In |
|---|---|---|
| Data breach exposes your anxiety, grades, habits | ✅ Vulnerable | ❌ Data never there |
| Company sells analytics to third parties | ✅ Common | ❌ No data to sell |
| AI training on your personal content | ✅ Often in TOS | ❌ Only aggregated stats |
| Government subpoena for user data | ✅ Must comply | ❌ Nothing to hand over |
| Employee access to your journals | ✅ Possible | ❌ Encrypted client-side |
| Company pivots/shuts down → data lost | ✅ Risk | ❌ Local copy always yours |
The "but convenience" argument
"But sync across devices is convenient!"
Locked In gives you both:
- Guest mode — full features, local-only, zero friction
- Sign in — encrypted sync, same features, you decide when
- Sign out → back to guest, local data intact
No "create account to continue" walls. No "premium for sync." You own the data flow.
Technical details (for the skeptical)
Encryption: AES-256-GCM via Web Crypto API
- Key derived via PBKDF2 (user ID + JWT-peppered secret)
- Format:
enc:v1:<ciphertext> - Pepper fetched from
/api/security/pepper(requires valid Supabase access token)
Supabase RLS: Row Level Security on every table
auth.uid()::text = user_idon all 4 policies (SELECT/INSERT/UPDATE/DELETE)anonrole: ALL GRANTS REVOKED — zero anonymous access- PKCE auth flow (no implicit flow token leakage)
Storage key: lockedin-v2 in localStorage
- Migrates legacy
sb-*-auth-tokensessions automatically consumeSignedOutFlag()prevents immediate re-redirect after sign-out
Try it — verify yourself
- Open lockedn.in in incognito
- "Start free" → "Continue as guest"
- Type something personal
- Get plan → complete it → check streak
- Open DevTools → Application → LocalStorage →
lockedin-v2 - See your data. See NO network requests to Supabase.
- Close tab → reopen → data persists
That's local-first. Your chaos, your device, your choice.
Locked In: Free, local-first, encrypted-if-synced AI productivity. Try it here — no account required.
— Locked In
More posts