Personal Project · 2025

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.

Expo 54 · React Native · TypeScriptClaude Haiku + Sonnet · AsyncStorage
Voice Journal app home screen

TL;DR

Built end-to-end in Expo + React Native, with recording, on-device transcription, a two-stage Claude pipeline, and local storage all working.
Two-stage Haiku → Sonnet pipeline cuts per-entry AI cost ~10× vs. sending raw transcripts to one expensive model.
Four HMWs drove the core product decisions: voice-first input, no-setup recording, conversational follow-ups, and multi-dimensional extraction in a single entry.
01The SparkPersonal need

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.

02Research3 competitors · 4 HMWs

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.

03ArchitecturePRD + pipeline design

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.

04BuildPOC → V2 → Final

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.

Voice Journal POC, screen 1
Record screen
Voice Journal POC, screen 2
Transcribing state
Voice Journal POC, screen 3
Entry detail + AI output

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.

Voice Journal V2, screen 1
Home, entry list
Voice Journal V2, screen 2
Follow-up Q&A
Voice Journal V2, screen 3
Insights view

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.

Voice Journal final login
Login
Voice Journal final recording
Recording
Voice Journal final entry
Entry detail
Voice Journal final insights
AI insights
Voice Journal final follow-up
Follow-up questions
Voice Journal final answers
Voice replies
05Key ChallengeLong-term trends

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

1

Weekly recaps generated from a week of EntryExtract summaries, not raw transcripts

2

A pattern bank built from recurring topics, emotions, and goals across all entries

3

Personalized journal prompts generated from that pattern bank, rooted in what you actually talk about rather than generic psychology templates

4

Mood trend visualization without a separate tracker, because the data is already structured

06ReflectLearnings + what's next

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.

Next Project

Writing Probe