Skip to content

lindsaycode05/podcastogist

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

96 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐ŸŽค Podcastogist

AI-Powered Podcast Post-Production Platform
Durable, real-time SaaS workflow pipeline that turns one upload into a full content kit:
upload podcast once โ†’ get a complete content pack (transcript + chapters + highlights + social drafts) with real-time progress updates.

Podcastogist Hero

Website: https://podcastogist.com
Instant demo (no login): https://podcastogist.com/demo
Flagship Personal Project: End-to-end SaaS build created to demonstrate full-stack product engineering depth.
Primary Audience: Recruiters, hiring managers, and engineers reviewing architecture.
Build Effort: ~200 hours (Dec 6 โ†’ Dec 30, 2025).
LinkedIn: https://www.linkedin.com/in/lindsaycode/

Next.js React TypeScript Clerk Convex Inngest AssemblyAI OpenAI Vercel%20Blob Tailwind shadcn/ui Biome CI Quality Gate (Biome) CI Quality Gate (Typecheck) CI Quality Gate (Build) CI Tests (Unit) CI Tests (Integration) CI Tests (E2E) CodeQL Dependabot

At a glance:

  • ๐Ÿš€ Upload podcast audio once, get recaps, social posts, highlights, hashtags, timestamps, and speaker dialogue.
  • โšก Durable background orchestration via Inngest with parallel, webhook-driven AI tasks (no long-running HTTP).
  • ๐Ÿ” Clerk-based authentication and plan gating (Free / Plus / Max).
  • ๐Ÿ“ก Real-time UI updates via Convex subscriptions (no polling).
  • ๐ŸŒ— Full dark mode + mobile-responsive UI.
  • ๐Ÿงช Deterministic CI test suite (unit + integration + E2E) with real-time Convex wiring.

๐ŸŽฅ Video Walkthrough

A fast, 200 seconds, high-signal walkthrough of the product flow, architecture, and quality gates.
This video is meant for people who want the context in moments.

Intro - 0:00 | Product Overview - 0:30 | Architecture Overview - 2:20 | CI & Tests - 3:15

Podcastogist-Video-Walkthrough.mp4

๐Ÿ“‹ Table of Sections:

๐Ÿ“Œ Product Overview

๐ŸŽฅ Media & UI

๐Ÿ’ณ Plans & Gating

๐Ÿ—๏ธ Architecture & Data

๐Ÿง  AI & Processing

๐ŸŽจ Design & UX

๐Ÿงฐ Engineering Notes

๐Ÿ”ฎ Future & Wrap-up


๐Ÿ’ก What Podcastogist Is

Podcastogist is an AI-powered podcast post-production platform.
You upload a single audio file of a podcast/interview and receive a complete content pack: Recaps, Social Posts, Titles, Hashtags, YouTube Timestamps, Highlight Moments and the Speaker Dialogue of the whole episode, in minutes.
Itโ€™s built as a full-stack SaaS workflow that emphasizes reliability and real-time UX.
The experience is designed to feel instant even though heavy AI work happens in the background.

Core idea: one upload becomes everything a podcaster needs to publish, promote, and distribute.


๐ŸŽฏ Why It Exists

Podcast post-production is repetitive, slow, and expensive.
Creators spend hours converting one episode into multiple formats and channel-specific copy.
Podcastogist automates that last-mile distribution layer.
The goal is to free creators from tedious tasks so they can focus on content.

It compresses hours of work into minutes.


๐Ÿ‘ฅ Who It's For

Podcastogist is built for creators who ship episodes and then get stuck in the post-production grind.

If you regularly need to:

  • Write different copy for multiple social platforms
  • Craft titles, descriptions, and hashtags per episode
  • Produce chapter markers or clipโ€‘worthy moments

โ€ฆthis is the workload Podcastogist automates.


๐Ÿง  What This Project Demonstrates

This project is designed to prove full-stack engineering competency end-to-end.
It highlights practical SaaS architecture patterns and real production tradeoffs.

What this build shows:

  • โœ… A production-style, multi-service architecture (auth, storage, DB, workflows, AI providers).
  • โœ… Durable workflow orchestration (retries, step isolation, observability, using Inngest).
  • โœ… Parallelization (fan-out / fan-in) to reduce end-to-end processing time.
  • โœ… Plan-based feature gating with Clerk (Free / Plus / Max) across UI + backend enforcement.
  • โœ… Realtime UI updates driven by Convex database subscriptions (no polling).
  • โœ… Large-file constraints (size + duration) enforced by plan limits with progress, validation, and safe retries.
  • โœ… Long-running transcription handling via webhook-based status updates.
  • โœ… Multi-provider AI pipeline (AssemblyAI + OpenAI) with schema validation.
  • โœ… Clean UI/UX: mobile responsive layout + dark mode toggle.
  • โœ… Type-safe boundaries using schema validation (Zod) and strong TS typing.
  • โœ… Developer experience: consistent formatting/linting (Biome), modern UI primitives.
  • โœ… CI quality gate on every push to main (Biome, typecheck, build).
  • โœ… Deterministic test suite that validates real SaaS workflows (Vitest + Playwright + Mock Providers Ecosystem).

