Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 2 additions & 59 deletions GEMINI.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,65 +14,8 @@ When executing an implementation plan, after a phase is completed, ask the user

If asked to use icons or pictures in your app (for example hero images or background images) generate them with the Nano Banana extension

## SQLAlchemy Database interactions coding guidelines

When using SQLAlchemy with Python and Flask, all database models and queries must adhere to the modern **SQLAlchemy 2.0** style. The legacy query API from `Flask-SQLAlchemy` (`Model.query`) is forbidden.

### 1. Model Definition

Models must be defined using `sqlalchemy.orm.Mapped` and `sqlalchemy.orm.mapped_column` with type annotations.

**Bad (Legacy Style):**
```python
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(40), unique=True, nullable=False)
```

**Good (Modern SQLAlchemy 2.0 Style):**
```python
import sqlalchemy as sa
import sqlalchemy.orm as so

class User(db.Model):
id: so.Mapped[int] = so.mapped_column(primary_key=True)
email: so.Mapped[str] = so.mapped_column(sa.String(40), unique=True)
```

### 2. Database Queries

All queries must be constructed using the `sqlalchemy.select()` function. Do not use the `Model.query` object.

**Bad (Legacy `Model.query`):**
```python
# Get by primary key
user = User.query.get(1)

# Filter and get first
user = User.query.filter_by(email="test@example.com").first()

# Get all
users = User.query.all()
```

**Good (Modern `select()` construct):**
```python
import sqlalchemy as sa

# Get by primary key
user = db.session.get(User, 1)

# Filter and get first
stmt = sa.select(User).where(User.email == "test@example.com")
user = db.session.scalars(stmt).first()

# Get all
stmt = sa.select(User)
users = db.session.scalars(stmt).all()
```




For guide on interacting with Gemini API follow the instructions in:
@gemini-styleguide.md


58 changes: 58 additions & 0 deletions IMPLEMENTATION_PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# 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: Project Initialization & Configuration
- [x] Initialize a new Next.js project with Tailwind CSS (`npx create-next-app@latest podcast-generator --typescript --tailwind --eslint`).
- [x] Install project dependencies: `npm install google-genai rss-parser uuid`.
- [x] Create a `.env.local` file for environment variables (`GOOGLE_API_KEY`, `PROJECT_ID`).
- [x] Generate a Hero Image ("Robot Agent in TV Studio") using the Nano Banana extension and save it to `public/hero-image.png`.
- [x] Verify the application runs locally (`npm run dev`).

## Phase 2: Data Layer & API - Feeds
- [x] Create a utility module `lib/store.ts` to handle reading/writing to a local JSON file (`data/db.json`) for data persistence. Define the `Feed` and `Podcast` interfaces here.
- [x] Implement the API route `GET /api/feeds` to retrieve the list of stored feeds.
- [x] Implement the API route `POST /api/feeds` to add a new feed. This must use `rss-parser` to validate the URL and fetch the feed title before saving.
- [x] Implement the API route `DELETE /api/feeds` to remove a feed by ID.
- [x] Verify API endpoints using `curl` or a tool like Postman.

## Phase 3: Frontend - Layout & Feed Manager
- [x] Update `app/layout.tsx` and `app/page.tsx` to implement the basic two-column layout. Include the Hero Image at the top.
- [x] Create a `components/FeedManager.tsx` component. This should include:
- An input form to add a new RSS feed URL.
- A list displaying currently added feeds with a "Remove" button.
- [x] Connect `FeedManager` to the `/api/feeds` endpoints to fetch, add, and delete feeds dynamically.
- [x] Verify the Feed Manager UI works correctly (adding valid/invalid URLs, removing feeds).

## Phase 4: API - Podcast Generation Logic
- [x] Create the `POST /api/podcasts/generate` endpoint. This should:
- Accept a request to start generation.
- Create a new "PENDING" podcast record in the DB.
- Trigger the generation process asynchronously (or simulate async if Vercel limits apply, but for local use, normal async is fine).
- Return the `podcastId`.
- [x] Implement the "Fetch & Filter" logic: Fetch articles from all stored feeds and filter for those published in the last 24 hours.
- [x] Implement the "Summarization" service: Use `google-genai` (`gemini-2.5-flash`) to summarize each article into a short script segment.
- [x] Implement the "Script Compilation" logic: specific Intro + Summaries + Outro.
- [x] Implement the "Audio Synthesis" service: Use `google-genai` (or specific TTS endpoint if `google-genai` audio generation is distinct) to convert the full script to speech. Save the resulting audio buffer to `public/podcasts/[id].mp3`.
- [x] Update the podcast record in `data/db.json` to "COMPLETED" with the path and duration.
- [x] Implement `GET /api/podcasts` to list all generated podcasts.
- [x] Implement `GET /api/podcasts/[id]` to return the status of a specific generation job.

## Phase 5: Frontend - Podcast Player & History
- [x] Create a `components/PodcastGenerator.tsx` component with a "Generate Podcast" button.
- It should call `/api/podcasts/generate`.
- It should display a loading state (spinner) while polling `/api/podcasts/[id]` until status is "COMPLETED".
- [x] Create a `components/PodcastList.tsx` component to display the history of generated podcasts.
- [x] Create/Integrate an `AudioPlayer` component (standard HTML5 `<audio>` tag styled with Tailwind) to play the generated files.
- [x] Integrate these components into the main page layout.
- [x] Verify the full flow: Add Feed -> Generate -> Wait -> Play Audio.

