Voice Journal
Journaling every day abroad was easy. Coming home, it wasn't.
Voice Journal lets you speak your entry like a voicemail to a friend. It then uses a two-stage Claude pipeline to extract structured reflection, generate personalized follow-up questions, and surface emotional patterns over time.
Built solo in Expo + React Native, inspired by Lenny Rachitsky's vibe-coding process.

TL;DR
During a quarter abroad, I journaled every single day, capturing experiences, processing emotions, and building a habit that felt genuinely valuable. Then I came home. The pace changed, the time disappeared, and sitting down to write felt like a task instead of a release. I'd open a blank page, feel impatient, and close it.
But I still wanted to reflect. I just couldn't afford the friction. So I asked: what if journaling were as easy as leaving a voicemail for a friend? No structure, no format. Just speak, and let something smarter do the work of turning it into something useful.
The constraint wasn't motivation. It was friction. Removing the writing step was the only way to make reflection sustainable.
Around the same time, I came across Lenny Rachitsky's post on how he vibe-coded LennyRPG through a six-step process: define the core idea, create a PRD through AI interview, build a proof of concept, add remaining features, polish, then ship. That framework became the spine of how I built this app. Rather than starting with code, I started with a structured product brief, then used Claude Code to move fast once the decisions were already made.
Before writing any code, I mapped the competitive landscape to find where existing voice and reflection apps fell short, then wrote How Might We questions to translate those gaps into product decisions.
Competitor analysis
Pillowtalk
Voice journaling · emotional insights
Turns daily voice entries into character strength cards. Replies to your journal, surfaces patterns, and generates psychology-rooted prompts. Strong aesthetic.
Key difference
Insights feel curated but surface-level. There is no structured data extraction behind the scenes, and the follow-up system reads like a preset worksheet instead of a conversation.
Glimpse
Visual journaling
Short video and photo-based journal entries with lightweight reflection prompts. Focuses on visual memory capture over deep self-analysis.
Key difference
Optimized for recall, not reflection. No AI reasoning layer, no emotional pattern tracking, no personalized follow-ups based on what you actually said.
Honestly
Gamified wellbeing journaling
Gamifies journaling with streaks, weekly recaps, mood tracking, and wellbeing insights. Makes the habit feel rewarding.
Key difference
Gamification drives frequency but not depth. Entries are short and structured by the app, so it solves the habit problem but not the insight problem.
The gap across all three: none of them treat the raw journal entry as structured data. They capture words and surface patterns, but the extraction is shallow. There's no systematic pass for goals, decisions, concerns, or gratitude in a single entry. And the follow-up experience in every competitor felt more like a form than a conversation.
How Might We questions
Four HMWs crystallized the core product decisions. Each one maps directly to a feature.
HMW make one spoken entry the complete input for mood, gratitude, goals, and concerns, so there's never a separate form or tracker to open?
Feature decision
EntryExtract (Stage 1 Haiku) captures seven structured fields from every transcript in a single pass: mood and intensity, key topics, people mentioned, decisions, goals, concerns, and gratitude moments. One entry covers seven dimensions, with no separate mood logger and no separate gratitude journal.
HMW make journaling feel as effortless as leaving a voicemail for a friend, with no prompts, no format, and just speaking?
Feature decision
Voice-first input with zero pre-recording structure. Follow-up questions are delivered conversationally after the fact, and each one can be answered by typing or recording a voice reply. As a result, responding feels like speaking instead of filling out a form.
HMW eliminate every setup barrier between 'I want to reflect' and 'I'm recording,' so reaching for the phone is enough?
Feature decision
On-device ASR as the default transcription path requires no API key to start. AsyncStorage means no account, no login, no sync. The record screen opens in one tap.
HMW make every 3-minute voice entry worth more than 30 minutes of traditional journaling by turning spoken thoughts into something actionable?
Feature decision
Stage 2 Sonnet generates three personalized follow-up questions, three concrete insights, and a 1–2 sentence emotional pattern note per entry. This gives the user something to act on, not just a record of what they said.
The PRD was built through an AI interview, with answers used to produce a detailed implementation plan before a single line of code was written. Two architectural decisions shaped everything else.
Two-stage AI pipeline
The core cost strategy: the raw transcript never reaches an expensive model. Haiku extracts compact structured JSON first; Sonnet only sees that ~200-token summary to generate insights and questions.
Voice Recording
expo-av · m4a file
On-Device ASR
expo-speech-recognition · no API key
Raw Transcript
500–3,000 words · stored locally
Stage 1: Haiku
Extract JSON: mood, topics, people, decisions, goals, concerns, gratitude · ~$0.0003/entry
Compact JSON ~200 tokens
transcript never forwarded
Stage 2: Sonnet
3 follow-up questions + 3 insights + emotional pattern note · ~$0.003/entry
AsyncStorage
full entry saved locally · no cloud required
Entry Detail Screen
transcript · insights · follow-up Q&A
Total cost per entry: ~$0.003, vs. $0.015–0.03 if the raw transcript went to Sonnet directly. The two-stage approach cuts cost by ~10× while improving output quality, since Sonnet reasons over clean structured data instead of noisy raw speech.
Abstraction layers
Both the transcription and storage paths are built behind interfaces, not directly against their implementations. This was a deliberate future-proofing call:
TranscriptionService
On-device ASR ships first with no API key, no latency, and offline support. The interface makes swapping to Whisper (for better accuracy on fast or accented speech) a single-file change.
StorageService
AsyncStorage ships first because it is local, private, and instant. The same interface lets the app migrate to Supabase for cross-device sync without touching any UI or pipeline code.
State machine
The recording flow runs as a typed state machine in useRecorder.ts. Each state transition saves the entry to storage immediately, so progress survives backgrounding. The sequence: IDLE → RECORDING → TRANSCRIBING → EXTRACTING → ANALYZING → AWAITING_ANSWERS. Any step can transition to ERROR with a typed message, so the UI always knows exactly where the failure happened.
I followed the POC-first approach from Lenny's framework: get the core loop working before adding any polish. The build progressed in three visible stages.
Proof of concept
Core recording → ASR → AI pipeline loop, barebones UI. The goal was to verify the two-stage pipeline produced usable output before investing in any design work.