๐Ÿง  Why it matters

  • Long-running AI jobs feel broken without live, reliable progress signals.
  • Cost boundaries need real enforcement, not just UI affordances.
  • Partial failures must be recoverable without rerunning everything.

โœจ Feature Suite

Podcastogist is organized around outcomes, not just features.
Each capability exists to ship content faster and smarter.

๐Ÿ“ค Upload & Validation

  • Drag-and-drop upload with file type validation and size gating.
  • Supports MP3, WAV, M4A, FLAC, OGG, AAC, Opus, WebM, and 3GP/3G2.
  • Pre-validation against plan limits before any expensive processing.
  • Duration extraction using HTML5 Audio; fallback to file-size estimation.
  • Progress bar, status states, and explicit error messaging.

๐Ÿงพ AI Transcription (AssemblyAI)

  • Speaker diarization enabled for every transcript (access gated by plan).
  • Auto chapters generated for better topic segmentation.
  • Word-level timestamps + formatted text for higher accuracy context.
  • Asynchronous transcription via webhooks (no long-running HTTP).

๐Ÿ“ Recaps & Summaries

  • Multi-format recaps: full summary, bullet points, insights, and TL;DR.
  • Generated with OpenAI Structured Outputs (Zod-validated JSON).
  • Uses transcript + chapter context to improve relevance.

๐Ÿ“ฃ Social Post Generation

  • Six platform-specific posts: Twitter/X, LinkedIn, Instagram, TikTok, YouTube, Facebook.
  • Each post has its own tone and formatting constraints.
  • Copy-to-clipboard UX for each platform card.

Style cues per platform:

  • Twitter/X: concise hook with a clear takeaway.
  • LinkedIn: professional framing and insight-heavy tone.
  • Instagram: caption-style summary with light engagement prompts.
  • TikTok: short, energetic copy for clips.
  • YouTube: description-friendly summary + context.
  • Facebook: community-friendly opener and discussion prompt.

๐Ÿง  Titles & SEO Keywords

  • YouTube short titles, YouTube long titles, podcast titles, SEO keywords.
  • Rendered with badges and lists for quick scanning.
  • Structured outputs ensure consistent formatting.

#๏ธโƒฃ Hashtags

  • Platform-specific hashtag strategies.
  • Visible as inline badges for fast copy/reuse.

๐ŸŽฌ Highlight Moments

  • Extracted from AssemblyAI auto chapters.
  • Uses accurate timing with human-readable timestamps.
  • Presented as a list of โ€œclip-worthyโ€ sections.

๐Ÿงญ YouTube Timestamps

  • Hybrid generation: AssemblyAI timestamps + GPT-enhanced chapter titles.
  • YouTube-ready formatting (MM:SS or HH:MM:SS + title).
  • One-click copy of the entire chapter list.

๐Ÿ—ฃ๏ธ Speaker Dialogue

  • Speaker-labeled dialogue with confidence scores.
  • Gated to Max plan access (but always captured in transcript).
  • Color-coded badges for visual scanning.

๐ŸŒ— Dark Mode + ๐Ÿ“ฑ Responsive UI

  • Theme toggle in the navbar (next-themes).
  • Works across light/dark with consistent contrast.
  • Full mobile responsiveness across key views.

๐Ÿ”’ Feature Gating & Upgrade UX

  • Locked tabs show upgrade prompts and plan details.
  • Upgrade CTAs are contextual to the missing feature.
  • Upgrade flow also supports โ€œgenerate missing featuresโ€ after upgrade.

๐Ÿ“ฆ Content Pack Output

The output bundle is designed for distribution across major channels.

Outputs generated today:

  • Recaps (full, bullets, insights, TL;DR).
  • Social posts (Twitter/X, LinkedIn, Instagram, TikTok, YouTube, Facebook).
  • Titles (YouTube short/long, podcast titles, SEO keywords).
  • Hashtags (YouTube, Instagram, TikTok, LinkedIn, Twitter).
  • YouTube timestamps (chapters).
  • Highlight moments (clip candidates).
  • Speaker dialogue (diarized transcript view).

๐Ÿ“‹ Output Matrix (What You Get)

Output Description Source Plan Access
Recaps Full summary + bullets + insights + TL;DR OpenAI GPT-5-mini Free / Plus / Max
Social Posts 6 platform-optimized posts OpenAI GPT-5-mini Plus / Max
Titles YouTube short/long + podcast + SEO OpenAI GPT-5-mini Plus / Max
Hashtags Platform-specific tags OpenAI GPT-5-mini Plus / Max
Highlight Moments Clip-worthy moments AssemblyAI chapters Max
YouTube Timestamps Chapters with GPT titles AssemblyAI + OpenAI Max
Speaker Dialogue Speaker diarization view AssemblyAI Max

๐Ÿงฉ Workflow Snapshot

Podcastogist follows a durable, step-based processing pipeline.

High-level flow:

  1. User signs in securely with Clerk (Google or email/password).
  2. User uploads audio via drag & drop.
  3. File is uploaded directly to Vercel Blob with progress tracking.
  4. Server action creates a project and triggers an Inngest workflow.
  5. AssemblyAI transcribes audio asynchronously via webhook.
  6. Parallel AI jobs run based on plan gating.
  7. Results are saved into Convex.
  8. UI updates in real-time as each step completes.

๐Ÿ”ง Application Pipeline Flow (diagram)

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#3B82F6','primaryTextColor':'#FFFFFF','primaryBorderColor':'#F97316','lineColor':'#3B82F6','secondaryColor':'#F97316','tertiaryColor':'#FFF7ED'}}}%%
flowchart TD
  A[User Uploads Podcast Episode] --> B[File Stored in Vercel Blob]
  B --> C[Inngest Event Fired]
  C --> D[Project Status: In Progress]
  D --> E[AssemblyAI Transcription]
  E --> F[Parallel AI Output Generation]
  F --> G[Outputs Saved to Convex]
  G --> H[Project Status: Completed]
  H --> I[User Views Project Detail page]
  I --> J[Live Updates via Convex]
Loading

๐Ÿ–ผ๏ธ UI Tour

Each collage shows the same page in both themes (light/dark) and viewports (desktop/mobile).

๐Ÿ  Landing Page

Desktop + Mobile โ€ข Light + Dark Landing Page

๐Ÿ“ค Upload Page

Drag & drop upload UX + plan limits messaging.
Desktop + Mobile โ€ข Light + Dark Upload Page

๐Ÿง  Project Detail โ€” Processing

Project detail view while AI jobs are running.
Desktop + Mobile โ€ข Light + Dark Project Detail Processing

โœ… Project Detail โ€” Processed

Completed project with all unlocked content tabs.
Desktop + Mobile โ€ข Light + Dark Project Detail Processed

๐Ÿ”’ Project Detail โ€” Feature Gating

Locked tab with upgrade prompt and plan benefits.
Desktop + Mobile โ€ข Light + Dark Project Detail Feature Gating

๐Ÿ“š Projects Page โ€” Processing

Multiple projects running with live status updates.
Desktop + Mobile โ€ข Light + Dark Projects Processing

๐Ÿ“‚ Projects Page โ€” Completed

Multiple finished projects in the dashboard.
Desktop + Mobile โ€ข Light + Dark Projects Completed

๐Ÿงผ Projects Page โ€” Empty State

First-time user experience with empty projects list.
Desktop โ€ข Light + Dark Projects Empty

๐Ÿ’ณ Upgrade Page

Plan comparison and upgrade CTAs.
Desktop โ€ข Light + Dark Upgrade Page


๐Ÿ’ณ Plans & Limits

Pricing and limits are enforced consistently in UI, server actions, and API routes.

๐Ÿ’ฐ Plan Pricing

Plan Price Summary
Free $0 Recaps only โ€” try the workflow with strict limits
Plus $21/month Social posts + titles + hashtags
Max $34/month Full intelligence pack: timestamps, highlights, speaker dialogue

Note: Not a real commercial SaaS. This is a demonstration project.
Podcastogist is a fully working platform built for podcast post-production jobs & content kit generation.
Billing runs in test mode (Clerk/Stripe), so no real charges are processed.

๐Ÿ“ Plan Limits

Plan Max Projects Max File Size Max Duration
Free 3 (lifetime, incl. deleted) 10MB 10 minutes
Plus 30 (active only) 200MB 2 hours
Max Unlimited 3GB Unlimited

Edge cases (intended behavior):

  • Free plan counts lifetime projects (including deleted).
  • Plus plan counts active projects (deleting frees slots).
  • Max plan removes quota limits but still enforces file type validation.

๐Ÿงท Enforcement Points

  • Client-side pre-validation in the upload flow.
  • Server-side validation in validateUploadAction.
  • API route enforcement in /api/upload.
  • Convex project counting (Free plan counts deleted projects, Plus plan counts active).

๐Ÿงฑ Feature Gating Matrix

This is enforced by Clerk Billing features and app-side checks.

Feature Free Plus Max
Recaps โœ… โœ… โœ…
Social Posts โŒ โœ… โœ…
Titles โŒ โœ… โœ…
Hashtags โŒ โœ… โœ…
YouTube Timestamps โŒ โŒ โœ…
Highlight Moments โŒ โŒ โœ…
Speaker Dialogue โŒ โŒ โœ…

