Rhetro: AI Podcast Application
A cutting-edge AI podcast application that simplifies content creation. It converts text into high-quality speech and generates eye-catching thumbnails using advanced AI models. Perfect for both seasoned podcasters and beginners, Rhetro streamlines the production process, letting you focus on delivering engaging content.
- Next.js 14 (App Router)
- TailwindCSS
- Shadcn UI
- Google TTS
- Gemini
- Clerk
- Convex
- Sentry
- Databuddy (analytics)
- Convert your written content into high-quality, natural-sounding speech, making podcast production faster and more efficient.
- Generate visually appealing and professional-looking thumbnails for your podcast with the help of advanced AI models, ensuring your podcast stands out.
rhetro.mp4
Rhetro is split between a Next.js frontend and a Convex backend-as-a-service. There is no custom server β all server-side logic runs as Convex functions (queries, mutations, actions, HTTP routes).
Browser βββΊ Next.js (App Router) βββΊ Convex (DB + Storage + Actions) βββΊ Google APIs (TTS / Gemini)
β β²
β β
βββ Clerk (auth + hosted UI) βββΊ svix webhook βββΊ Convex /clerk
Frontend β app/
- Route groups:
(auth)for/signin,/signup;(root)for the authenticated shell (create,discover,podcasts,profile). middleware.tsprotects every non-public route via Clerk.- Root layout wires up
ConvexClerkProvider(Convex client authenticated with Clerk JWTs),AudioProvider, and Databuddy analytics.
Backend β convex/
schema.tsβpodcasts(with search indexes on author, title, description) anduserstables.podcasts.ts,users.tsβ CRUD, search, view counting, top-creator queries.files.tsβ issues pre-signed upload URLs for Convex Storage (audio + thumbnail blobs).googleTTS.tsβ Convex action calling Google Cloud TTS for MP3 synthesis.gemini.tsβ Convex action calling Geminigemini-3-pro-image-previewfor thumbnails.http.tsβPOST /clerkHTTP route that verifies svix signatures and mirrors Clerkuser.created/updated/deletedevents into theuserstable.auth.config.tsβ trusts the Clerk JWT issuer soctx.auth.getUserIdentity()works inside queries/mutations.
Observability β Sentry is wired through next.config.mjs (withSentryConfig) plus sentry.{client,server,edge}.config.ts and instrumentation.ts.
| Component | Hosted on |
|---|---|
| Next.js app | Vercel |
| Convex backend | Convex Cloud |
| Auth | Clerk (hosted) |
| File storage | Convex Storage |
| AI inference | Google Generative Language API |
| Error tracking | Sentry |
| Analytics | Databuddy |
Pushing to main deploys the Next.js app to Vercel. The Convex backend is deployed separately with npx convex deploy (typically wired into the same CI step).
Two processes need to run side-by-side: the Next.js dev server and the Convex dev server.
npm install
npx convex dev # in one terminal β pushes convex/ to your dev deployment, regenerates _generated/
npm run dev # in another terminal β starts Next.js on http://localhost:3000Copy .env.example to .env.local and fill in:
| Variable | Source |
|---|---|
CONVEX_DEPLOYMENT |
Set automatically by npx convex dev (CLI-only, used to push code) |
NEXT_PUBLIC_CONVEX_URL |
Convex deployment URL β used by the browser to open the WebSocket |
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY |
Clerk dashboard |
CLERK_SECRET_KEY |
Clerk dashboard |
CLERK_WEBHOOK_SECRET |
Clerk webhook endpoint pointing at <convex-url>/clerk |
NEXT_PUBLIC_CLERK_SIGN_IN_URL |
/signin |
NEXT_PUBLIC_CLERK_SIGN_UP_URL |
/signup |
Convex actions also need GOOGLE_GENERATIVE_AI_API_KEY β set this in the Convex dashboard (Environment Variables), not in .env.local, since the actions execute on the Convex backend, not in Next.js.