An intelligent RSS feed watcher that monitors your favorite RSS feeds, filters content based on your interests using AI, and sends you email notifications for relevant new posts.
- 🔍 Smart Content Filtering: Uses OpenAI GPT to analyze posts and only notifies you about content relevant to your interests
- 📧 Email Notifications: Beautiful HTML email notifications with post summaries
- ⏰ Automated Monitoring: Runs on a cron schedule (every 6 hours by default) to check for new posts
- 🗄️ SQLite Database: Tracks feed history to avoid duplicate notifications
- 🌐 REST API: Simple Express server with endpoints to view feeds and manually trigger checks
- 🔒 SSL Support: Handles feeds with self-signed or problematic SSL certificates
This is how the email looks like (will improve the email template with time)

- Node.js (v16 or higher)
- npm or yarn
- An OpenAI API key (for content filtering)
- A Resend API key (get one for free at resend.com)
-
Clone the repository
git clone https://github.com/hritik2002/rss-feeds-notifier cd rss-feeds-notifier -
Install dependencies
npm install
-
Create a
.envfile in the root directory with the following variables:# OpenAI Configuration OPENAI_API_KEY=your_openai_api_key_here # Resend API Configuration RESEND_API_KEY=re_your_resend_api_key RESEND_FROM_EMAIL=onboarding@resend.dev MAIL_TO=recipient@example.com # Server Configuration (optional) PORT=3000
Notes:
- Resend API Key: Get your API key from resend.com (free tier available)
- From Email:
RESEND_FROM_EMAILis optional - if not set, defaults toonboarding@resend.dev- You cannot use Gmail, Yahoo, or other personal email domains (they must be verified)
- Use
onboarding@resend.devfor testing, or verify your own domain at resend.com/domains - The application automatically detects unverified domains and uses
onboarding@resend.devas a fallback
Edit src/data/feeds.js to add, remove, or modify RSS feed URLs:
export const feeds = [
{ url: "https://blog.pragmaticengineer.com/rss/" },
{ url: "https://overreacted.io/rss.xml" },
// Add your own feeds here
{ url: "https://example.com/feed" },
];Edit src/data/interests.js to define what content should be filtered and sent to you:
export const interests = [
"Software Engineering",
"Database internals",
"Web Development",
// Add your own interests here
"Machine Learning",
"DevOps",
];The AI will analyze each post and only send notifications if the content is relevant to these interests.
Edit src/rssWatcher.js to modify the cron schedule. The default is every 6 hours:
// Current: Every 6 hours
cron.schedule("0 */6 * * *", watchRSSFeeds);
// Examples:
// Every hour: "0 * * * *"
// Every 12 hours: "0 */12 * * *"
// Daily at 9 AM: "0 9 * * *"
// Every 30 minutes: "*/30 * * * *"Edit src/notifier.js to modify the email HTML template. The sendNewPostEmail function contains the email structure and styling.
Edit src/db.js to change the SQLite database file path:
const db = await open({
filename: './feeds.db', // Change this path
driver: sqlite3.Database
});If you need stricter SSL verification, edit src/rssWatcher.js:
const parser = new RssParser({
requestOptions: {
rejectUnauthorized: true, // Set to true for strict SSL verification
timeout: 10000, // Adjust timeout as needed
},
});Edit src/llmClient.js to use a different OpenAI model:
const response = await openai.chat.completions.create({
model: "gpt-4o-mini", // Change to "gpt-4", "gpt-3.5-turbo", etc.
// ...
});npm startThe server will:
- Start the Express server on port 3000 (or the port specified in
.env) - Run an initial RSS feed check
- Schedule automatic checks based on the cron schedule
The server exposes a REST API for managing feeds and triggering checks. All endpoints are available at http://localhost:3000 (or your configured PORT).
Quick Reference:
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Get all tracked feeds from database |
POST |
/watch-rss-feeds |
Manually trigger RSS feed check |
POST |
/add-to-db |
Add a single feed to database |
POST |
/refresh-feeds-db |
Replace all feeds in database |
Returns all tracked feeds with their latest post information from the database.
Request:
curl http://localhost:3000/Response:
[
{
"id": 1,
"url": "https://blog.pragmaticengineer.com/rss/",
"title": "The Pragmatic Engineer",
"last_link": "https://blog.pragmaticengineer.com/latest-post",
"last_updated": "2025-11-12T10:30:00.000Z"
},
...
]Manually trigger an RSS feed check. This will process all feeds configured in src/data/feeds.js, check for new posts, analyze them with AI, and send email notifications for relevant content.
Request:
curl -X POST http://localhost:3000/watch-rss-feedsResponse:
✅ RSS feeds watched
Note: This operation may take some time depending on the number of feeds and network conditions.
Add a single feed to the database and process it immediately. This is useful for adding new feeds without modifying the code.
Request:
curl -X POST http://localhost:3000/add-to-db \
-H "Content-Type: application/json" \
-d '{
"feed": {
"url": "https://example.com/feed"
}
}'Request Body:
{
"feed": {
"url": "https://example.com/feed"
}
}Response (Success):
{
"status": "success",
"message": "Feed added to db"
}Response (Error):
{
"status": "error",
"message": "Error message here"
}Note: The feed will be processed immediately - if there's a new post, you'll receive an email notification if it matches your interests.
Replace all feeds in the database with a new set. This clears the existing feeds and inserts the provided ones. Useful for bulk updates or syncing feeds from an external source.
Request:
curl -X POST http://localhost:3000/refresh-feeds-db \
-H "Content-Type: application/json" \
-d '{
"feeds": [
{
"id": 1,
"url": "https://blog.pragmaticengineer.com/rss/",
"title": "The Pragmatic Engineer",
"last_link": "https://blog.pragmaticengineer.com/latest-post",
"last_updated": "2025-11-12T10:30:00.000Z"
},
{
"id": 2,
"url": "https://overreacted.io/rss.xml",
"title": "Overreacted",
"last_link": "https://overreacted.io/latest-post",
"last_updated": "2025-11-12T09:15:00.000Z"
}
]
}'Request Body:
{
"feeds": [
{
"id": 1,
"url": "https://example.com/feed",
"title": "Feed Title",
"last_link": "https://example.com/latest-post",
"last_updated": "2025-11-12T10:30:00.000Z"
}
]
}Response:
Feeds added to db
Response (Error):
Error adding feeds to db
Note:
- This endpoint clears all existing feeds before inserting the new ones
- The
idfield is optional - if not provided, SQLite will auto-generate it - The
last_updatedfield is optional - if not provided, it defaults to the current timestamp
// Get all feeds
const feeds = await fetch('http://localhost:3000/').then(r => r.json());
// Manually trigger feed check
await fetch('http://localhost:3000/watch-rss-feeds', { method: 'POST' });
// Add a new feed
await fetch('http://localhost:3000/add-to-db', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
feed: { url: 'https://example.com/feed' }
})
});
// Refresh all feeds
await fetch('http://localhost:3000/refresh-feeds-db', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
feeds: [
{ url: 'https://example.com/feed', title: 'Example Feed' }
]
})
});import requests
# Get all feeds
feeds = requests.get('http://localhost:3000/').json()
# Manually trigger feed check
requests.post('http://localhost:3000/watch-rss-feeds')
# Add a new feed
requests.post('http://localhost:3000/add-to-db', json={
'feed': {'url': 'https://example.com/feed'}
})
# Refresh all feeds
requests.post('http://localhost:3000/refresh-feeds-db', json={
'feeds': [
{'url': 'https://example.com/feed', 'title': 'Example Feed'}
]
})- Feed Monitoring: The application periodically checks all configured RSS feeds
- Content Analysis: For each new post, the content is sent to OpenAI to:
- Determine if it's relevant to your interests
- Generate a summary (if relevant)
- Notification: If the post is relevant, a beautifully formatted email is sent with:
- Feed title
- Post title
- AI-generated summary
- Direct link to the post
- Database Tracking: The application tracks the last seen post for each feed to avoid duplicate notifications
rss-subsriber/
├── src/
│ ├── data/
│ │ ├── feeds.js # RSS feed URLs
│ │ └── interests.js # Your interests for filtering
│ ├── db.js # SQLite database initialization
│ ├── index.js # Express server entry point
│ ├── llmClient.js # OpenAI integration for content analysis
│ ├── notifier.js # Email notification service
│ └── rssWatcher.js # RSS feed monitoring and processing
├── feeds.db # SQLite database (auto-generated)
├── .env # Environment variables (create this)
├── package.json
└── readme.md
ISC
hritik2002