๐Ÿง  Why this gating exists

  • AI costs scale with file length and number of outputs.
  • Free proves value; Plus unlocks distribution outputs.
  • Max unlocks deep intelligence (timestamps, highlights, speaker dialogue).

๐Ÿ” How Gating Works

Feature access is enforced at multiple layers to prevent bypass.

Plan detection (Clerk):

  • has({ plan: "free" | "plus" | "max" }) is used to determine access.
  • Feature availability is mapped in PLAN_FEATURES.

UI gating:

  • Locked tabs show an Upgrade Prompt with plan details.
  • Feature tabs are wrapped with Protect to guard access.

Workflow gating:

  • Inngest pipeline conditionally schedules AI jobs by plan.
  • Recaps always run; advanced tasks only run for Plus/Max.

๐Ÿ—๏ธ Architecture Overview

End-to-end pipeline from upload to real-time results.

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#3B82F6','primaryTextColor':'#FFFFFF','primaryBorderColor':'#F97316','lineColor':'#3B82F6','secondaryColor':'#F97316','tertiaryColor':'#FFF7ED'}}}%%
flowchart LR
  A[Client Upload] --> B[Vercel Blob]
  A --> C[Server Actions]
  C --> D[Convex: create project]
  C --> E[Inngest event: podcast/uploaded]
  E --> F[AssemblyAI transcription]
  E --> G[OpenAI generation]
  F --> H[Convex: save transcript]
  G --> H[Convex: save outputs]
  H --> I[Realtime UI updates]
  I --> J[Dashboard tabs]
Loading

๐Ÿ—บ๏ธ Data Boundaries (what lives where)

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#3B82F6','primaryTextColor':'#FFFFFF','primaryBorderColor':'#F97316','lineColor':'#F97316','secondaryColor':'#F97316','tertiaryColor':'#FFF7ED'}}}%%
flowchart LR
  UI[Client UI] --> NX[Next.js]
  NX -->|URLs only| CX[(Convex)]
  NX -->|File bytes| BL[(Vercel Blob)]
  IN[Inngest] -->|Reads transcript| AI[AI Providers]
  AI -->|Structured outputs| IN
  IN -->|Writes results| CX
  CX --> UI
Loading

โšก Parallel Orchestration

AI generation runs in parallel to reduce total time.

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#3B82F6','primaryTextColor':'#FFFFFF','primaryBorderColor':'#F97316','lineColor':'#3B82F6','secondaryColor':'#F97316','tertiaryColor':'#FFF7ED'}}}%%
flowchart TD
  A[AssemblyAI Transcription Step Complete] --> B{Fan-out}
  B --> C[Recaps]
  B --> D[Social Posts]
  B --> E[Titles]
  B --> F[Hashtags]
  B --> G[YouTube Timestamps]
  B --> H[Highlight Moments]
  C --> I[Join]
  D --> I
  E --> I
  F --> I
  G --> I
  H --> I
  I --> J[Save to Convex]
  J --> K[UI updates]
Loading

Execution detail:

  • Uses Promise.allSettled to allow partial success.
  • Errors are tracked per job and saved to jobErrors.
  • Retry flow regenerates a single failed output without rerunning the entire pipeline.

๐Ÿ•ฐ๏ธ Long-Running File Handling

Long transcriptions are handled asynchronously to avoid server timeouts.

Key mechanism:

  • AssemblyAI transcription is submitted with a webhook URL.
  • Inngest step.waitForEvent waits for assemblyai/transcript.status.
  • The webhook endpoint (/api/webhooks/assemblyai) forwards status events to Inngest.

Why this matters:

  • No long HTTP requests in Next.js server functions.
  • Durable wait with retries if webhooks fail.
  • The UI remains responsive and accurate throughout processing.

๐Ÿงต Webhook-driven flow

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#3B82F6','primaryTextColor':'#FFFFFF','primaryBorderColor':'#F97316','lineColor':'#3B82F6','secondaryColor':'#F97316','tertiaryColor':'#FFF7ED','signalColor':'#F97316','noteBkgColor':'#3b83f687','noteTextColor':'#FFFFFF'}}}%%
sequenceDiagram
  participant UI as UI
  participant NX as Next.js
  participant IN as Inngest
  participant AS as AssemblyAI
  participant CX as Convex

  UI->>NX:
  note over UI,NX: upload audio
  NX->>CX:
  note over NX,CX: create project(status=uploaded)
  NX->>IN:
  note over NX,IN: emit podcast.uploaded event
  IN->>CX:
  note over IN,CX: update status=processing
  IN->>AS:
  note over IN,AS: start transcription
  AS-->>NX:
  note over AS,NX: webhook status updates(transcriptId, status)
  NX->>CX:
  note over NX,CX: update jobStatus/transcript fields
  IN->>CX:
  note over IN,CX: write AI outputs as ready
  CX-->>UI:
  note over CX,UI: realtime updates (subscription)
Loading

๐Ÿงฉ API Surface

These endpoints enable the full workflow while keeping UI clean.

๐Ÿงญ Public routes used by the app

  • POST /api/upload โ†’ generates Vercel Blob upload tokens.
  • POST /api/inngest โ†’ Inngest webhook endpoint for execution.
  • POST /api/webhooks/assemblyai โ†’ AssemblyAI webhook receiver.

๐Ÿงพ Server actions used by the client

  • validateUploadAction โ†’ plan limit validation.
  • createProjectAction โ†’ create project + trigger Inngest event.
  • deleteProjectAction โ†’ delete project + blob cleanup.
  • generateMissingFeatures โ†’ generate newly unlocked features after upgrade.

๐Ÿ“ก Event Contracts

Inngest events are strongly typed and used to orchestrate work.

๐Ÿ“ค Event: podcast/uploaded

{
  "name": "podcast/uploaded",
  "data": {
    "projectId": "<convex_id>",
    "userId": "<clerk_user_id>",
    "plan": "free | plus | max",
    "fileUrl": "https://<blob_url>",
    "fileName": "episode-42.mp3",
    "fileSize": 12345678,
    "mimeType": "audio/mpeg"
  }
}

๐Ÿ” Event: podcast/retry-job

{
  "name": "podcast/retry-job",
  "data": {
    "projectId": "<convex_id>",
    "job": "socialPosts | titles | hashtags | highlightMoments | youtubeTimestamps | recaps",
    "userId": "<clerk_user_id>",
    "originalPlan": "free | plus | max",
    "currentPlan": "free | plus | max"
  }
}

๐Ÿ“ฅ Event: assemblyai/transcript.status

{
  "name": "assemblyai/transcript.status",
  "data": {
    "projectId": "<convex_id>",
    "transcriptId": "<assemblyai_id>",
    "status": "completed | error",
    "error": "<error_message>"
  }
}

๐Ÿ—‚๏ธ Data Model

Convex uses a single denormalized projects table to store everything.
This allows real-time updates and atomic writes as jobs complete.

๐Ÿงพ Project Document (conceptual example)

{
  _id: "projects:abc123",
  userId: "user_123",
  deletedAt: undefined,
  inputUrl: "https://<blob_url>",
  fileName: "episode-42.mp3",
  displayName: "My Episode 42",
  fileSize: 12345678,
  fileDuration: 3672,
  fileFormat: "mp3",
  mimeType: "audio/mpeg",
  status: "completed",
  jobStatus: {
    transcription: "completed",
    contentGeneration: "completed"
  },
  transcript: {
    text: "...",
    segments: [
      {
        id: 0,
        start: 0,
        end: 12,
        text: "Welcome to the show...",
        words: [
          { word: "Welcome", start: 0, end: 1 },
          { word: "to", start: 1, end: 2 }
        ]
      }
    ],
    speakers: [
      {
        speaker: "A",
        start: 0,
        end: 12,
        text: "Welcome to the show...",
        confidence: 0.94
      }
    ],
    chapters: [
      {
        start: 0,
        end: 60000,
        headline: "Opening",
        summary: "Introductions and episode goals",
        gist: "intro"
      }
    ]
  },
  highlightMoments: [
    {
      time: "00:42",
      timestamp: 42,
      text: "Key takeaway",
      description: "A strong quote worth clipping"
    }
  ],
  recaps: {
    full: "Full summary...",
    bullets: ["Point one", "Point two"],
    insights: ["Insight one"],
    tldr: "One sentence hook"
  },
  socialPosts: {
    twitter: "Tweet...",
    linkedin: "LinkedIn post...",
    instagram: "IG caption...",
    tiktok: "TikTok caption...",
    youtube: "YouTube description...",
    facebook: "Facebook post..."
  },
  titles: {
    youtubeShort: ["Short title"],
    youtubeLong: ["Long title"],
    podcastTitles: ["Podcast title"],
    seoKeywords: ["keyword1", "keyword2"]
  },
  hashtags: {
    youtube: ["#podcast"],
    instagram: ["#podcast"],
    tiktok: ["#podcast"],
    linkedin: ["#podcast"],
    twitter: ["#podcast"]
  },
  youtubeTimestamps: [
    { timestamp: "0:00", description: "Intro" },
    { timestamp: "4:12", description: "Main topic" }
  ],
  error: { message, step, timestamp },
  jobErrors: { recaps, socialPosts, titles, hashtags, youtubeTimestamps, highlightMoments },
  createdAt: 1733420000000,
  updatedAt: 1733420500000,
  completedAt: 1733420600000
}

Indexes: by_user, by_status, by_user_and_status, by_created_at.


๐Ÿงญ Project Status Model

Status is used to drive UI state and processing feedback.

