
MindSync
A journaling app that reads what you wrote and how you sounded, then surfaces the gap
A privacy-first mental wellness journaling app that analyses an entry through two channels at once—the text and the voice recording—and flags when the two disagree. A Flutter client holds all journal data on-device under AES encryption; a stateless FastAPI service runs the models and keeps nothing.
The 15-second brief
At a glance
- Outcome
- Built the dual-channel analysis and the evidence behind it: a 15-model benchmark that overturned the text model already in production, replacing it with one scoring 0.172 higher macro-F1.
- Delivery
- Prototype, 2026
- Focus
- ML, Mobile, Research
- Scope
- 12 core technologies
- Models benchmarked
- 15
- Macro-F1 gain
- +0.172over the model already in production
- Client screens
- 18~16k lines of Dart
Ownership and evidence
What I built
The product decisions and engineering work that shaped the final result.
Designed a discrepancy engine that compares two classifiers with incompatible label sets by folding both onto a shared six-emotion schema, projecting each channel's full confidence distribution into Russell's valence-arousal plane, and measuring the Euclidean distance between the weighted centroids.
Benchmarked 15 candidate models (8 text on the GoEmotions test split, 7 voice on all 1,440 RAVDESS clips) and found the backend's existing text model scored 0.172 macro-F1 below the best alternative.
Shipped the accuracy-per-parameter optimum rather than the top-ranked model: third place cost 0.007 macro-F1 and saved 3.2× the parameters, which matters when every cold start loads the weights.
Caught a false generalisation claim by checking a model's training corpus against the dataset's own provenance column instead of its model card—the card named one dataset, but that dataset aggregated RAVDESS, making the study's only apparent out-of-domain candidate in-domain like the rest.
Made the privacy claim structural rather than stated: no database, no cache, audio dropped when the handler returns, and FastAPI's default 422 handler replaced because its error payload echoes the rejected value—which on a journaling endpoint is the journal entry.
Handled Hive's silent failure on a wrong cipher (it recovers the box as empty, and the next write destroys the file) by verifying every key before opening a box and staging re-key migrations so an interrupted run is survivable.
Architected the Flutter client on MVVM and Repository with Riverpod—18 screens, ~16k lines of Dart—with three swappable sources behind each repository interface and a best-effort offline analysis queue with retry.
Product evidence
See it in action
Interface views and demonstrations from the working product.
Visual assets are not published for this project. The verified delivery and engineering scope are documented above.