## Phase 6: Completion & Version Control
- [x] Verify application functionality.
- [x] Create a `README.md` file explaining the application functions, how to interact with them, the architecture, file breakdown and how to run and test it locally.
- [x] Add all changes to the repository (`git add .`).
- [x] Commit the changes (`git commit -m "Complete implementation of Podcast Generator"`).
- [x] Push the feature branch to the remote repository, creating a branch with the same name in the remote repository, using the Gemini CLI github MCP server.
- [x] Open a pull request for the feature branch using the Gemini CLI github MCP server, leave it open for review, don't merge it.
94 changes: 0 additions & 94 deletions README.md

This file was deleted.

Binary file added Screenshot 2025-12-14 at 13.30.39.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
107 changes: 107 additions & 0 deletions gemini-styleguide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# GoogleCloudPlatform/generative-ai Style Guide

The current year is 2025.

## Markdown Style (For `.md` files and `.ipynb` Markdown Cells)

- Use single backticks ( ` ` ) to format inline code elements, such as variable names, function names, enum names, and brief code snippets.
- Add documentation links to the appropriate Vertex AI pages when describing product features. e.g. https://cloud.google.com/vertex-ai/generative-ai/docs
- Do not reference documentation from the Gemini Developer API, e.g. https://ai.google.dev/ unless there is not a suitable page in the Vertex AI documentation.

---

The Author block in Notebooks and Markdown should be in a format like this:

For one author:

| Author |
| --- |
| [Firstname Lastname](https://github.com/username) |

For multiple authors

| Authors |
| --- |
| [Firstname Lastname](https://github.com/username) |
| [Firstname Lastname](https://github.com/username) |

## Code Requirements

- Don't include hard-coded Google Cloud project IDs, always use a placeholder like `[your-project-id]`

**Correct**

```py
PROJECT_ID = "[your-project-id]"
```

***Incorrect**

```py
PROJECT_ID = "actual-projectid-1234"
```

## Golden Rule: Use the Correct and Current SDK

Always use the Google Gen AI SDK to call the Gemini models, which became the
standard library for all Gemini API interactions as of 2025. Do not use legacy
libraries and SDKs. 3rd party integrations like LangGraph, LlamaIndex, LiteLLM are okay.

- **Library Name:** Google Gen AI SDK
- **Python Package:** `google-genai`
- **Legacy Library**: (`google-generativeai`) is deprecated.

**Installation:**

- **Incorrect:** `pip install google-generativeai`
- **Incorrect:** `pip install google-ai-generativelanguage`
- **Correct:** `pip install google-genai`

**APIs and Usage:**

- **Incorrect:** `import google.generativeai as genai`-> **Correct:** `from
google import genai`
- **Incorrect:** `from google.ai import generativelanguage_v1` ->
**Correct:** `from google import genai`
- **Incorrect:** `from google.generativeai` -> **Correct:** `from google
import genai`
- **Incorrect:** `from google.generativeai import types` -> **Correct:** `from
google.genai import types`
- **Incorrect:** `import google.generativeai as genai` -> **Correct:** `from
google import genai`
- **Incorrect:** `genai.configure(api_key=...)` -> **Correct:** `client =
genai.Client(api_key="...")`
- **Incorrect:** `model = genai.GenerativeModel(...)`
- **Incorrect:** `model.generate_content(...)` -> **Correct:**
`client.models.generate_content(...)`
- **Incorrect:** `response = model.generate_content(..., stream=True)` ->
**Correct:** `client.models.generate_content_stream(...)`
- **Incorrect:** `genai.GenerationConfig(...)` -> **Correct:**
`types.GenerateContentConfig(...)`
- **Incorrect:** `safety_settings={...}` -> **Correct:** Use `safety_settings`
inside a `GenerateContentConfig` object.
- **Incorrect:** `from google.api_core.exceptions import GoogleAPIError` ->
**Correct:** `from google.genai.errors import APIError`
- **Incorrect:** `types.ResponseModality.TEXT`

## Models

- By default, use the following models when using `google-genai`:
- **General Text & Multimodal Tasks:** `gemini-2.5-flash`
- **Coding and Complex Reasoning Tasks:** `gemini-2.5-pro`
- **Latency-sensitive operations:** `gemini-2.5-flash-lite`
- **Image Generation Tasks:** `imagen-4.0-fast-generate-001`,
`imagen-4.0-generate-001` or `imagen-4.0-ultra-generate-001`
- **Image Editing Tasks:** `gemini-2.5-flash-image-preview`
- **Video Generation Tasks:** `veo-3.0-fast-generate-preview` or
`veo-3.0-generate-preview`.

- It is also acceptable to use following models if explicitly requested by the
user:
- **Gemini 2.0 Series**: `gemini-2.0-flash-lite`, `gemini-2.0-flash`, `gemini-2.0-pro`

- Do not use the following deprecated models (or their variants like
`gemini-1.5-flash-latest`):
- **Prohibited:** `gemini-1.5-flash`
- **Prohibited:** `gemini-1.5-pro`
- **Prohibited:** `gemini-pro`
41 changes: 41 additions & 0 deletions podcast-generator/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# 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
Loading