V2: features complete
Full feature set built out: follow-up questions with voice reply support, home list with mood and duration, entry persistence and deletion with audio file cleanup, onboarding for API key setup.



Final: polished UI
End-to-end UX pass: visual hierarchy, spacing, recording animation, waveform visualizer, haptic feedback on record start/stop. Every screen tested for the golden path and edge cases.






The hardest product problem wasn't the recording or the AI pipeline. It was long-term trend analysis. The competitor analysis surfaced it as a key differentiator: summarizing patterns across weeks of entries, not just reflecting on today.
The problem
Storing raw transcripts for trend analysis is expensive and heavy. A 3-minute entry produces 500–3,000 words. Sending even a week of transcripts to a model for pattern analysis would cost an order of magnitude more per session, and it would also create a growing local storage problem.
The solution
The two-stage pipeline already solves this by design. Stage 1 produces a compact EntryExtract JSON for every entry, about 200 tokens capturing mood, topics, people, decisions, goals, concerns, and gratitude. That structured summary becomes the long-term memory layer. A trend analysis call reads seven compact JSONs instead of seven raw transcripts, with the same semantic signal at a fraction of the token cost.
The extract that makes per-entry analysis cheap also makes long-term analysis possible. The architecture solves both problems simultaneously.
What this unlocks next
Weekly recaps generated from a week of EntryExtract summaries, not raw transcripts
A pattern bank built from recurring topics, emotions, and goals across all entries
Personalized journal prompts generated from that pattern bank, rooted in what you actually talk about rather than generic psychology templates
Mood trend visualization without a separate tracker, because the data is already structured
The app is fully built and running locally, with every screen, every state transition, and every AI pipeline call working end-to-end. It's not deployed yet, but the core loop is proven: speak an entry, get structured reflection back in seconds.
What I learned
Start with the PRD, not the code
Spending time on the product brief before touching Expo paid off. The architecture decisions, including abstraction layers, the two-stage pipeline, and the state machine, came from the PRD instead of debugging.
The friction problem is the product problem
The insight that unlocked everything was treating friction as the primary design constraint, not features. Once 'one tap to record' was the north star, every other decision fell into place.
AI cost is a product decision, not an engineering detail
The two-stage pipeline was not only cheaper, it also produced better output because Sonnet reasoned over clean structured data instead of raw speech. Token economy and output quality improved together.
Abstraction layers are worth the upfront cost
Building the TranscriptionService and StorageService interfaces before they were needed made the codebase feel stable from day one. Swapping to Whisper or Supabase is a single file change.
What's next
The foundation is built for the features that would make this worth shipping: long-term trend summaries from the EntryExtract pattern bank, personalized daily prompts, mood visualization, and Supabase sync for cross-device access. The architectural decisions made at PRD time make each of those a contained addition instead of a rewrite.