SafeScribe — a journal that can't read itself.
A private journalling app for Android and iOS. Every entry is encrypted on the phone before it is written anywhere — so the storage layer, and anyone who ever reaches it, holds nothing but ciphertext.

- Domain
- Personal journalling & wellbeing
- Platform
- Android & iOS, one codebase
- Core build
- Expo · libsodium · SQLite
- Status
- Built, in internal testing
A diary is the most private thing a person writes.
People put things in a journal they would not say aloud — and most journalling apps store that in plain text on a server, one misconfigured database away from being readable by anyone.
The brief inverted the usual arrangement. Instead of asking users to trust the operator, make the operator unable to help. If the entries are encrypted on the phone under a key derived from the user's own password, then a breach, a subpoena, or a careless engineer all reach the same thing: noise.
The hard part is that this conflicts with the second requirement — the app should still understand how you're feeling over time. Sentiment analysis normally means sending text to a server. Here it couldn't.
The design rule: if a feature requires the plaintext to leave the phone, it either runs on the device or it doesn't ship.
Real cryptography, not a wrapper around a library.
The encryption is built on libsodium primitives with a wrapped-key vault — the same shape a password manager uses, rather than a single key hidden in the app bundle.
A random master key, wrapped
Each vault generates its own random master key. That key is never derived from the password — it is encrypted by a key that is, so the password can change without re-encrypting a single entry.
Argon2id, tuned for real phones
Password stretching uses Argon2id at a published OWASP profile, deliberately stepped down from the strongest setting — the higher memory cost crashes low-RAM Android devices, and an algorithm that fails on your users protects nobody.
Authenticated encryption
Entries are sealed with XChaCha20-Poly1305 — an AEAD construction, so tampered ciphertext fails to decrypt rather than silently returning corrupted text.
Ciphertext columns only
The local database has no plaintext column to write to. Title, body and the sentiment result are each encrypted before the insert — the schema itself enforces the rule.
A recovery path, by design
The vault holds more than one wrapper. A recovery secret can unlock the same master key independently of the password — because “forgot password” in an end-to-end encrypted app otherwise means “lost everything”.
A versioned vault format
The vault file carries a version number and refuses to open anything it does not recognise. Changing the scheme later is a migration, not a corrupted diary.
Understanding the writing without ever reading it.
The app tracks how a person's mood moves across weeks. Normally that means posting the text to an API — which would defeat the entire premise.
So the sentiment model runs on the phone. A TensorFlow.js sentiment network is loaded into the app and classifies the entry locally, mapping the result onto a small set of everyday emotions rather than clinical labels. The classification is then encrypted alongside the entry, so even the derived mood is not readable at rest.
The result is a mood history the user can see and the system cannot — charted over time, searchable, and never sent anywhere to be computed.
What it does day to day
One Expo codebase shipping to Android and iOS, built so the privacy model never shows up as friction.
What it's built on
App
- Expo · React Native
- expo-router file-based navigation
- TypeScript
- NativeWind / Tailwind
- Android & iOS from one codebase
- EAS build profiles
Crypto & Storage
- libsodium (react-native-libsodium)
- XChaCha20-Poly1305 AEAD
- Argon2id key derivation
- Wrapped-key vault, versioned
- Local SQLite, ciphertext columns
- OS keystore via SecureStore
Intelligence
- TensorFlow.js for React Native
- On-device sentiment classification
- Mood mapping and trends
- Encrypted local backup & restore
- Offline-first by construction
Building something where the data is the sensitive part?
Health records, journals, legal notes, financial data — the architecture question is the same: what can you make yourself unable to read?