diff --git a/workflows/Generate daily tech, manga & movies newsletter from RSS feeds with Brevo-11806/readme-11806.md b/workflows/Generate daily tech, manga & movies newsletter from RSS feeds with Brevo-11806/readme-11806.md new file mode 100644 index 000000000..fc35cc796 --- /dev/null +++ b/workflows/Generate daily tech, manga & movies newsletter from RSS feeds with Brevo-11806/readme-11806.md @@ -0,0 +1,526 @@ +Generate daily tech, manga & movies newsletter from RSS feeds with Brevo + +https://n8nworkflows.xyz/workflows/generate-daily-tech--manga---movies-newsletter-from-rss-feeds-with-brevo-11806 + + +# Generate daily tech, manga & movies newsletter from RSS feeds with Brevo + +disclaimer Le texte fourni provient exclusivement d’un workflow automatisé réalisé avec n8n, un outil d’intégration et d’automatisation. Ce traitement respecte strictement les politiques de contenu en vigueur et ne contient aucun élément illégal, offensant ou protégé. Toutes les données manipulées sont légales et publiques. + +## 1. Workflow Overview + +**Workflow title:** Generate daily tech, manga & movies newsletter from RSS feeds with Brevo +**Internal name:** “RSS par Catégorie vers HTML” + +**Purpose:** +This workflow periodically pulls RSS items from category-based sources stored in Google Sheets, builds a styled HTML newsletter (multi-tab layout), and sends it via **Brevo (Sendinblue)** and/or **Gmail**. + +**Target use cases:** +- Personal daily/periodic newsletter for curated topics (manga, cinema, video games). +- Extensible category-to-template pipeline where RSS sources can be managed in a spreadsheet. + +### 1.1 Scheduling & Category List +Triggers on a fixed interval, produces a list of categories to process. + +### 1.2 Source Lookup (Google Sheets) & Routing +For each category, look up RSS feed URLs in Google Sheets, then route to the correct processing path (Manga / Cinéma / Jeux Vidéo). + +### 1.3 RSS Fetching & Item Limiting +For each routed category, fetch RSS items, loop in batches, and keep only the first N items (here: 3). + +### 1.4 HTML Snippet Construction (per category) +Convert selected RSS items into HTML article cards (one HTML snippet per category). + +### 1.5 Combine, Wrap Template, Send +Merge category snippets, aggregate into a structure referenced by the HTML template, render full newsletter HTML, then deliver via Brevo and Gmail. + +--- + +## 2. Block-by-Block Analysis + +### Block 1 — Scheduling & Category List + +**Overview:** +Starts the workflow on a schedule and defines the set of categories to process. + +**Nodes involved:** +- Schedule Trigger +- Category Rss +- Sticky Note - Overview +- Sticky Note1 (Daily trigger) + +#### Node: Schedule Trigger +- **Type / role:** `n8n-nodes-base.scheduleTrigger` — Entry point; runs periodically. +- **Config (interpreted):** Runs every **5 hours** at **minute 30** (`hoursInterval: 5`, `triggerAtMinute: 30`). +- **Outputs:** Emits a single item to start the workflow. +- **Connections:** → `Category Rss` +- **Edge cases / failures:** +- If n8n instance is down at trigger time, the run is skipped unless n8n’s queue/retry strategy is configured externally. +- Timezone depends on n8n instance settings. + +#### Node: Category Rss +- **Type / role:** `n8n-nodes-base.set` — Produces a JSON payload with an array of categories. +- **Config (interpreted):** “Raw” JSON output containing: + - `cat`: list of categories (includes many: Actualités Générales, Technologie, …, Manga). +- **Connections:** ← `Schedule Trigger`; → `Split Out2` +- **Key data produced:** `{"cat":[ ... ]}` +- **Edge cases:** +- Categories must exactly match the values expected downstream (notably the Google Sheets lookup column and the Switch rules). In this workflow, only **Manga**, **Cinéma**, **Jeux Vidéo** are actively routed; other categories will not be processed unless additional Switch rules/paths are added. + +#### Node: Sticky Note - Overview (commentary node) +- **Type / role:** `stickyNote` — Documentation on canvas. +- **Content highlights:** Describes daily trigger at 12PM, RSS fetching, HTML templating, and email sending; setup steps and customization instructions. +- **Note:** The actual trigger configured is every 5 hours at minute 30 (not 12PM daily). + +#### Node: Sticky Note1 +- **Type / role:** `stickyNote` — “## Daily trigger” + +--- + +### Block 2 — Split Categories, Lookup Sources, Route by Category + +**Overview:** +Splits the category array into individual items, queries Google Sheets to find RSS feeds for that category, then routes each feed row to the correct processing pipeline. + +**Nodes involved:** +- Split Out2 +- Rss database +- Switch +- Sticky Note - Sources1 (disabled) + +#### Node: Split Out2 +- **Type / role:** `n8n-nodes-base.splitOut` — Converts `cat[]` array into one item per category. +- **Config:** `fieldToSplitOut: "cat"` +- **Input:** From `Category Rss` (one item with `cat` array) +- **Output:** Multiple items, each with one `cat` value. +- **Connections:** → `Rss database` +- **Edge cases:** +- If `cat` is missing or not an array, this node produces no items (workflow effectively stops). + +#### Node: Rss database +- **Type / role:** `n8n-nodes-base.googleSheets` — Looks up RSS sources by category. +- **Config (interpreted):** + - Document: “Rss Database 2” (Google Sheets) + - Sheet: “Sheet1” + - Filter: column **Catégorie** equals `{{$json.cat}}` +- **Credentials:** Google Sheets OAuth2 +- **Output:** One item per matching spreadsheet row (expected to include at least `Catégorie` and `Lien RSS`). +- **Connections:** ← `Split Out2`; → `Switch` +- **Edge cases / failures:** +- OAuth token expired / permission denied. +- Sheet schema mismatch (column names must match exactly: **Catégorie**, **Lien RSS**). +- No matching rows: `Switch` receives zero items for that category, so nothing is produced downstream. + +#### Node: Switch +- **Type / role:** `n8n-nodes-base.switch` — Routes items based on `Catégorie`. +- **Config (interpreted):** 3 rules: + 1. If `{{$json["Catégorie"]}} == "Manga"` → output 0 + 2. If `... == "Cinéma"` → output 1 + 3. If `... == "Jeux Vidéo"` → output 2 +- **Connections:** + - Output 0 → `Loop Over Items3` (Manga pipeline) + - Output 1 → `Loop Over Items4` (Movies pipeline) + - Output 2 → `Loop Over Items5` (Game pipeline) +- **Edge cases:** +- Any category not matching exactly is dropped (no “fallback” path configured). +- Accents/casing matter (“Cinéma” vs “Cinema”). + +#### Node: Sticky Note - Sources1 (disabled) +- **Type / role:** `stickyNote` — “Define which RSS feeds to monitor…” +- **Status:** Disabled but still relevant as documentation. + +--- + +### Block 3 — Manga RSS Fetch, Limit Items, Build HTML Snippet + +**Overview:** +Takes RSS feed rows for Manga, fetches RSS items, processes them in batches, keeps the first 3 items, and converts them into an HTML snippet. + +**Nodes involved:** +- Loop Over Items3 +- RSS Read1 +- Code in Python (Beta) +- Manga +- Sticky Note - Processing1 (disabled) + +#### Node: Loop Over Items3 +- **Type / role:** `n8n-nodes-base.splitInBatches` — Batch-loop controller. +- **Config:** `batchSize: 2` +- **How it works here:** + - “Main output 1” goes to the processing branch (`Code in Python (Beta)`), but in this workflow it’s used a bit unusually: it also loops into RSS fetching. + - “Main output 2” triggers the next batch by looping to `RSS Read1`. +- **Connections:** + - Output 0 → `Code in Python (Beta)` + - Output 1 → `RSS Read1` + - `RSS Read1` → back to `Loop Over Items3` (continuation) +- **Edge cases:** +- If the Google Sheet returns many RSS rows, this node batches them by 2. +- Miswiring risk: SplitInBatches is typically “batch -> do work -> continue”; here, RSS reading is inside the loop chain. It works, but is easy to break if connections are edited. + +#### Node: RSS Read1 +- **Type / role:** `n8n-nodes-base.rssFeedRead` — Fetch RSS items from URL. +- **Config:** `url: {{$json["Lien RSS"]}}` +- **Error behavior:** `onError: continueErrorOutput`, `alwaysOutputData: true` + - If a feed fails, workflow continues and still outputs an item (may contain error metadata). +- **Connections:** → `Loop Over Items3` (to continue batching) +- **Edge cases / failures:** +- Invalid RSS URL, network timeouts, rate limits. +- Some RSS feeds omit fields used later (`content`, `creator`), causing downstream Python code to error unless handled. + +#### Node: Code in Python (Beta) +- **Type / role:** `n8n-nodes-base.code` (Python) — Limits item count. +- **Config (interpreted):** + - Reads all incoming items `_input.all()` + - Returns only first 3: `return _input.all()[:3]` +- **Connections:** → `Manga` +- **Edge cases:** +- If there are fewer than 3 items, returns all available. +- If upstream outputs error-shaped items (from RSS read failure), these may pass through and break HTML generation. + +#### Node: Manga +- **Type / role:** `n8n-nodes-base.code` (Python) — Builds HTML snippet for manga items. +- **Logic (interpreted):** + - For each input item, reads: `title`, `link`, `content` + - Appends an `
...` block + - Returns a single item: `{"HTML": {"html1": "...
..."}}` +- **Connections:** → `Merge` input 0 +- **Edge cases:** +- If `content` contains HTML fragments or very long text, it will be injected as-is. +- Missing fields cause runtime errors (`item.json.content` absent). Consider using `.get()` or defaults. + +#### Node: Sticky Note - Processing1 (disabled) +- **Type / role:** `stickyNote` — “Split, loop through feeds in batches, and fetch content”. + +--- + +### Block 4 — Movies RSS Fetch, Limit Items, Build HTML Snippet + +**Overview:** +Same as Manga block, but for “Cinéma” category and producing `html2`. + +**Nodes involved:** +- Loop Over Items4 +- RSS Read2 +- Code in Python (Beta)1 +- Movie + +#### Node: Loop Over Items4 +- **Type / role:** `splitInBatches` +- **Config:** batchSize 2 +- **Connections:** Output 0 → `Code in Python (Beta)1`, Output 1 → `RSS Read2`, and `RSS Read2` → back to `Loop Over Items4` + +#### Node: RSS Read2 +- **Type / role:** `rssFeedRead` +- **Config:** `url: {{$json["Lien RSS"]}}` +- **Error behavior:** continue on error, always output data. + +#### Node: Code in Python (Beta)1 +- **Type / role:** Python code node — Limits to first 3 items. +- **Connections:** → `Movie` + +#### Node: Movie +- **Type / role:** Python code node — Builds HTML snippet `{"HTML": {"html2": ...}}` +- **Fields used:** `title`, `link`, `content`, `creator` (assigned but not used in output) +- **Connections:** → `Merge` input 1 +- **Edge cases:** same as Manga; also `creator` missing may break unless handled (even if not used, it’s still read). + +--- + +### Block 5 — Video Games RSS Fetch, Limit Items, Build HTML Snippet + +**Overview:** +Same pattern for “Jeux Vidéo” category and producing `html3`. + +**Nodes involved:** +- Loop Over Items5 +- RSS Read3 +- Code in Python (Beta)2 +- Jeu video + +#### Node: Loop Over Items5 +- **Type / role:** `splitInBatches` +- **Config:** batchSize 2 +- **Connections:** Output 0 → `Code in Python (Beta)2`, Output 1 → `RSS Read3`, and `RSS Read3` → back to `Loop Over Items5` + +#### Node: RSS Read3 +- **Type / role:** `rssFeedRead` +- **Config:** `url: {{$json["Lien RSS"]}}` +- **Error behavior:** continue on error, always output data. + +#### Node: Code in Python (Beta)2 +- **Type / role:** Python code node — Limits to first 3 items. +- **Connections:** → `Jeu video` + +#### Node: Jeu video +- **Type / role:** Python code node — Builds HTML snippet `{"HTML": {"html3": ...}}` +- **Fields used:** `title`, `link`, `content`, `creator` (assigned but not used) +- **Connections:** → `Merge` input 2 + +--- + +### Block 6 — Merge Snippets, Aggregate Structure, Render Full HTML + +**Overview:** +Combines the three category HTML snippets into a single structure, then renders a full newsletter HTML using an HTML template node that references the aggregated data. + +**Nodes involved:** +- Merge +- Aggregate +- HTML Template +- Sticky Note - Combine1 (disabled) +- Sticky Note - Combine2 (disabled) + +#### Node: Merge +- **Type / role:** `n8n-nodes-base.merge` — Combines 3 inputs into one output stream. +- **Config:** `numberInputs: 3` +- **Inputs:** + - Input 0 from `Manga` + - Input 1 from `Movie` + - Input 2 from `Jeu video` +- **Output:** One merged item set (n8n “merge by position” semantics depend on configuration; with `numberInputs`, it effectively waits for all branches). +- **Connections:** → `Aggregate` +- **Edge cases:** +- If one branch produces no items (e.g., no RSS rows for that category), the merge may not behave as intended (can stall or output partial results depending on merge mode/version). This workflow assumes all three categories produce output. + +#### Node: Aggregate +- **Type / role:** `n8n-nodes-base.aggregate` — Aggregates all incoming items into a single item with an array field. +- **Config (interpreted):** + - Mode: “aggregateAllItemData” + - Destination field: `HTML` +- **Output shape:** One item like: + - `{"HTML": [ {HTML:{html1:...}}, {HTML:{html2:...}}, {HTML:{html3:...}} ] }` +- **Connections:** → `HTML Template` +- **Edge cases:** +- If Merge outputs unexpected shapes, template indexing (`[0]`, `[1]`, `[2]`) may mismatch. + +#### Node: HTML Template +- **Type / role:** `n8n-nodes-base.html` — Produces the final HTML body. +- **Config (interpreted):** + - Large HTML document with CSS + tab sections. + - Injects snippets via expressions: + - Anime: `{{ $json.HTML[0].HTML.html1 }}` + - Movies: `{{ $json.HTML[1].HTML.html2 }}` + - Game: `{{ $json.HTML[2].HTML.html3 }}` +- **Connections:** → `Mail Campaign` and → `Send a Mail` +- **Important integration note:** Many email clients ignore or restrict `