AI News Digest Workflow
Complete Instruction Manual — n8n Self-Hosted Automation
No results found. Try a different search term.
This is a fully automated AI News Digest system that runs without any manual action needed.
Four Coverage Categories
Why This Is Useful
- Saves 30–60 minutes of manual news reading per day
- Provides a curated, summarized view instead of raw articles
- Delivered automatically — no manual action needed
- Consistent format makes it easy to scan quickly
2.1 n8n (Workflow Automation Platform)
- Runs: Locally on your Windows machine via Node.js
- Access:
http://localhost:5678 - Key concept: n8n uses "nodes" (building blocks) connected together to form a "workflow"
2.2 RSS Feeds (News Sources)
RSS (Really Simple Syndication) is a standard format websites use to publish their latest content in a structured, machine-readable way. No API key needed — RSS feeds are publicly available.
| Source | URL | Focus |
|---|---|---|
| TechCrunch AI | techcrunch.com/category/artificial-intelligence/feed/ | Startup & industry news |
| The Verge AI | theverge.com/rss/index.xml | Consumer tech & AI products |
| VentureBeat AI | venturebeat.com/category/ai/feed/ | Enterprise AI & business |
| MIT Tech Review | technologyreview.com/feed/ | Research & deep tech |
2.3 OpenAI API (GPT-4o-mini)
- Model: GPT-4o-mini — fast, cost-effective, and highly capable
- How it's called: Via n8n's built-in OpenAI node with your API key
- API Key: Obtained from
https://platform.openai.com/api-keys
2.4 Gmail SMTP (Email Delivery)
- Server: smtp.gmail.com, Port 465 (SSL)
- Authentication: Uses a Gmail App Password (not your regular password)
- Recipients: chekchoon@gmail.com and chekchoon@sp.edu.sg
Data Flow Explained
- Schedule fires → triggers all 4 RSS nodes simultaneously
- Each RSS node fetches ~10–20 latest articles from its source
- Merge nodes combine all articles into one list (~40–80 items)
- Code node sorts by date, removes duplicates, keeps top 25
- OpenAI receives the 25 article titles + summaries
- OpenAI returns a structured 4-section digest
- Code node wraps the digest in HTML with CSS styling
- Email node sends the HTML email via Gmail to both recipients
Node 1: Schedule Trigger — Cron Expression
| Part | Value | Meaning |
|---|---|---|
| Minute | 0 | At minute 0 (top of the hour) |
| Hour | 8 | At 8 AM |
| Day of month | * | Every day of month |
| Month | * | Every month |
| Day of week | 1-5 | Monday (1) through Friday (5) only |
0 8 * * 1-5
Nodes 2–5: RSS Feed Readers — Output Fields
Each RSS node outputs an array of article objects containing:
| Field | Description |
|---|---|
title | Article headline |
contentSnippet | Short text preview |
link | URL to full article |
isoDate | Publication date/time (ISO format) |
pubDate | Alternative date format |
Node 9: Process & Deduplicate — Code
const items = $input.all();
const sorted = items.sort((a, b) => {
const dateA = new Date(a.json.isoDate || a.json.pubDate || 0);
const dateB = new Date(b.json.isoDate || b.json.pubDate || 0);
return dateB - dateA;
});
const seen = new Set();
const unique = sorted.filter(item => {
const title = (item.json.title || '').toLowerCase().trim();
if (seen.has(title)) return false;
seen.add(title);
return true;
});
const top = unique.slice(0, 25);
const newsText = top.map((item, i) => {
const title = item.json.title || 'No title';
const snippet = (item.json.contentSnippet || item.json.summary || item.json.content || '')
.replace(/<[^>]+>/g, '').substring(0, 300);
const date = item.json.isoDate || item.json.pubDate || '';
return `${i + 1}. ${title} (${date})\n${snippet}`;
}).join('\n\n');
const today = new Date();
const dateStr = today.toLocaleDateString('en-US', {
weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'
});
const systemPrompt = "You are an expert AI news curator...";
const userPrompt = "AI news digest for " + dateStr + ":\n\n" + newsText;
return [{ json: {
dateStr,
messages: [
{ role: "system", content: systemPrompt },
{ role: "user", content: userPrompt }
]
} }];
Node 10: OpenAI — Response Path
output[0].content[0].text
Node 11: Build HTML Email — Key Settings
| Setting | Value |
|---|---|
| Input path | $input.first().json.output[0].content[0].text |
| Markdown handling | Converts ####, ###, ## to HTML headings |
| Styling | Light green background, dark green headers |
| Output fields | html (full HTML) and subject (email subject line) |
Node 12: Send Email — Configuration
| Field | Value |
|---|---|
| From | Your Gmail address |
| To | chekchoon@gmail.com, chekchoon@sp.edu.sg |
| Subject | ={{ $json.subject }} (expression toggle ON) |
| Message | ={{ $json.html }} (expression toggle ON) |
| Email Type | HTML |
fx icon). Without it, the literal text ={{ $json.html }} is sent instead of the actual HTML.
5.1 OpenAI API Key
- Go to
https://platform.openai.com/api-keys - Click "Create new secret key"
- Give it a name (e.g., "n8n AI Digest")
- Copy the key (starts with
sk-proj-...) — you only see it once! - In n8n: Settings → Credentials → Add → OpenAI
- Paste the key and click Save
https://platform.openai.com/settings/limits. Recommended starting limit: $5/month — more than enough for daily digests. When the limit is reached, OpenAI will stop processing requests but your account remains active.
5.2 Gmail App Password
- Enable 2-Factor Authentication on your Google account (required first)
- Go to
https://myaccount.google.com/apppasswords - Select "Mail" as the app, then click "Generate"
- Copy the 16-character password (e.g.,
abcd efgh ijkl mnop) - In n8n: Settings → Credentials → Add → SMTP
- Enter:
- Host:
smtp.gmail.com - Port:
465 - SSL: ON
- User:
your-email@gmail.com - Password: the 16-char app password (no spaces)
- Host:
❌ "404 Not Found" on RSS node
Fix: Visit the news website directly, look for an RSS icon or link in the footer, and update the URL in the RSS node.
Alternative URLs to try:
TechCrunch: https://techcrunch.com/feed/
The Verge: https://www.theverge.com/rss/index.xml
❌ "Bad request" on OpenAI node
- Is your OpenAI API key valid and not expired?
- Do you have credits in your OpenAI account?
- Is the credential properly linked to the node?
- Check OpenAI status at
https://status.openai.com
❌ Email sends but no content shows
Fix:
- Open the Send Email node
- Set Email Type = HTML
- Message field must contain
={{ $json.html }}with expression toggle ON - Subject must contain
={{ $json.subject }}with expression toggle ON
❌ Workflow runs on weekends
* * * instead of 1-5.
Fix: Ensure cron is 0 8 * * 1-5 (not 0 8 * * *)
❌ "Module disallowed" in Code node
What's allowed: Pure JavaScript only (Math, JSON, Array, Date, etc.)
What's NOT allowed: require('https'), require('fs'), fetch, this.helpers
Fix: Use n8n's dedicated nodes (HTTP Request, OpenAI) for external calls
❌ Content shows as "[object Object]"
Fix: Use JSON.stringify(object) to convert to readable text, or navigate to the correct nested property (e.g., output[0].content[0].text)
❌ n8n stops after closing terminal
Fix: Run n8n as a background service using PM2:
# Install PM2 process manager
npm install -g pm2
# Start n8n with PM2
pm2 start n8n
# Auto-start on system boot
pm2 startup
pm2 save
❌ Headers not formatting in email
### or ####) that your regex doesn't handle.
Fix: Update the markdownToHtml function to handle all heading levels:
| Markdown | HTML Output | Usage |
|---|---|---|
#### | <h2> | Section headers |
### | <h2> | Main title |
## | <h3> | Sub-headers |
7.1 Add More News Sources
Wired AI: https://www.wired.com/feed/tag/ai/latest/rss
Ars Technica: https://feeds.arstechnica.com/arstechnica/index
Google AI Blog: https://blog.google/technology/ai/rss/
Hugging Face: https://huggingface.co/blog/feed.xml
7.2 Weekday Safety Net (IF Node)
Add an IF node after the Schedule Trigger to double-check it's a weekday:
// In an IF node condition:
{{ [1,2,3,4,5].includes(new Date().getDay()) }}
7.3 Store Digest in Google Sheets
Add a Google Sheets node to keep a historical archive: log each digest with date, number of articles, and key topics. Useful for tracking AI trends over time.
7.4 Add Telegram/Slack Notification
Send a quick notification alongside the email:
- Telegram Bot node — sends a brief 3-line summary to your phone
- Slack node — posts to a team channel
7.5 Topic Filtering
// Keep only articles mentioning key AI terms
const aiKeywords = ['AI', 'machine learning', 'LLM', 'GPT', 'neural', 'OpenAI', 'Anthropic'];
const filtered = items.filter(item =>
aiKeywords.some(kw =>
(item.json.title || '').toLowerCase().includes(kw.toLowerCase())
)
);
7.6 Personalized Summaries
Create different email versions for different audiences:
- Technical version (for developers) — include code snippets, model benchmarks
- Business version (for managers) — focus on business impact and ROI
7.7 Error Handling & Alerts
- Enable "Continue on Fail" on each node
- Add an IF node to check for errors
- Send yourself a simple text email if any node fails
7.8 Unsubscribe Feature
Add a one-click unsubscribe link in the email footer using n8n's webhook feature.
7.9 AI News Scoring
Use OpenAI to rate each news item by importance (1–10) and only include top-rated items.
7.10 Multi-Language Support
Add a translation step to send the digest in multiple languages for international recipients.
n8n Key Concepts
| Term | Meaning |
|---|---|
| Node | A single step/action in the workflow |
| Workflow | A chain of connected nodes |
| Trigger | The node that starts the workflow |
| Expression | Dynamic value using ={{ }} syntax |
| Credential | Saved login/API key for a service |
| Execution | One run of the entire workflow |
n8n Expression Syntax
| Expression | Meaning |
|---|---|
={{ $json.fieldName }} | Access a field from current node's data |
={{ $input.first().json.field }} | Access first input item's field |
={{ $now }} | Current date/time |
={{ new Date().toLocaleDateString() }} | Formatted date string |
Cron Expression Reference
| Expression | Schedule |
|---|---|
0 8 * * 1-5 | 8 AM, Monday–Friday |
0 9 * * 1-5 | 9 AM, Monday–Friday |
0 8 * * * | 8 AM, every day |
0 8,17 * * 1-5 | 8 AM and 5 PM, weekdays |
OpenAI Model Comparison
| Model | Speed | Cost | Best For |
|---|---|---|---|
| gpt-4o-mini ⭐ | Fast | Lowest | Daily digests (recommended) |
| gpt-4o | Medium | Medium | More detailed analysis |
| gpt-4-turbo | Slow | Highest | Complex reasoning tasks |
Common n8n Node Types
| Node | Purpose |
|---|---|
| Schedule Trigger | Time-based automation |
| RSS Feed Read | Fetch news from RSS feeds |
| Merge | Combine multiple data streams |
| Code (JavaScript) | Custom data processing |
| OpenAI | AI text generation |
| Send Email | SMTP email delivery |
| HTTP Request | Call any web API |
| IF | Conditional branching |
| Set | Modify/set data fields |