๐Ÿ“ Primary status

  • uploaded โ†’ project created, waiting to process.
  • processing โ†’ Inngest workflow running.
  • completed โ†’ all scheduled jobs finished.
  • failed โ†’ workflow or a critical step failed.
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#3B82F6','primaryTextColor':'#FFFFFF','primaryBorderColor':'#F97316','lineColor':'#3B82F6','secondaryColor':'#F97316','tertiaryColor':'#FFF7ED'}}}%%
stateDiagram-v2
  [*] --> uploaded
  uploaded --> processing
  processing --> completed
  processing --> failed
  failed --> [*]
  completed --> [*]
Loading

๐Ÿงฉ Job status (granular)

  • transcription: pending โ†’ running โ†’ completed/failed.
  • contentGeneration: pending โ†’ running โ†’ completed/failed.

๐Ÿงฏ Per-job errors

  • Individual AI jobs record errors inside jobErrors.
  • The UI surfaces per-tab retries for only the failed output.

๐Ÿ—ƒ๏ธ Storage Layout

Storage is split between Blob (files) and Convex (structured results).

Vercel Blob:

  • Input audio files stored via direct client upload.
  • Public URLs with randomized suffixes.

Convex:

  • Stores metadata + AI outputs.
  • Stores transcript structure (segments, chapters, speakers).

Example key structure (conceptual):

  • blob://uploads/{userId}/{random}.mp3
  • blob://uploads/{userId}/{random}.wav

๐Ÿ›ก๏ธ Security Model

Podcastogist is designed for practical, application-level security.

Access control:

  • Clerk enforces authentication at the app boundary.
  • Convex queries/mutations are user-scoped.

Blob access model:

  • Vercel Blob client uploads require access: "public".
  • URLs are unlisted and stored privately in Convex.
  • Projects are only accessible to the owning user.

Practical outcome:

  • Public blob URLs exist, but access is effectively private by design.
  • This is appropriate for podcast media workflows.

๐Ÿ“ˆ Observability

High-signal visibility across every stage of the pipeline.

  • Inngest: step runs, retries, and execution history.
  • Convex: mutation/query logs and realtime subscriptions.
  • Vercel: request/runtime logs + Blob activity.
  • Providers: AssemblyAI + OpenAI dashboards for usage and errors.

๐Ÿง  AI Generation Engine

OpenAI is used for recaps, posts, titles, and hashtags.

Key characteristics:

  • Model: gpt-5-mini (fast, cost-effective).
  • Structured outputs enforced via Zod schemas.
  • Inngest step.ai.wrap() ensures observability and retries.

Why structured outputs matter:

  • Enforces predictable JSON shape.
  • Prevents UI breakage from malformed model output.
  • Keeps type safety consistent across the stack.

๐ŸŽง AssemblyAI Transcription

AssemblyAI is used for high-quality transcription and audio intelligence.

Enabled features:

  • Speaker diarization (always captured).
  • Auto chapters (topic detection with summaries).
  • Word-level timestamps.
  • Formatted text (punctuation + capitalization).

Design rationale:

  • Strong diarization performance.
  • Async transcription API fits durable workflows.
  • Chapters provide reliable timing for highlights and YouTube timestamps.

๐Ÿงฌ Prompt & Schema Discipline

Prompting is structured and reproducible across all AI steps.

Prompts include:

  • Partial transcript text for context.
  • AssemblyAI chapters for structure.
  • Platform-specific rules and constraints.

Schemas enforce:

  • Output shape for recaps, titles, posts, hashtags.
  • Minimum/maximum array lengths.
  • Character limits (Twitter/X).

๐Ÿ“ก Real-time Updates

Convex makes the UI reactive without manual polling.

What updates in real-time:

  • Project list as uploads complete.
  • Project detail tabs as AI outputs arrive.
  • Processing status and progress states.

Why this matters:

  • UI feels โ€œliveโ€ even for long processing steps.
  • Users always see accurate status from the database.

โ™ป๏ธ Retry & Regeneration

Podcastogist supports selective regeneration.

Retry flow:

  • Failed tabs can be retried individually.
  • Inngest function reuses stored transcript data.
  • Job errors clear automatically after success.

Upgrade flow:

  • Upgrading plans unlocks new features.
  • A single action generates all missing outputs.

Performance choices:

  • Parallel AI fan-out (Promise.allSettled).
  • Async transcription via webhooks.
  • No polling thanks to Convex subscriptions.
  • Client-side direct Blob uploads for large files.

๐Ÿงฏ Failure Modes & Recovery

This system is built to behave predictably when things go wrong.

Area Failure User impact Recovery behavior
Upload file too large blocked before processing clear error + upgrade CTA
Upload unsupported type blocked supported formats listed
Upload blob upload fails project not created retry upload
Transcription AssemblyAI error no outputs project marked failed
Webhook late/duplicate webhook delayed updates idempotent handling
Generation OpenAI error missing outputs per-job retry
Gating locked feature access upgrade prompt no compute runs
Limits duration exceeds plan blocked early limit message shown
Realtime subscription drop stale UI auto reconnect/refresh
Deletion project removed disappears from list Free counts include deleted

