Personal audio intelligence
Orin
A two-host audio briefing generated from
your emails, calendar, tasks, and the news.
Your data. No one else's.
By Luka Löhr
The journey
The Journey of Building Orin
Jan 2026 — present

Apps like this already existed. That was the problem. They had access to my inbox, my calendar, all my accounts — and I was the product. Device IDs, email addresses, everything I'd connected, sold to brokers I'd never heard of. I wanted the briefing without the trade-off. So I built it myself.

10 Jan 2026
The first commit

I had no idea what I was doing with Firebase, but it was the obvious starting point for someone who'd never built backend infrastructure before. The first version was a Python Cloud Function that called Google's TTS API, downloaded a jazz track from Firebase Storage, mixed them together in memory, and streamed the audio over HTTP. No user data yet, no personalization — just proof that the core idea worked as audio. By the end of the day I'd pushed over twenty commits: CORS fixes, region moves when the TTS model wasn't available in Europe, Firebase Auth, rate limiting. None of it was clean. All of it was necessary.

11 – 12 Jan 2026
Wiring in real data

The next day I wired in real data. Firestore schemas for OAuth tokens and briefing history so it wouldn't repeat yesterday's stories. A Gmail provider pulling today's emails. Google Calendar with a 7-day window. Gemini generating a proper two-host script from your actual inbox — structured JSON output, Pydantic validation, the whole thing. Getting Gemini to reliably produce structured output turned out to be much harder than expected. The safety filters kept blocking things. The JSON format kept shifting. I spent most of the 12th just debugging API calls — removing thinking config, adding it back, stripping the prompt down to nothing, adding error handlers one by one. Eventually it clicked and the briefings started actually sounding like they were about someone's real day.

13 – 16 Jan 2026
Making it sound good

Once the data was working I shifted focus to the audio itself. Refactored to Jinja2 templates so the prompts were maintainable. Moved script generation to Vertex AI. Added real audio mixing — the jazz fades down when the voice starts, fades back up in the quiet gaps, proper outro. Content curation rules: skip spam, skip password reset emails, paraphrase rather than quote directly, address the user by name. Then I added a separate news mode with its own intro audio and Scrapingdog for web research. Then Microsoft and Outlook came in as a second data provider — parallel token refreshing for multiple accounts. Notion briefly existed and then got removed the same day I added it. The shape of what Orin should be was getting clearer even as the codebase was getting messier.

17 – 27 Jan 2026
News, iOS, and the long middle

The second half of January was slower. News mode got proper regional and global scoping so you could ask for local or world news. An auth gateway for routing different request types. Apple Sign-In via an OAuth broker. Documentation for an iOS client — there was an app being built in parallel and it needed a real API guide. A lot of audio timing tweaks and prompt refinements that don't show up as dramatic commits but take hours. By the end of the month Orin worked, more or less, but the Python Firebase Functions foundation was starting to show its limits. Cold starts were getting worse. The architecture had grown organically and it showed.

9 Mar 2026
Moving to Cloud Run

After a quiet February I moved everything to Cloud Run. Firebase Functions had worked well enough to get started but the cold starts were painful and the deployment model was too rigid. Migrated to standalone containers, split the auth and stream services into their own directories, cleaned up the API structure. Switched the news research from Scrapingdog to Perplexity Sonar which gave much better live results. Started preloading the music tracks into memory at instance startup so there were no per-request GCS downloads adding latency. The first real architectural decision that would matter long term.

11 Mar 2026
Dropping Firebase entirely

Two days after Cloud Run, the bigger migration: everything off Firebase Auth and Firestore and onto Supabase Postgres. Firebase had made sense at the start because I knew it and it was fast to get running. But it wasn't the right foundation for what Orin needed to become — proper relational data, real token management, EU data residency without workarounds. The new auth system used self-signed JWTs with no Firebase SDK dependency anywhere. Custom domains went live the same day — orin-ai.app, auth.orin-ai.app, api.orin-ai.app. Cloud Run moved to Frankfurt to sit next to the Supabase database. The landing page appeared for the first time. Things started feeling less like a prototype and more like an actual product.

12 – 15 Mar 2026
The rewrite

The week of the 12th was the most intensive stretch of work on the project. It started with latency profiling — dense timing logs at every stage of the pipeline to understand where every second was going. Token caching to skip OAuth round-trips on each request. Full parallelization of data fetching across providers. 90-day sessions with silent refresh tokens so the CLI would re-auth without interrupting you. CPU boost on Cloud Run. New music library licensed from Epidemic Sound. On the 14th I stripped out GCS and Firestore at runtime — neither was actually needed anymore — and added token theft detection with rotating token families. Then on the 15th I scrapped the Python backend completely and rewrote orin-auth, orin-stream, and the CLI in Bun and TypeScript. The in-process AAC encoder replaced an external ffmpeg subprocess that had been adding hundreds of milliseconds. About 600ms of startup latency was eliminated in a single afternoon. The whole stack suddenly pointed in the same direction.

16 – 19 Mar 2026
Memory

The week after the rewrite I built the part I'd been thinking about since the beginning: memory. orin-memory is a separate service that runs after every briefing and updates what Orin knows about you. It uses a Gemini tool-calling agent loop to decide what to keep, what to update, what patterns are emerging — the people you work with, the projects you keep mentioning, the themes that come up again and again across your calendar and inbox and tasks. I added OAuth connectors for Spotify, GitHub, Notion, Slack, Todoist, Linear, and more — fifteen services in total — all feeding into a profile that builds over time. The idea is that Orin shouldn't just read your inbox every morning. It should gradually learn what your mornings are actually about.

20 Mar 2026
First briefing

Ten weeks after the first commit. I ran a full briefing through the CLI, saved the audio to disk, and listened back. This is what it sounds like.

Recorded 20 March 2026 — first briefing ever delivered
0:00

The backend is real, memory is running, the audio is clean, and the connectors are live. Still a lot to build.