DEV Community

Cover image for The journal app that can't phone home
Karthikeyan NG
Karthikeyan NG

Posted on

The journal app that can't phone home

DailyVox, the voice journal I build, holds no network permission. There is no analytics call to remove and no upload path to audit, because the capability was never granted. That single constraint made most of my architecture decisions for me. This post walks through what it forced.

The reasoning behind the rule is short. A diary is the most honest text a person produces, and I could not bring myself to be honest in an app that stored my entries on someone's server. "We promise not to look" is a policy. "The app has no way to send it" is a property. I wanted the property, so every model in the pipeline has to run on the phone, and every fallback that reaches for a server has to be treated as a bug.

Speech first

Recording is the whole interface. You talk for about 42 seconds, and everything downstream is built on what the recognizer returns.

let request = SFSpeechAudioBufferRecognitionRequest()
request.requiresOnDeviceRecognition = true
Enter fullscreen mode Exit fullscreen mode

That flag is load-bearing. Without it, SFSpeechRecognizer is free to use Apple's servers when it judges the result would be better, and for connected iPhones it usually judges exactly that. With it, transcription runs on the Neural Engine or fails. When the on-device model for a language is missing, DailyVox shows an error that names the setting to fix, because a loud failure is cheaper than a quiet upload.

The trade is real. Server-side models punctuate better and handle rare words better. In exchange you get transcription that works in airplane mode, latency that doesn't depend on your connection, and audio that dies inside the device that heard it.

Sentiment you can check

Each transcript gets a mood score from NLTagger plus a lexicon layer. When I correlated the scorer against self-reported mood labels, it came out at r = +0.663. Middling as correlations go, and about what a lexicon method earns on 42-second spoken entries. I publish the number anyway. A mood feature that has never been measured against ground truth is decoration.

The scores feed a small forecasting model keyed on day of week. Mine found that my low days cluster on Sundays. Twenty years of paper diaries never showed me that, because nobody rereads twenty years of paper.

The Insights screen in DailyVox, showing recent mood patterns and a 32-day writing streak

The name the tagger couldn't see

The Twin builds a knowledge graph of the people in your life, which means named entity recognition. Apple's tagger handled "Sarah" fine and treated "Adyah" as noise. Names from outside its training distribution simply vanished, and on my entity test suite that blind spot cost 34.6% recall.

The fix was to stop trusting the tagger's entity class as the source of truth. Capitalized tokens become entity candidates, and the graph decides over time which candidates are people, by watching how they recur across entries. It recovered the missing names.

It also bought me a new dependency: the speech recognizer must capitalize names in the first place. Apple's does. Whether Android's does on real Samsung and Xiaomi hardware is the question currently standing between the finished Android port and its release.

Search with no server

Semantic search runs on NLEmbedding.sentenceEmbedding. Apple ships those vectors for English, Spanish, French, German and Italian, which is why the interface ships in exactly those five languages. Shipping a language where search quietly returns nothing would be worse than waiting.

Cosine similarity has no sense of time, so a pure vector search happily surfaces a three-year-old entry over last week's. The ranking blends similarity with recency, and below a similarity of roughly 0.37 the app says "no good match" instead of padding results. Teaching a search box to abstain took longer than teaching it to match.

The Twin itself

Everything lands in the model the app is named for: a Digital Twin, meaning baselines for emotional valence and arousal, a communication-style profile, the entity graph, and the mood forecaster. The whole state is Codable JSON inside a single Core Data entity, synced through the user's own iCloud container so a new phone doesn't mean a new stranger.

The Digital Twin screen in DailyVox: entries rendered as a constellation of stars, one per entry, grouped around the people they mention

You can ask it questions. Answers come from Apple's Foundation Models framework, on-device, and every answer must cite the entries it drew from. A deterministic audit checks each claim against its citations and rejects answers that fail. That gate deserves its own post, and it will get one.

What the constraint bought

The App Store privacy label reads "Data Not Collected," and it reads that way as a build output rather than a marketing decision. Demos run in airplane mode. There are no retention pings and no A/B tests, so the only usage number I have is the App Store's install count, which is a strange feeling for someone who has shipped instrumented products for years. I recommend the feeling.

The honest split

The iOS app is MIT. How it records, stores, encrypts and exports your words is readable by anyone, and so is the permission list. The Twin's analysis engine is a closed Swift package that lives inside that app. The part that touches your data is checkable; the part that models you is the product I'm betting on. Some people find that line unsatisfying. I'd rather draw it where you can see it than blur it.

GitHub logo intrepidkarthi / dailyvox

Free open-source voice journal for iPhone with on-device AI. Every entry becomes a star in your private constellation. Built with SwiftUI, Apple Speech, NaturalLanguage, ActivityKit. MIT licensed.

DailyVox — speak, and watch your stars appear

DailyVox

Speak for 42 seconds. Watch your words become stars.

The free voice journal with on-device AI and a Digital Twin that learns who you are — entirely on your phone. iPhone today; Android in development.

Free forever  ·  100% on-device  ·  No account, no servers, no analytics  ·  MIT licensed  ·  on Product Hunt

Download on App Store Website GitHub stars

DailyVox on Product Hunt — upvote us   Try the interactive demo

Privacy Platform Android in development License Free Forever On-Device AI

Forks Watchers Last commit Commit activity Repo size Open issues Contributors

Swift SwiftUI Xcode Core Data + CloudKit Neural Engine / Core ML On-device Speech


What is DailyVox?

DailyVox turns your spoken thoughts into a constellation of stars. Every journal entry becomes a point of light in your inner sky — mood-colored, connected by patterns only you can see.

Behind the scenes, an on-device Digital Twin learns how you think, how you feel, and who matters to you. It predicts your mood, answers questions about your patterns, and reveals meaning across months of entries. No accounts. No servers. No data collection.

Your thoughts never leave your device. Ever.

Download


App Screenshots

The Speak tab: today's entry, and a microphone docked where your thumb is The Digital Twin sky: distance is how long ago, angle is the hour of day An entry with the names it caught underlined, and what the Twin filed beneath Insights: a 32-day writing streak and the week's pattern Ask your Twin: an answer that cites the entries it came from The Data Shield: transcription on device, DailyVox servers none exist

Real screenshots from v1.11.0, seeded with a demo journal.




DailyVox is free, with no account and no ads, on iPhone. The no-network claim takes ten seconds to verify in the repo or in the app's own settings ledger. Check me.

Top comments (0)