โš–๏ธ Tradeoffs

Deliberate choices to balance reliability, speed, and scope.

Chosen intentionally:

  • Managed services for faster iteration and fewer ops burdens.
  • Durable workflows instead of long-running API requests.
  • Realtime subscriptions instead of client polling.
  • Progressive enrichment instead of โ€œall-or-nothingโ€ output.
  • Direct-to-Blob uploads for large files.

Not chosen (for this scope):

  • Self-hosted workers and queues.
  • One mega prompt for all outputs.
  • Storing raw audio in the database.
  • Hard-blocking UI until all outputs finish.
  • Private blob access with signed URLs (future enhancement).

๐ŸŽจ Design System & UI

The UI is built to feel premium and confident.

Visual system:

  • Gradient sunrise theme (blue โ†’ orange).
  • Glassmorphism cards with soft elevation.
  • Clear hierarchy with bold typography.

Interaction design:

  • Copy-to-clipboard actions for outputs.
  • Progress indicators tied to real-time data.
  • Upgrade prompts placed at the moment of need.

๐Ÿงญ UX Details

Micro-interactions and layout decisions that improve usability.

Upload UX:

  • Immediate file validation feedback.
  • Duration display before upload starts.
  • Clear upload status states.

Dashboard UX:

  • Tabs for outputs to prevent scrolling fatigue.
  • Distinct states for processing vs completed.
  • Empty state guidance for first-time users.
  • Processing shown as a pipeline, not just a spinner.

Accessibility: ARIA-labeled theme toggle, focusable actions, and contrast-safe colors.


๐Ÿงฐ Tech Stack

A modern, production-grade stack optimized for SaaS workflows.

Frontend:

  • Next.js 16 (App Router).
  • React 19 + TypeScript.
  • Tailwind CSS v4 + shadcn/ui + Radix UI.
  • Lucide icons + react-social-icons.
  • Sonner for toast feedback.

Backend & Infrastructure:

  • Clerk (auth + billing + feature gating).
  • Convex (realtime DB + reactive queries).
  • Inngest (durable background jobs).
  • AssemblyAI (transcription + diarization).
  • OpenAI GPT-5-mini (content generation).
  • Vercel Blob (large file storage + direct uploads).

Quality & DX:

  • Zod for schema validation.
  • Biome for linting/formatting.
  • CI quality gate on every push to main (Biome, typecheck, build).
  • Vitest for unit + integration tests; Playwright for E2E.
  • Typed AI outputs via Structured Outputs.
  • Dependabot for automated dependency updates.
  • CodeQL for security scanning.

๐Ÿ—บ๏ธ Repo Map

Key directories and their roles.

  • app/ โ†’ Next.js App Router pages + API routes.
  • components/ โ†’ UI components, tabs, upload flow, layout.
  • actions/ โ†’ Server actions for uploads, projects, retries.
  • convex/ โ†’ Schema + queries + mutations.
  • inngest/ โ†’ Workflow functions and AI steps.
  • lib/ โ†’ Shared utilities, types, constants, clients.
  • schemas/ โ†’ Zod schemas for AI outputs.
  • tests/ โ†’ Test suites and fixtures.
  • .github/ โ†’ GitHub workflows and repo assets.

๐Ÿงช Engineering Notes

These are the decisions that made the product reliable.

๐Ÿงฑ Upload Flow (Large Files)

  • Direct Blob upload via @vercel/blob/client.
  • Server action pre-checks prevent wasted uploads.
  • API route enforces plan-based size limits.

๐Ÿ”„ Durable Orchestration

  • Inngest functions run steps with retries and observability.
  • Transcription waits on webhook events (not HTTP timeouts).
  • Parallel steps run independently to avoid cascading failures.

๐Ÿ“š Data & State

  • Convex schema supports progressive updates.
  • jobStatus enables granular UI progress.
  • jobErrors supports per-feature retry.

๐Ÿ”‘ Plan Enforcement

  • Clerk billing features map directly to app capabilities.
  • Free tier project count includes deleted projects.
  • Plus tier counts only active projects (fair usage).

๐Ÿ›ก๏ธ Security & Maintenance

  • Automated dependency updates (Dependabot)
  • Static analysis / code scanning (CodeQL)

This repo is maintained with automated update and scanning workflows to keep dependencies current and reduce risk.
Dependabot PRs are grouped to avoid noise while still surfacing meaningful updates on a weekly cadence.
CodeQL runs on pushes, PRs, and a scheduled job to catch common security issues early.
Together, these checks keep the Security tab active and provide a visible maintenance signal in GitHub PRs.


๐Ÿ”ฌ Tests

