Monetize global trends, automatically.
Real trending videos, worldwide, turned into a multilingual newsletter and viral social posts — with zero humans in the loop.
Every day, on its own, TrendPulse:
- Scrapes real trending videos worldwide via the YouTube Data API v3 — no simulated or invented data.
- Writes a multilingual digest (EN / ES / JA) plus platform-ready social posts, using Claude.
- Emails the full issue to paid subscribers, and publishes free social copy — with subscription billing on Stripe.
No editor reviews an issue before it ships. The live site shows the free web feed; Pro subscribers receive the full issue by email.
A fully autonomous "Micro-SaaS (video/trend digest) × paid newsletter" system. No human touches an issue between trend collection and delivery. Every integration below is a real API call — nothing is mocked except the one place explicitly noted (the LP's interactive demo).
trendpulse/
├── backend/ FastAPI app, agents, workflow, DB
│ ├── config.py env-var settings loader
│ ├── db.py SQLite persistence (subscribers, issues)
│ ├── agents/
│ │ ├── trend_scraper.py TrendScraperAgent — real YouTube Data API v3
│ │ └── content_generator.py ContentGeneratorAgent — real Anthropic API
│ ├── email_service.py EmailService — real Brevo REST API (HTTPS)
│ ├── stripe_webhook.py Stripe webhook handler (signature-verified)
│ ├── workflow/
│ │ └── automation.py AutomationWorkflow — orchestrates the full cycle
│ ├── main.py FastAPI routes
│ ├── requirements.txt
│ └── .env.example
└── frontend/ React + Vite + Tailwind landing page
├── src/components/ Hero, Features, InteractivePreview, Pricing, Footer
└── ...
The spec asked for trend collection to "simulate Perplexity/web search." I
deliberately built against the real YouTube Data API v3 (chart=mostPopular)
instead of having an LLM invent plausible-sounding trending videos — a paid
newsletter that quietly fabricates its source data is selling something
false to paying subscribers. Likewise, email delivery goes out over real
Brevo's HTTP API rather than simulating a send. The only intentional mock in
the whole system is the LP's "Interactive Preview" widget, which is
client-side only and does not call the live LLM — a public, unauthenticated
form wired to a real Claude call would let anyone on the internet spend your
API budget for free.
cd backend
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # then fill in the real values below
uvicorn main:app --reload --port 8000| Variable | Where to get it |
|---|---|
ANTHROPIC_API_KEY |
console.anthropic.com — API Keys |
YOUTUBE_API_KEY |
console.cloud.google.com/apis/credentials — create a project, enable "YouTube Data API v3", create an API key. Free quota (10,000 units/day) |
STRIPE_SECRET_KEY |
Stripe Dashboard → Developers → API keys |
STRIPE_WEBHOOK_SECRET |
Stripe Dashboard → Developers → Webhooks → add endpoint POST /webhooks/stripe, listen for checkout.session.completed, customer.subscription.updated, customer.subscription.deleted |
STRIPE_PRICE_ID |
The Price object backing your $29/mo Payment Link |
BREVO_API_KEY / BREVO_SENDER_EMAIL |
app.brevo.com — verify a single sender email (no domain needed), then Settings → SMTP & API → API Keys. Free tier: 300 emails/day. |
LP_BASE_URL |
Your deployed frontend's public URL |
INTERNAL_TRIGGER_TOKEN |
Any long random string — protects /internal/* routes |
None of these accounts can be created on your behalf — API keys and domain verification require you to own the account.
There is no built-in scheduler (keeps the web process lightweight). Point any external scheduler (host cron, your platform's scheduled-job feature, or a one-line GitHub Actions workflow) at:
curl -X POST https://your-api.example.com/internal/run-cycle \
-H "X-Internal-Token: $INTERNAL_TRIGGER_TOKEN"once a day. This runs TrendScraperAgent → ContentGeneratorAgent → db → EmailService end to end and emails every active pro subscriber.
cd frontend
npm install
cp .env.example .env # if you create one — see variables below
npm run dev # local dev, http://localhost:5173
npm run build # production build → dist/| Variable | Default | Purpose |
|---|---|---|
VITE_API_BASE_URL |
http://localhost:8000 |
Backend URL the signup form posts to |
VITE_STRIPE_PAYMENT_LINK |
placeholder | Real Stripe Payment Link / Checkout URL for the $29/mo "Upgrade to Pro" button |
Set these in a frontend/.env file or your hosting platform's environment
config before deploying.
- Creating the Google Cloud project + enabling YouTube Data API v3
- Creating an Anthropic account and API key
- Creating a Stripe account, Product/Price, Payment Link, and registering the webhook endpoint
- Creating a Brevo account and verifying a single sender email address
- Deploying both services somewhere (backend: Railway/Fly.io/Render/a VPS;
frontend: Vercel/Netlify/Cloudflare Pages) and pointing
LP_BASE_URL/VITE_API_BASE_URLat the real deployed URLs - Swapping SQLite for Postgres if you expect meaningful concurrent write
volume (the
db.pyquery layer is written so this is a connection-string change, not a rewrite)
- All backend
.pyfiles:py_compileclean, and a fullimportof every module (including the FastAPIappobject) succeeds with all 9 routes registered, using dependencies actually installed fromrequirements.txt. - Frontend:
npm install+npm run buildsucceed with no errors; verified live in a dev-server preview — all five sections render, the signup form, language switcher, and the Interactive Preview's mock 3-step scrape→generate→ready flow all work correctly (including the JA/ES/EN content swap and LP-link append).