AutomationFlowsAI & RAG › Generate a Weekly Content Calendar with Openai Gpt-5-mini, RSS Feeds, and Notion

Generate a Weekly Content Calendar with Openai Gpt-5-mini, RSS Feeds, and Notion

ByDiego Alejandro Parrás @diegoalejandroparras on n8n.io

Categories: AI, Content Creation, Marketing Automation, Productivity

Cron / scheduled trigger★★★★☆ complexityAI-powered17 nodesRSS Feed ReadOpenAINotion
AI & RAG Trigger: Cron / scheduled Nodes: 17 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #13103 — we link there as the canonical source.

This workflow follows the Notion → OpenAI recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "Rq90UFhzDszsXRyyx5SgZ",
  "name": "Generate weekly content calendar with AI from RSS feeds",
  "tags": [],
  "nodes": [
    {
      "id": "b44f2fe5-42ee-4950-a1ba-7e669b78ca91",
      "name": "Weekly Monday 9AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        1088,
        560
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                1
              ],
              "triggerAtHour": 9
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "2544fab0-093b-4d42-bc2b-1148f5b2f00d",
      "name": "RSS Feed - Tech News",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        1312,
        464
      ],
      "parameters": {
        "url": "https://techcrunch.com/feed/",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "cd4ab05f-e858-4b72-a586-ef01cc4dc556",
      "name": "RSS Feed - Biz & IT",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        1312,
        656
      ],
      "parameters": {
        "url": "https://feeds.arstechnica.com/arstechnica/technology-lab",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "d5887fcb-ed45-4c73-9044-7caf86e47fbd",
      "name": "RSS Feed - MIT Science & Tech",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        1312,
        864
      ],
      "parameters": {
        "url": "https://news.mit.edu/rss/topic/science-technology-and-society",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "2ea32e74-4006-4a67-8719-0c2aa271dc0d",
      "name": "Combine All Articles",
      "type": "n8n-nodes-base.merge",
      "position": [
        1744,
        640
      ],
      "parameters": {
        "numberInputs": 3
      },
      "typeVersion": 3
    },
    {
      "id": "2192d450-36c0-4b24-a84a-edf5aebbe6a1",
      "name": "Filter and Format Articles",
      "type": "n8n-nodes-base.code",
      "position": [
        1968,
        656
      ],
      "parameters": {
        "jsCode": "/*\n * Filter and Format Articles for AI\n * ==================================\n * Purpose: Filters recent articles and formats them as a numbered list\n *          for AI prompt consumption.\n * \n * Input: Array of article items from merged RSS feeds\n * Output: Object with articleCount, articlesList (formatted), rawArticles\n * \n * To customize: Change the UPPERCASE values below\n */\n\n// \u2699\ufe0f CONFIGURATION - Edit these to customize behavior\nconst DAYS_BACK = 7;           // Number of days to look back for articles\nconst MAX_ARTICLES = 20;       // Maximum number of articles to send to AI\nconst SNIPPET_LENGTH = 150;    // Maximum characters for article description preview\n\n// ==================== CODE START ====================\n\n// Create a date object for the cutoff point (7 days ago)\nconst cutoffDate = new Date();\n// Subtract DAYS_BACK days from today's date to get the oldest allowed date\ncutoffDate.setDate(cutoffDate.getDate() - DAYS_BACK);\n\n// Get all items from the previous node (Merge) and extract just the JSON data\n// $input.all() returns all items as array, .map() extracts the .json property from each\nconst allArticles = $input.all().map(item => item.json);\n\n// Filter, sort, and limit the articles\nconst processedArticles = allArticles\n  // Keep only articles that have a pubDate AND were published after the cutoff\n  .filter(article => {\n    // Skip articles without a publication date\n    if (!article.pubDate) return false;\n    // Compare article date with cutoff - keep if newer than cutoff\n    return new Date(article.pubDate) >= cutoffDate;\n  })\n  // Sort by publication date, newest first (descending order)\n  // b - a = descending (newest first), a - b would be ascending (oldest first)\n  .sort((a, b) => new Date(b.pubDate) - new Date(a.pubDate))\n  // Take only the first MAX_ARTICLES items (default: 20)\n  .slice(0, MAX_ARTICLES);\n\n// Format articles as a numbered list string for the AI prompt\nconst formattedList = processedArticles\n  .map((article, index) => {\n    // Get the article snippet, with fallbacks if contentSnippet doesn't exist\n    // Try contentSnippet first, then description, finally use default text\n    const snippet = (article.contentSnippet || article.description || 'No description')\n      // Truncate to SNIPPET_LENGTH characters to keep the list manageable\n      .substring(0, SNIPPET_LENGTH);\n    // Format each article as: \"1. \"Article Title\" - Description preview...\"\n    return `${index + 1}. \"${article.title}\" - ${snippet}...`;\n  })\n  // Join all formatted articles with newline characters into one string\n  .join('\\n');\n\n// ==================== CODE END ======================\n\n// Return the processed data in n8n's required format\n// Must return an array of objects, each with a 'json' property\nreturn [{\n  json: {\n    articleCount: processedArticles.length,  // Number of articles found (for conditional check)\n    articlesList: formattedList,              // Formatted string for AI prompt\n    rawArticles: processedArticles            // Original article objects (for reference/debugging)\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "5730d377-6228-4d7c-9ec0-d02a6003cd96",
      "name": "Has Articles?",
      "type": "n8n-nodes-base.if",
      "position": [
        2176,
        640
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "condition-has-articles",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.articleCount }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "38d662bb-a7f7-493c-9d79-27b409dabc61",
      "name": "Generate Content Calendar (Structured)",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        2400,
        544
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5-mini",
          "cachedResultName": "GPT-5-MINI"
        },
        "options": {
          "maxTokens": 4000
        },
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "=# ROLE\nYou are a content strategist creating a weekly content calendar.\n\n# TASK\n\nYour task is to analyze a list of trending articles and generate content ideas for the following week.\n\n# RULES\n\n## STRICT OUTPUT RULES:\n\n- Output MUST be valid JSON only.\n- Do NOT include Markdown, comments, explanations, or extra text.\n\n- Each object MUST follow EXACTLY this structure:\n\n{\n  \n  \"Title\": \"...\",\n  \"Content type\": \"...\",\n  \"Target Audience\": \"...\",\n  \"Publish Day\": \"...\",\n  \"Status\": \"Draft\",\n  \"Key Point\": \"...\"\n}\n\n## FIELD RULES:\n- \"Title\": short, clear, and actionable (max 80 characters).\n- \"Content type\": choose one (e.g. LinkedIn post, Carousel, Short video, Newsletter, Thread, Case study, Checklist).\n- \"Target Audience\": specific professional segment.\n- \"Publish Day\": MUST be one of these exact values:\n  MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY\n- \"Status\": MUST always be \"Draft\".\n- \"Key Point\": one concise sentence describing the main takeaway.\n\n## CONTENT RULES:\n\n- Generate exactly 7 ideas.\n- Distribute ideas across MONDAY\u2013FRIDAY (no empty days; some days may repeat).\n- Mix content types across the week (avoid repeating the same type more than twice).\n- Each idea must be inspired by the trends but provide a unique, original angle.\n- Focus on practical, actionable value for professionals.\n\n# IMPORTANT:\nReturn JSON only."
            },
            {
              "content": "=Based on these trending articles from this week:\n\n{{ $json.articlesList }}\n\nGenerate exactly 7 content ideas for next week's content calendar.\n"
            }
          ]
        },
        "jsonOutput": true
      },
      "typeVersion": 1.8
    },
    {
      "id": "2b237c53-b051-4983-bc34-04ebaeacd40a",
      "name": "Split Into Individual Ideas",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        2688,
        544
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "message.content.ideas"
      },
      "typeVersion": 1
    },
    {
      "id": "85f07e46-72c9-469e-bb33-26921ef65ab5",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        448,
        176
      ],
      "parameters": {
        "width": 520,
        "height": 924,
        "content": "## Generate weekly content calendar with AI from RSS feeds\n\n### How it works\nThis workflow automatically generates a weekly content calendar by analyzing trending articles from your industry RSS feeds. Every Monday at 9 AM, it collects articles from TechCrunch, Ars Technica, and MIT News, filters those published in the last 7 days, and uses OpenAI's structured output to generate exactly 7 content ideas in validated JSON format. Each idea includes a title, content type, target audience, and key talking points\u2014then automatically adds them to your Notion database.\n\n### Setup steps\n1. **Configure RSS feeds**: Replace the example URLs with feeds relevant to your industry\n2. **Add OpenAI credentials**: Connect your OpenAI API key (gpt-5-mini recommended)\n3. **Create Notion database** with these properties:\n   - Title (title)\n   - Content Type (select: blog, linkedin, twitter, video, newsletter)\n   - Target Audience (rich text)\n   - Publish Day (select: Monday-Friday)\n   - Status (select: Draft, In Progress, Done)\n   - Key Points (rich text)\n4. **Connect Notion**: Add your Notion credentials and select your database\n5. **Map fields**: In the Notion node, map the AI output fields to your database properties\n6. **Test manually** before enabling the schedule\n\n**Tip**: Duplicate RSS nodes to add more sources. The AI automatically adjusts to more input."
      },
      "typeVersion": 1
    },
    {
      "id": "87048c0a-6fd0-4275-b7cb-e978a8dc4e71",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1232,
        352
      ],
      "parameters": {
        "color": 7,
        "width": 272,
        "height": 720,
        "content": "### \ud83d\udce5 RSS Sources\nAdd your industry feeds here.\nDuplicate nodes for more sources."
      },
      "typeVersion": 1
    },
    {
      "id": "fa37bf50-0e1e-4035-ac45-65b89bec62e8",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1664,
        448
      ],
      "parameters": {
        "color": 7,
        "width": 472,
        "height": 440,
        "content": "### \ud83d\udd04 Processing\nAggregate and filter articles from last 7 days.\n\n**Customize in code:**\n- `DAYS_BACK` \u2192 time window\n- `MAX_ARTICLES` \u2192 limit for AI"
      },
      "typeVersion": 1
    },
    {
      "id": "66b56246-3251-4ff5-8f75-52035c5d4935",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2336,
        400
      ],
      "parameters": {
        "color": 7,
        "width": 464,
        "height": 352,
        "content": "### \ud83e\udd16 AI Generation\nGPT creates 7 content ideas with strict JSON output.\n\nDistributes across Monday-Friday."
      },
      "typeVersion": 1
    },
    {
      "id": "b6dc2f28-9f0c-407d-a2de-b6fe93f0e727",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2832,
        384
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 384,
        "content": "### \ud83d\udcdd Notion Output\nEach idea becomes a database page.\n\nReady for your content workflow."
      },
      "typeVersion": 1
    },
    {
      "id": "d2554d17-ab84-4d9d-89f9-d118372ac06c",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2368,
        784
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 240,
        "content": "\n\n\n\n\n\n\n\n\n\n\n**No articles found in timeframe**\n\nStop execution gracefully."
      },
      "typeVersion": 1
    },
    {
      "id": "1c2c3d0c-e5aa-484a-b5f0-1b694a641a7a",
      "name": "No Recent Articles",
      "type": "n8n-nodes-base.noOp",
      "position": [
        2400,
        800
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "22f4adea-5c1f-4498-a657-ff34bb52c2da",
      "name": "Create Database Page in Notion",
      "type": "n8n-nodes-base.notion",
      "position": [
        2896,
        544
      ],
      "parameters": {
        "title": "={{ $json.Title }}",
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Content Type",
              "richText": "={{ $json['Content type'] }}"
            },
            {
              "key": "Target Audience",
              "richText": "={{ $json['Target Audience'] }}"
            },
            {
              "key": "Publish Day",
              "richText": "={{ $json['Publish Day'] }}"
            },
            {
              "key": "Status",
              "richText": "={{ $json.Status }}"
            },
            {
              "key": "Key Points",
              "richText": "={{ $json['Key Point'] }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "d070e9ed-1d62-4db9-9231-892f76bee2eb",
  "connections": {
    "Has Articles?": {
      "main": [
        [
          {
            "node": "Generate Content Calendar (Structured)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Recent Articles",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Weekly Monday 9AM": {
      "main": [
        [
          {
            "node": "RSS Feed - Tech News",
            "type": "main",
            "index": 0
          },
          {
            "node": "RSS Feed - Biz & IT",
            "type": "main",
            "index": 0
          },
          {
            "node": "RSS Feed - MIT Science & Tech",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RSS Feed - Biz & IT": {
      "main": [
        [
          {
            "node": "Combine All Articles",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Combine All Articles": {
      "main": [
        [
          {
            "node": "Filter and Format Articles",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RSS Feed - Tech News": {
      "main": [
        [
          {
            "node": "Combine All Articles",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter and Format Articles": {
      "main": [
        [
          {
            "node": "Has Articles?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Into Individual Ideas": {
      "main": [
        [
          {
            "node": "Create Database Page in Notion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RSS Feed - MIT Science & Tech": {
      "main": [
        [
          {
            "node": "Combine All Articles",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Generate Content Calendar (Structured)": {
      "main": [
        [
          {
            "node": "Split Into Individual Ideas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Categories: AI, Content Creation, Marketing Automation, Productivity

Source: https://n8n.io/workflows/13103/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

AI Innovation Feed → Notion (Top 3 every 3 days). Uses rssFeedRead, openAi, notion. Scheduled trigger; 17 nodes.

RSS Feed Read, OpenAI, Notion
AI & RAG

AI-powered priority re-evaluation every 2 hours. Analyzes new signals, meeting decisions, emails, and blockers, then runs 3 AI passes (Impact, Urgency, Final Ranking) to suggest re-ranking. Only updat

Notion, OpenAI, Slack
AI & RAG

YouTube Automation Pipeline - Notion + Gemini + CometAPI + JSON2Video. Uses notion, httpRequest, googleDrive, writeBinaryFile. Scheduled trigger; 43 nodes.

Notion, HTTP Request, Google Drive +3
AI & RAG

This workflow automatically collects the latest technology news, filters for emerging topics, and uses AI to score relevance and generate clean, ready-to-share content. It helps you focus on high-impa

RSS Feed Read, OpenAI, Google Sheets +1
AI & RAG

Daily trigger scans your Notion database for unpublished blog ideas AI generates complete blog posts + engaging LinkedIn content using OpenAI (Blog Posting is not implemented yet) Creates custom image

Notion, Error Trigger, Gmail +3