An AI-powered autonomous curator that transforms doomscrolling into hope-scrolling
Features β’ Demo β’ Quick Start β’ Roadmap β’ Contributing
Doomscrolling is destroying our mental health. Studies show 73% of news consumers experience anxiety from constant negative coverage. We built an autonomous AI agent that fights back.
Every 6 hours, our serverless engine:
- π Scans 100+ global headlines
- π€ AI-filters for genuinely uplifting stories (no toxic positivity)
- β¨ Summarizes with context and emotional intelligence
- π± Delivers hope directly to your app/feed
Zero maintenance. Zero cost (under 10K users). 100% good vibes.
- π§ Smart AI Curation - Gemini 2.5 Flash enforces strict "Good News" criteria
- β No politics/crime/tragedy
- β Yes to science breakthroughs, human kindness, environmental wins
- β‘ Batch Processing - Analyzes 20+ articles per AI call (cost: ~$0.002/batch)
- π Auto-Deduplication - URL fingerprinting prevents story repeats
- π§Ή Self-Cleaning Database - 48-hour TTL keeps Firestore lean
- π One-Command Deploy -
firebase deploy --only functions - π Secret Manager Integration - No
.envfiles, no leaked keys - π Built-in Analytics - Track filter rates and AI performance
- π§ͺ Local Testing Suite - Validate filters before deployment
Try the engine: goodnews-demo.web.app
Sample Output:
{
"title": "Scientists Develop Plastic-Eating Enzyme 10x More Efficient",
"summary": "Researchers at UT Austin engineered a bacterial enzyme that breaks down PET plastic in hours instead of centuries...",
"category": "Environment",
"sentiment": "breakthrough",
"publishedAt": "2025-01-14T08:30:00Z"
}node --version # 20+
firebase --version # 13+git clone https://codeberg.org/yourusername/good-news-engine
cd good-news-engine
npm install# Initialize Firebase
firebase login
firebase init functions
# Store keys securely
firebase functions:secrets:set GEMINI_API_KEY
firebase functions:secrets:set NEWSDATA_API_KEYfirebase deploy --only functions
# β
Function deployed: https://us-central1-yourproject.cloudfunctions.net/fetchGoodNews# Trigger the function
curl -X POST https://YOUR_FUNCTION_URL
# Check Firestore
firebase firestore:read goodNews --limit 5good-news-engine/
βββ functions/
β βββ index.js # Main Cloud Function
β βββ filters.js # AI prompt templates
β βββ package.json
βββ firestore.rules # Security rules
βββ firebase.json
βββ README.md
βββ .gitignore
- Automated fetching + filtering
- Gemini 2.5 Flash integration
- Firestore storage with TTL
- Category Tagging - Science, Environment, Health, etc.
- Sentiment Scoring - "Inspiring" vs "Hopeful" vs "Breakthrough"
- Multi-Language Support - Spanish, French, German (using Gemini's built-in translation)
- RSS Feed Output -
goodnews.rssfor compatibility
- Upvote System - Let users vote on their favorite stories
- Weekly Digest Email - Automated Mailchimp/SendGrid integration
- Browser Extension - Replace "Trending News" with good news
- Public API - Share good news with other developers
- Premium Tier - Custom filters, private instances ($5/mo)
- White-Label Licensing - For mental health apps
- Corporate Wellness - Slack/Teams integration
| Service | Usage | Cost |
|---|---|---|
| NewsData.io | 200 requests/day | $0 |
| Gemini API | 1,500 requests/day | $0 |
| Firebase Functions | 2M invocations/month | $0 |
| Firestore | 50K reads/day | $0 |
| Total | $0/month |
| Service | Usage | Cost |
|---|---|---|
| NewsData.io | 10K requests/month | $0 (free tier) |
| Gemini API | 45K requests/month | $0 (free tier) |
| Firebase Functions | 6M invocations/month | $0 |
| Firestore | 1.5M reads/month | ~$0.50 |
| Total | ~$0.50/month |
Estimated at $15-30/month depending on traffic patterns. Contact us for optimization strategies.
βββββββββββββββββββ
β Cloud Schedulerβ (Every 6 hours)
ββββββββββ¬βββββββββ
β
βΌ
βββββββββββββββββββ
β Firebase Functionβ
β fetchGoodNews β
ββββββββββ¬βββββββββ
β
ββββββββββββββββ
βΌ βΌ
ββββββββββββββββ ββββββββββββββββ
β NewsData.io β β Gemini 2.5 β
β API Fetch β β Flash AI β
ββββββββ¬ββββββββ ββββββββ¬ββββββββ
β β
ββββββββββ¬βββββββββ
βΌ
βββββββββββββββββββ
β Firestore DB β
β (Auto-Cleanup) β
βββββββββββββββββββ
Key Design Decisions:
- Batch Processing - Process 20 articles in one AI call instead of 20 separate calls
- URL Fingerprinting - Hash URLs to prevent duplicate storage
- TTL Pattern - Store
createdAttimestamp, query withwhere('createdAt', '>', 48hoursAgo) - Stateless Functions - No persistent memory between runs
firebase emulators:start --only functions,firestorenode test-gemini.jsconst { analyzeArticles } = require('./functions/filters');
const mockArticles = [
{
title: "Local Dog Rescues Family from Fire",
description: "Hero pup alerts sleeping family to kitchen blaze..."
},
{
title: "Political Scandal Rocks Capital",
description: "Corruption investigation expands..."
}
];
analyzeArticles(mockArticles).then(results => {
console.log('β
Good News:', results.filter(r => r.isGoodNews));
console.log('β Filtered:', results.filter(r => !r.isGoodNews));
});We welcome contributions! Here are ways to help:
- π Report Bugs - Open an issue with reproduction steps
- π‘ Suggest Features - Share your ideas in Discussions
- π Improve Docs - Fix typos, add examples
- β Star the Repo - Help others discover this project
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-idea) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-idea) - Open a Pull Request
See CONTRIBUTING.md for detailed guidelines.
- Never commit API keys to version control
- Use Firebase Secret Manager for production
- Rotate keys every 90 days
- Enable 2FA on all service accounts
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /goodNews/{article} {
allow read: if true; // Public read
allow write: if false; // Only Cloud Functions can write
}
}
}Email security@yourproject.com (do not open public issues for security bugs)
This project is licensed under the MIT License - see LICENSE file for details.
TL;DR: You can use, modify, and distribute this freely. Just include the original license.
- NewsData.io - For providing free news API access
- Google AI - For Gemini 2.5 Flash's incredible filtering capabilities
- Firebase Team - For the best serverless platform
- You - For caring about mental health and positive news
- Issues: Open an issue
- Discussions: Join the conversation
- Twitter: @goodnewsengine
- Email: hello@goodnewsengine.dev
Every deploy makes the internet a little brighter. β¨
If this project helped you, consider:
- β Starring the repo
- π¦ Sharing on social media
- π¬ Telling a friend who needs good news
- β Buy us a coffee
Find me on nostr, codeberg, and substack ONLY!
π nostr
πΎ codeberg
π substack
If you find this helpful, consider sending a tip!
| Asset | Address |
|---|---|
| Lightning (Zap) | gallantdisk053@walletofsatoshi.com |
| Bitcoin (BTC) | bc1q073hyc4gnd4zpr3zvxldqxd7pwusktw7tguu4g |
| Monero (XMR) | 88hWjDuptnBerfkoTTAUhJ4AFuiMnMPSVVQhAbiV2rSEV7Gj2FaytRv1bnL8gPmL6U4L4XhFVBc4KbQLDmDM9hEaC4S1FV5 |
When sending Monero (XMR), your transaction is private by default. For Bitcoin, consider using a fresh address for each tip if you want to maintain maximum on-chain privacy.
Built with β€οΈ and AI to fight doomscrolling