← All projects

Project notes / 2026

PodiumA speaking coach,
one take at a time.

An iOS app for practicing how you speak. Pick a lesson, warm up, record a short take, and get feedback you can use on the next try.

RoleSolo builder · product to backend

ReleaseShipped on the App Store

StatusRetired · September 2026

Podium Explore screen with Clear Speech, Public Speaking, and Everyday Confidence courses. The Podium recorder beneath a prompt to describe your day in 60 seconds. Podium feedback with a coaching focus point, filler count, speaking pace, and relevance notes.

From a prompt to a little more confidence.

Courses
21
Lessons
249
Takes per attempt
3
Platform
iOS
01

A small loop for a hard skill.

Podium turned “I want to speak more clearly” into something concrete to do: a short lesson, a recording, a little feedback, and another attempt.

Three longer roadmaps covered clear speech, everyday confidence, and public speaking. Shorter courses and standalone missions made room for specific situations, from introducing yourself to making a point at work.

The product combined a structured curriculum with AI coaching. The lesson supplied the task; the recording supplied the evidence; the feedback pointed toward the next repetition.

02

Inside the app.

The path from choosing a course to finishing a take. Scroll through the screens; open any image for the full view.

Podium Explore screen with Clear Speech, Public Speaking, and Everyday Confidence courses.
01

Find a course

A personal course library and shorter paths for confidence, clarity, social situations, and work.

A timed Podium warmup with four exercises and a Skip Warmup button.
02

Settle in

A brief, optional warmup before the recording: jaw release, lip trill, tongue movement, and a breath.

The Podium recorder beneath a prompt to describe your day in 60 seconds.
03

Make a take

One prompt, a time limit, and a recorder on the same page. Each lesson attempt allowed up to three takes.

Podium processing a recording, showing uploading, transcribing, and analyzing stages.
04

Follow the work

Upload, transcription, and analysis stayed visible while the backend worked on the recording.

Podium feedback with a coaching focus point, filler count, speaking pace, and relevance notes.
05

Get a next step

Pace and filler estimates sat alongside coaching on clarity, relevance, and what to change next.

Podium completion screen showing Everyday Confidence roadmap progress and a Next Lesson button.
06

Keep going

The completed lesson fed into the course roadmap, with a clear next lesson to return to.

Podium mission picker with confidence exercises including a 20-second introduction.
07

Practice a real situation

Short, category-based missions used the same recorder and feedback pipeline as the longer courses.

01—07 Scroll to explore →

03

From microphone to coaching.

The phone handled practice. The API handled requests. A background worker did the slow work, with progress saved between stages.

Session processingClient → API → jobs → feedback
  1. 01 / On the phone

    Expo + React Native

    Choose a lesson, record audio, and send it with the user's auth token.

    Apple sign-in · Expo Audio
  2. 02 / Request boundary

    FastAPI on Railway

    Verify identity, enforce usage limits, create the session, and accept the upload.

    Authenticated REST API
  3. 03 / Durable state

    Supabase

    Save audio in a private bucket and enqueue a transcription job in Postgres.

    Auth · Postgres · Storage
  4. 04 / Background work

    Python worker

    Claim a job, read its audio, and recover interrupted work with retries and stale-lock handling.

    Postgres jobs · SKIP LOCKED
  5. 05 / Speech + feedback

    Whisper + GPT-4o-mini

    Transcribe, calculate pace and fillers, then generate coaching using the lesson prompt.

    Transcribe → measure → coach
  6. 06 / Back to practice

    Save, poll, review

    Persist the result. The app polls the session, shows feedback, and lets the user try another take.

    Same screen · next action
Transcription and analysis were separate queued jobs. The database held the session state, so the request that uploaded a recording did not have to wait for the full coaching pipeline.
The stack, by responsibility
LayerToolsResponsibility
MobileExpo · React Native · TypeScriptExpo Router, audio recording, and Zustand state.
API & workerFastAPI · Python · RailwayAuthenticated requests and asynchronous processing.
Data & identitySupabase · PostgreSQLAuth, relational data, private Storage, and a jobs table.
Speech & coachingWhisper-1 · GPT-4o-miniTranscription, calculated metrics, and structured coaching.
SubscriptionsRevenueCatMobile purchases, entitlements, and backend webhooks.
04

Build notes / a retrospective

The engineering decisions

A practice attempt was more than one recording

A lesson attempt grouped up to three takes. Each take had its own recording, transcript, processing state, and feedback. The user could choose a take to finish the attempt. Keeping attempts and sessions separate made it possible to preserve the earlier work without treating every recording as a completed lesson.

Slow work belonged in a queue

The API accepted the upload and queued transcription. A separate Python worker claimed jobs through a Postgres function using FOR UPDATE SKIP LOCKED. That kept two workers from claiming the same available job at once. Stale locks, bounded retries, and backoff gave interrupted jobs a path to recovery.

Transcription saved its result before analysis was queued. The app polled the session endpoint and showed uploading, transcribing, and analyzing on the same screen. The waiting state was part of the practice experience.

Measurements and coaching had different jobs

Python calculated words per minute from transcript length and recording duration, and counted filler phrases using explicit patterns. The language model received the transcript, those metrics, and the lesson prompt, then returned a coaching label, observations, and one next-step focus point.

These were transcript-derived estimates, not an acoustic or clinical assessment. If transcription omitted a filler, the count could miss it too. Keeping that distinction clear is something I would carry into the next version.

Identity and billing reached the backend

Native Sign in with Apple connected to Supabase Auth. FastAPI checked bearer tokens with Supabase and scoped application operations to the authenticated user. The database also had row-level security policies for user-owned records and private audio paths. The privileged Supabase key stayed on the backend.

RevenueCat handled the mobile purchase integration. An authenticated webhook updated the user’s subscription tier, while the backend enforced trial and Pro usage limits. A separate retention task could remove audio older than 30 days while keeping transcripts and coaching history.

What I took from it

An AI feature is a whole product loop. Recording, upload failures, waiting, feedback, retrying, and choosing the next lesson all needed to work together. The model call was one stage in that loop.

Useful feedback needs a next action. Pace and filler counts were easiest to use when they led to a specific thing to try on the next take. The curriculum and warmups gave the feedback somewhere to go.

Shipping exposes the work around the demo. Apple sign-in, App Store delivery, subscriptions, background jobs, data access, and retention were as much a part of Podium as the recorder and coaching screens.

Shipped, learned, archived

Podium reached the App Store, and I used it myself. I retired it in September 2026 and shut down the hosted services. Before doing that, I saved the application code, live database schema, courses, lessons, and restart documentation. It is a finished learning project I can revisit, rather than an app currently available to download.

Three more captures from development

Processing states and feedback from testing the recording loop.

Development capture of the recorder and session processing timeline.
Analysis in progress
Development capture showing a finished session and its coaching response.
A completed session
Development capture of second-take feedback, pace, and a transcript excerpt.
Feedback on a second take