From 1c96e318f544e7eb2ea2eade494f7e7b2d4bdb45 Mon Sep 17 00:00:00 2001 From: ggalloro Date: Sun, 14 Dec 2025 14:10:22 +0100 Subject: [PATCH 1/3] Complete implementation of Podcast Generator --- .gitignore | 44 + IMPLEMENTATION_PLAN.md | 50 + README.md | 139 +- dev.db | Bin 0 -> 28672 bytes eslint.config.mjs | 18 + js_codegen_instructions.md | 762 ++ next.config.ts | 7 + package-lock.json | 9174 +++++++++++++++++ package.json | 38 + postcss.config.mjs | 7 + prisma.config.ts | 14 + .../20251214125935_init/migration.sql | 20 + prisma/migrations/migration_lock.toml | 3 + prisma/schema.prisma | 26 + public/file.svg | 1 + public/globe.svg | 1 + public/hero.png | Bin 0 -> 860633 bytes public/next.svg | 1 + public/vercel.svg | 1 + public/window.svg | 1 + py_codegen_instructions.md | 624 ++ src/app/api/feeds/[id]/route.ts | 26 + src/app/api/feeds/route.ts | 51 + src/app/api/podcasts/generate/route.ts | 61 + src/app/api/podcasts/route.ts | 15 + src/app/favicon.ico | Bin 0 -> 25931 bytes src/app/globals.css | 26 + src/app/layout.tsx | 34 + src/app/page.tsx | 86 + src/components/FeedManager.tsx | 109 + src/components/PodcastPlayer.tsx | 83 + src/lib/db.ts | 27 + src/lib/services/audio.ts | 34 + src/lib/services/gemini.ts | 41 + src/lib/services/rss.ts | 40 + src/lib/services/tts.ts | 40 + tsconfig.json | 34 + 37 files changed, 11549 insertions(+), 89 deletions(-) create mode 100644 .gitignore create mode 100644 IMPLEMENTATION_PLAN.md create mode 100644 dev.db create mode 100644 eslint.config.mjs create mode 100644 js_codegen_instructions.md create mode 100644 next.config.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 postcss.config.mjs create mode 100644 prisma.config.ts create mode 100644 prisma/migrations/20251214125935_init/migration.sql create mode 100644 prisma/migrations/migration_lock.toml create mode 100644 prisma/schema.prisma create mode 100644 public/file.svg create mode 100644 public/globe.svg create mode 100644 public/hero.png create mode 100644 public/next.svg create mode 100644 public/vercel.svg create mode 100644 public/window.svg create mode 100644 py_codegen_instructions.md create mode 100644 src/app/api/feeds/[id]/route.ts create mode 100644 src/app/api/feeds/route.ts create mode 100644 src/app/api/podcasts/generate/route.ts create mode 100644 src/app/api/podcasts/route.ts create mode 100644 src/app/favicon.ico create mode 100644 src/app/globals.css create mode 100644 src/app/layout.tsx create mode 100644 src/app/page.tsx create mode 100644 src/components/FeedManager.tsx create mode 100644 src/components/PodcastPlayer.tsx create mode 100644 src/lib/db.ts create mode 100644 src/lib/services/audio.ts create mode 100644 src/lib/services/gemini.ts create mode 100644 src/lib/services/rss.ts create mode 100644 src/lib/services/tts.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c1dba4f5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,44 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts +node_modules + +/src/generated/prisma diff --git a/IMPLEMENTATION_PLAN.md b/IMPLEMENTATION_PLAN.md new file mode 100644 index 00000000..3b1b3455 --- /dev/null +++ b/IMPLEMENTATION_PLAN.md @@ -0,0 +1,50 @@ +# Implementation Plan - Podcast Generator + +## Phase 0: Git Setup +- [x] Check if the current directory is an initialized git repository. +- [x] If it is, create and checkout a new feature branch named `podcast-generator`. + +## Phase 1: Environment & Project Setup +- [x] Initialize a new Next.js project with TypeScript, Tailwind CSS, and App Router. +- [x] Install backend dependencies: `prisma`, `@prisma/client` (or `better-sqlite3`), `rss-parser`, `fluent-ffmpeg`, `@google/generative-ai` (Gemini SDK), `@google-cloud/text-to-speech`. +- [x] Install frontend dependencies: `lucide-react` (for icons), `axios` or use `fetch`. +- [x] Configure Environment Variables (`.env.local`): `GOOGLE_AI_API_KEY`, `GOOGLE_APPLICATION_CREDENTIALS`, `DATABASE_URL`. +- [x] Verify `ffmpeg` installation on the local machine. + +## Phase 2: Database & Data Access +- [x] Initialize Prisma with SQLite provider (`npx prisma init --datasource-provider sqlite`). +- [x] Define `Feed` model in `prisma/schema.prisma` (id, url, title, createdAt). +- [x] Define `Podcast` model in `prisma/schema.prisma` (id, title, filePath, duration, createdAt, summary). +- [x] Run migration to create the SQLite database (`npx prisma migrate dev --name init`). +- [x] Create a `db.ts` lib file to export the singleton Prisma client instance. + +## Phase 3: Backend Services (Core Logic) +- [x] **RSS Service**: Create `lib/services/rss.ts`. Implement `fetchLatestArticles(feeds)` using `rss-parser`. Filter articles from the last 24 hours. +- [x] **AI Service (Summarization)**: Create `lib/services/gemini.ts`. Implement `generatePodcastScript(articles)` using the Gemini API. Construct the prompt as specified in the Tech Spec. +- [x] **TTS Service (Synthesis)**: Create `lib/services/tts.ts`. Implement `synthesizeSpeech(text)` using Google Cloud TTS (Chirp model). Handle text chunking if necessary. +- [x] **Audio Service (Processing)**: Create `lib/services/audio.ts`. Implement `concatAudioSegments(segments, outputPath)` using `fluent-ffmpeg` to merge Intro + Body + Outro. + +## Phase 4: API Routes +- [x] **Feed Endpoints**: Create `app/api/feeds/route.ts` and `app/api/feeds/[id]/route.ts`. Implement GET (list), POST (add & validate), DELETE (remove). +- [x] **Podcast Endpoints**: Create `app/api/podcasts/route.ts`. Implement GET (list history). +- [x] **Generation Endpoint**: Create `app/api/podcasts/generate/route.ts`. Implement POST. This should orchestrate the full pipeline: Fetch RSS -> Summarize -> TTS -> Concat -> Save to DB -> Return Result. + +## Phase 5: Frontend - UI Components +- [x] **Layout & Hero**: Update `app/page.tsx` with a responsive layout. Add the Hero section with the "Robot agent reading news" image (placeholder or generated). +- [x] **Feed Manager Component**: Create `components/FeedManager.tsx`. Implement a form to add URLs and a list to display/delete current feeds. Connect to `/api/feeds`. +- [x] **Podcast History & Player**: Create `components/PodcastPlayer.tsx`. Display a list of generated podcasts. When selected, play the audio file using the standard `