Echo 🎙️
Your life, in your own voice. A voice-first journaling social app.
💡 Inspiration
We kept hitting the same gap in our own lives: we mean to journal, but we rarely do. Opening an app and typing is just enough friction that the moment passes — and the moments most worth keeping arrive when our hands are busy: walking home, cooking dinner, rocking a baby at 3 a.m.
And even when we do write, a typed line flattens the memory. It can't hold the laugh, the pause, or the way we actually sounded that day, a voice note can.
The second spark was language. In multilingual families, a grandparent and a grandchild often don't fully share one, so the small daily stories never travel between them.
So we built Echo: tap, talk, done - and it handles the rest. Speak it · keep it · share it.
⚙️ How it works
$$ \text{🎙️ record} \rightarrow \text{S3} \rightarrow \text{Transcribe} \rightarrow \text{Translate} \rightarrow {\text{EN}, \text{ES}, \text{FR}} $$
You tap record and talk. The clip uploads to Amazon S3 with a presigned URL, Amazon Transcribe turns your voice into text, and Amazon Translate adds Spanish and French automatically. The entry saves to your journal, kept private or shared into a social feed. The UI shows a "Transcribing…" state and fills in the real text the moment it's ready.
🗄️ Two AWS databases, chosen by data shape
The data has two shapes, so we used two databases - each where it's strongest:
| Amazon DynamoDB | Amazon Aurora PostgreSQL Serverless v2 | |
|---|---|---|
| Type | Serverless NoSQL (key-value) | Relational, autoscaling |
| Holds | echo-entries, echo-social |
users, follows, chapters, comments |
| Role | Recordings, transcripts, likes | Profiles + the social graph |
| Powers | Your journal | Feed, follow, people-search |
DynamoDB takes the append-heavy entry data; Aurora handles everything that needs joins — like building your feed from who you follow → their public entries.
Rest of the stack: Next.js 16 · TypeScript · NextAuth (Google + email) · Amazon Bedrock (Claude Haiku) · AWS CDK · deployed on Vercel.
📚 What I learned
- NoSQL vs. relational is a data-shape decision, not a preference. Entries are append-heavy and accessed by key → DynamoDB. The social graph is all relationships and joins → Aurora. Using both, each where it's strongest, made the whole app simpler.
- The RDS Data API is the unlock for serverless databases. Aurora lives in a private VPC, so it's normally unreachable from a serverless host like Vercel. The RDS Data API exposes it over HTTPS — so the entire app runs serverless with no VPC tunnel, no connection pooling headaches.
- Orchestrating an async ML pipeline. Transcription isn't instant, so we designed around it: optimistic UI, then poll. With interval $\Delta t = 5\text{s}$ and a cap of $n = 30$ attempts, the wait is bounded by $T_{\max} = n \cdot \Delta t = 150\text{s}$, after which we surface a graceful state.
- Serverless economics are linear. Aurora Serverless v2 scales in the range $\text{ACU} \in [0.5,\, 4.0]$, and DynamoDB on-demand cost is essentially $C \propto \sum_i (r_i + w_i)$ over read/write requests — so an idle hackathon app costs almost nothing, and it still scales if usage spikes.
🧗 Challenges
| Hit a wall | Got past it |
|---|---|
| Aurora unreachable from localhost (private VPC) | Switched to the RDS Data API (HTTPS) |
| CDK wouldn't bootstrap (root tsconfig is ESM) | Separate tsconfig.infra.json (CommonJS) |
| Bedrock model id invalid for on-demand calls | Cross-region inference profile |
| Hydration mismatch on load | Move localStorage out of the useState initializer |
| Playback was a fake progress bar | Real audio via presigned S3 GET URLs |
| Feed entries had no author names | Batch profile lookup in Aurora to enrich them |
| A like wrote a phantom negative counter | Found in end-to-end testing; removed the dead write |
invalid_client on deploy |
Set env vars (+ redeploy) and the OAuth redirect URI |
🚀 What's next
Co-authored "chapters," offline capture for moments without signal, more languages via Amazon Translate, and richer AI reflections with Bedrock - so Echo becomes a living, multilingual record of a life, in the voice that lived it.
Built With
- amazon-aurora-postgresql-serverless-v2
- amazon-bedrock
- amazon-dynamodb
- amazon-transcribe
- amazon-translate
- amazon-web-services
- next.js-16
- nextauth
- typescript
- vercel
Log in or sign up for Devpost to join the conversation.