This suite is designed to prove real SaaS workflows, not toy tests.
It validates the same contracts used in production while keeping CI deterministic and fast.

โœ… Coverage Matrix

Layer Framework What it validates Examples
Unit Vitest Gating logic and limits Plan limits, feature gating, plan-to-feature mapping
Integration Vitest Contract-level correctness Zod output schemas, Inngest event shapes, webhook mapping, golden AI outputs
E2E Playwright Real user workflows Auth gate, create project, upload โ†’ processing โ†’ results, plan CTA, mobile nav, retry

Folder layout: tests/unit, tests/integration, tests/e2e

๐Ÿงช Mock Providers Ecosystem (Deterministic by Design)

To make end-to-end testing real yet repeatable, external providers are mocked at the boundary:

  • MOCK_AI=1 returns structured AI fixture outputs that match production Zod schemas.
  • MOCK_TRANSCRIPTION=1 returns transcript + chapter fixtures (no AssemblyAI calls).
  • MOCK_PIPELINE=1 runs the pipeline synchronously with mocked providers.
  • MOCK_AUTH=1 + MOCK_PLAN=free|plus|max simulate auth + plan gating.

Convex is not mocked: E2E runs against a real local Convex instance, so mutations, subscriptions, and status transitions are exercised exactly as in production.

๐Ÿ” CI Proof

All three suites run in GitHub Actions on every push to main with named checks:

  • โœ… CI Tests (Unit)
  • โœ… CI Tests (Integration)
  • โœ… CI Tests (E2E)

๐Ÿ” Test Flow Snapshot

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#3B82F6','primaryTextColor':'#FFFFFF','primaryBorderColor':'#F97316','lineColor':'#3B82F6','secondaryColor':'#F97316','tertiaryColor':'#FFF7ED'}}}%%
flowchart LR
  A[Vitest + Playwright] --> B[Mock Flags]
  B --> C[Mock Providers<br/>AI + Transcription]
  A --> D[Next.js App]
  D --> E[Convex Local DB]
  E --> F[Realtime UI Updates]
  C --> D
Loading

Why this matters: It proves the full pipeline (upload โ†’ processing โ†’ results) without paid APIs, and keeps CI both reliable and high-signal.


๐Ÿง— Build Challenges

What required real engineering problem-solving.

1) Long-running transcription on serverless

  • Solved using AssemblyAI webhooks + Inngest durable waits.

2) Large file uploads

  • Solved with direct-to-Blob uploads and server-side size constraints.

3) Plan gating without security holes

  • Solved with multi-layer enforcement in UI, server actions, and routes.

4) Partial failure tolerance

  • Solved with Promise.allSettled and per-job error tracking.

5) Real-time UX

  • Solved with Convex subscriptions and atomic mutations.

โณ Build Timeline

The project was built in an intense sprint schedule.

Timeline (2025):

  • Dec 6 โ†’ Dec 25: Architecture + core build.
  • Dec 25 โ†’ Dec 30: Packaging, video walkthrough, README prep.
  • Total effort: ~200 hours.

๐Ÿ”ฎ Roadmap

Future enhancements that would extend the product.

Product expansions:

  • Batch processing for multiple episodes.
  • Multi-language transcription and translation (currently only English is supported)
  • Custom brand voice profiles for AI outputs.
  • Export packs (PDF / Notion / Google Docs).

Distribution enhancements:

  • Social scheduling integrations (Buffer, Hootsuite).
  • Analytics dashboard for content performance.
  • A/B testing for titles and hooks.

Workflow upgrades:

  • Captions/SRT export.
  • Team workspaces and roles.
  • Webhook notifications when processing completes.

๐Ÿ“š Glossary

A quick reference for reviewers and recruiters.

  • Inngest โ†’ Durable job orchestration layer.
  • Convex โ†’ Real-time database with reactive queries.
  • Clerk โ†’ Authentication + billing + plan gating.
  • AssemblyAI โ†’ Speech-to-text + audio intelligence.
  • OpenAI GPT-5-mini โ†’ LLM used for content generation.
  • Vercel Blob โ†’ Object storage for uploaded audio files.
  • Plan gating โ†’ Feature access based on subscription tier.
  • Diarization โ†’ Identifying who spoke in a transcript.
  • Auto chapters โ†’ AssemblyAI topic segmentation.
  • Structured outputs โ†’ LLM responses constrained by Zod schemas.

๐Ÿงพ Demo Disclaimer

Not a real commercial SaaS. This is a demonstration project.
Podcastogist is a fully working platform built for podcast post-production jobs & content kit generation.
Billing runs in test mode (Clerk/Stripe), so no real charges are processed.


๐Ÿ“ฌ Contact

About

AI-Powered Podcast Post-Production SaaS Platform ๐ŸŽค

Topics

Resources

Stars

Watchers

Forks

Contributors 2

  •  
  •