Skip to content

Teslin92/Battery-Scout

Repository files navigation

Battery Scout

Automated battery industry newsletter service β€” curates news from global sources, generates AI summaries, and delivers personalized daily/weekly emails.

Python FastAPI React TypeScript

πŸ“‹ Overview

Battery Scout is a full-stack newsletter platform that:

  • Scrapes battery industry news from Google News across 8+ languages
  • Summarizes articles using Google Gemini AI
  • Categorizes content into 6 industry-relevant topics
  • Personalizes newsletters based on subscriber preferences
  • Delivers daily/weekly emails via automated GitHub Actions

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  React Frontend β”‚  ← User signup/unsubscribe
β”‚   (Vite + TS)   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚ REST API
         ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  FastAPI Backendβ”‚  ← Subscription management
β”‚   (Python 3.11) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚    Supabase     β”‚  ← Database (subscribers, articles)
β”‚   (PostgreSQL)  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

GitHub Actions (daily cron)
  ↓
  1. scrape_news.py   β†’ Fetch & summarize articles
  2. send_email.py    β†’ Send personalized emails

πŸš€ Quick Start

Prerequisites

  • Python 3.11+
  • Node.js 18+
  • Supabase account (for database)
  • Google Gemini API key (for AI summaries)
  • Gmail account (for sending emails)

Backend Setup

cd backend

# Install dependencies
pip install -r requirements.txt

# Set environment variables (create .env file)
export SUPABASE_URL=your_supabase_url
export SUPABASE_SERVICE_KEY=your_service_key
export GEMINI_API_KEY=your_gemini_key
export GMAIL_USER=your_email@gmail.com
export GMAIL_APP_PASSWORD=your_app_password
export UNSUBSCRIBE_SALT=random_secret_string

# Run the API server
python main.py
# Server runs on http://localhost:8000

Frontend Setup

cd frontend

# Install dependencies
npm install

# Set environment variables (create .env file)
echo "VITE_API_URL=http://localhost:8000" > .env

# Start dev server
npm run dev
# App runs on http://localhost:8080

πŸ“‚ Project Structure

Battery Scout/
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ main.py              # FastAPI server & API endpoints
β”‚   β”œβ”€β”€ scrape_news.py       # News scraping & AI summarization
β”‚   β”œβ”€β”€ send_email.py        # Email delivery service
β”‚   β”œβ”€β”€ supabase_client.py   # Database operations
β”‚   β”œβ”€β”€ utils.py             # Validation & helpers
β”‚   β”œβ”€β”€ email_template.py    # HTML email templates
β”‚   └── requirements.txt
β”‚
β”œβ”€β”€ frontend/
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ components/      # React components
β”‚   β”‚   β”œβ”€β”€ pages/           # Route pages
β”‚   β”‚   β”œβ”€β”€ lib/
β”‚   β”‚   β”‚   └── api.ts       # Backend API client
β”‚   β”‚   └── integrations/    # Supabase client (legacy)
β”‚   β”œβ”€β”€ package.json
β”‚   └── vite.config.ts
β”‚
β”œβ”€β”€ .github/
β”‚   └── workflows/
β”‚       └── daily_email.yml  # Automated daily newsletter
β”‚
└── README.md

πŸ”§ Configuration

Backend Environment Variables

Variable Description Required
SUPABASE_URL Your Supabase project URL βœ…
SUPABASE_SERVICE_KEY Supabase service role key βœ…
GEMINI_API_KEY Google Gemini API key βœ…
GMAIL_USER Gmail address for sending βœ…
GMAIL_APP_PASSWORD Gmail app password βœ…
UNSUBSCRIBE_SALT Secret for token generation βœ…
FRONTEND_URL Production frontend URL Optional
PORT Server port (default: 8000) Optional

Frontend Environment Variables

Variable Description
VITE_API_URL Backend API URL (e.g., http://localhost:8000)

πŸ“‘ API Endpoints

Public Endpoints

  • GET / β€” Health check
  • GET /api/topics β€” Get available categories
  • GET /api/content β€” Get sample articles
  • GET /api/stats β€” Get subscriber statistics
  • POST /api/signup β€” Subscribe to newsletter
  • POST /api/unsubscribe/verify β€” Verify unsubscribe token
  • POST /api/unsubscribe/confirm β€” Confirm unsubscribe

See full API docs at http://localhost:8000/docs (Swagger UI)

πŸ€– Automation

The newsletter runs automatically via GitHub Actions:

  1. Daily at 14:00 UTC (9am EST / 6am PST)
  2. Scrapes news from past 24 hours
  3. Generates AI summaries
  4. Sends personalized emails

Manual trigger: Go to Actions tab β†’ Daily Newsletter β†’ Run workflow

πŸ“§ Categories

  1. Companies & Deals β€” Partnerships, acquisitions, factory openings
  2. Policy & Regulation β€” Tariffs, subsidies, government regulations
  3. Supply Chain β€” Lithium, cobalt, nickel mining and pricing
  4. Lithium-ion & Solid-state β€” Battery tech breakthroughs
  5. Sodium-ion & Alternatives β€” Next-gen battery chemistries
  6. Recycling & Second-life β€” Circular economy, reuse, recycling

🌍 Regional Coverage

  • North America (US, Canada)
  • Europe (Germany, France, UK, Sweden, etc.)
  • Asia (China, Japan, South Korea, India)
  • Global (all regions)

News is scraped in 8 languages: English, Chinese, German, Japanese, Korean, Hungarian, Swedish, French, Spanish

🚒 Deployment

Backend (Railway/Render/Fly.io)

# Set all environment variables in your platform
# Deploy from backend/ directory

Frontend (Vercel/Netlify)

# Set VITE_API_URL to your backend URL
# Deploy from frontend/ directory
vercel --prod

Database (Supabase)

Run the migration in frontend/supabase/migrations/ to set up tables.

πŸ§ͺ Testing

# Frontend tests
cd frontend
npm test

# Backend (manual testing)
cd backend
python scrape_news.py  # Test scraping
python send_email.py   # Test email sending

πŸ“ Development Workflow

  1. Backend changes: Edit Python files, restart server
  2. Frontend changes: Hot reload via Vite
  3. Database schema: Update Supabase migrations
  4. New categories: Update NEW_CATEGORIES in supabase_client.py

πŸ”’ Security Notes

  • Never commit .env files
  • Use service role key for backend (not anon key)
  • Rotate UNSUBSCRIBE_SALT if exposed
  • Use Gmail app passwords (not account password)

πŸ› Troubleshooting

Frontend can't reach backend

  • Check VITE_API_URL is set correctly
  • Verify backend CORS allows frontend domain

No articles scraped

  • Check Gemini API quota/limits
  • Verify Google News RSS is accessible

Emails not sending

  • Verify Gmail app password is correct
  • Check Gmail "Less secure app access" settings

πŸ“„ License

MIT License - see LICENSE file for details

🀝 Contributing

This is a personal project, but suggestions are welcome! Open an issue to discuss changes.

πŸ“§ Contact

For questions about the newsletter: [Your Contact Info]


Built with ❀️ for battery industry professionals

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors