active

Murmur

A voice-first notes app designed for fast, calm thought capture. Press and hold to record, release to transcribe.

Web AppNext.jsAIVoiceProductivity

Overview

Murmur is a voice-first mobile app for capturing fleeting thoughts in under 5 seconds. The core experience: hold a button, speak, release. No typing, no menus, no setup. Recordings upload instantly and sync across devices via Clerk authentication.

Built as an Android-first Flutter client with a Node.js backend, private Cloudflare R2 audio storage, and async AI for semantic search.

One gesture capture: press-and-hold → recording starts in under 200ms → release → auto-upload → saved. The user remembers the thought, not the app.

Core Features

  • Ultra-low latency capture - Press-and-hold maps directly to the recorder; no countdown or confirmation
  • Invisible sync - Failed uploads retry with exponential backoff; local file retained until success
  • Future Capsules - Time-lock a memo to unlock later (1 hour to 50 years) with lazy unlock + notifications
  • Semantic search - OpenAI embeddings over voice memos; cosine similarity ranking without a separate vector DB
  • Private by default - R2 bucket is private; playback uses signed URLs with a 1-hour TTL

Architecture

Flutter App ──► Clerk SDK ──► Clerk (Auth)
     │
     └──► Dio API Client ──► Nginx (SSL) ──► Express API (EC2)
                                                      │
                                    ┌─────────────────┼─────────────────┐
                                    ▼                 ▼                 ▼
                              PostgreSQL          Cloudflare R2      Clerk API
                              (Prisma)           (Private Bucket)   (JWT Verify)
  • Client: Flutter + Riverpod + Clerk Flutter SDK; record for capture, just_audio for playback
  • API: Node.js + Express on AWS EC2 (PM2 + Nginx); Clerk session JWTs only - no app-issued tokens
  • Storage: Cloudflare R2 (private); zero-transcode native M4A storage (read the deep-dive note)
  • Data: PostgreSQL + Prisma; compound index (userId, createdAt DESC) for instant library loads
  • AI: Async Whisper + text-embedding-3-small; never blocks the upload response

Audio Pipeline

  1. Client starts recording on press (<200ms)
  2. On release, client PUTs native AAC (.m4a) directly to Cloudflare R2 via presigned URL
  3. Server receives completion ping, verifies object via HeadObject, and writes DB row (zero CPU transcoding)
  4. Async worker streams audio buffer directly from R2 to OpenAI Whisper
  5. Library updates optimistically on the client; AI embedding runs fire-and-forget

Outcomes

  • Sub-5s end-to-end capture path from gesture to saved memo
  • Zero custom auth stack - Clerk owns session lifecycle end to end
  • Zero-transcoding pipeline: 98% CPU reduction and zero server disk I/O

Reliability first: failed uploads retry silently in the background - no data loss, no friction.