A privacy-first AI voice journaling web app. Record your thoughts, get AI transcription + reflection, and keep everything on your device.
- Voice recording via MediaRecorder API with real-time countdown
- AI transcription via Groq Whisper
- AI reflection — a warm second-person response generated by Llama 3.3 70B
- Local storage only — all journal entries live in your browser's IndexedDB (Dexie)
- Daily minute quotas — 20 min/user/day, 200 min/day global cap tracked in Upstash Redis
- No login, no accounts — anonymous UUID + IP-based identity
- Hard cost cap — ~$5–7/month at max usage (well under $12)
git clone <repo>
cd cathart
npm installCopy .env.local.example to .env.local and fill in your keys:
cp .env.local.example .env.local| Variable | Where to get it |
|---|---|
GROQ_API_KEY |
console.groq.com — free tier available |
UPSTASH_REDIS_REST_URL |
console.upstash.com — free tier sufficient |
UPSTASH_REDIS_REST_TOKEN |
Same as above |
npm run dev- Push to GitHub
- Import to vercel.com
- Add the three env vars in Project Settings → Environment Variables
- Deploy
- New Web Service → connect repo
- Build command:
npm run build - Start command:
npm start - Add env vars in the Render dashboard
app/
page.tsx — main UI (recording + history)
api/
quota/route.ts — GET quota status for a user
transcribe/route.ts — POST audio → transcript (checks + increments quota)
reflect/route.ts — POST transcript → AI reflection
components/
QuotaBar.tsx — daily minutes remaining bar
RecordButton.tsx — record / stop button with live timer
JournalEntryCard.tsx — expandable past entry card
hooks/
useRecorder.ts — MediaRecorder lifecycle + auto-stop at quota limit
useQuota.ts — quota fetching
lib/
db.ts — Dexie (IndexedDB) setup
quota.ts — Upstash Redis quota logic
userId.ts — anonymous UUID from localStorage
ipHash.ts — IP → SHA-256 hash (server-side)
| Resource | Limit | Rationale |
|---|---|---|
| Per-user daily | 20 min | Encourages focused journaling |
| Global daily | 200 min | ~$2.40/day max Groq cost |
| Monthly ceiling | ~$7/mo | Groq Whisper + Llama at 200 min/day |
Quotas reset at UTC midnight via key TTL expiry (48h Redis TTL).
- Audio and transcripts are processed by Groq's API transiently and not stored by the server
- No journal content is written to any server-side database
- All entries exist only in the user's browser (IndexedDB)
- Redis stores only numeric minute counters keyed to an anonymous UUID+IP hash