{
  "id": "FreeWeeklyDigest02",
  "name": "Weekly AI Digest of Your Blog (RSS to Newsletter Draft)",
  "nodes": [
    {
      "id": "8c3d98b6-ed1a-40f2-9899-82f859a5b07a",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -272,
        -240
      ],
      "parameters": {
        "width": 480,
        "height": 768,
        "content": "## Weekly AI Digest of Your Blog (RSS to Newsletter Draft)\n\n### How it works\n\nThis workflow runs every Monday morning to create a weekly AI-generated newsletter draft from a blog RSS feed. It loads configuration, reads recent posts from the feed, filters them to the last seven days, and branches based on whether any posts were found. If posts exist, it calls an AI API to write the digest and exposes the markdown for copying; otherwise it exits with a no-op path.\n\n### Setup steps\n\n- Configure the schedule trigger for the desired weekly send or draft time.\n- Set the RSS feed URL, AI API base URL, model, and newsletter tone in the configuration node.\n- Add the required HTTP/API credentials or authentication headers for the AI endpoint in the AI request node.\n- Verify the RSS feed includes publish dates so the last-seven-days filter can work correctly.\n\n### Customization\n\nAdjust the newsletter tone, AI model, RSS feed URL, or the filtering window in the code node to match a different publishing cadence or editorial style."
      },
      "typeVersion": 1
    },
    {
      "id": "8334ace1-3cec-4562-9a58-d101ccced383",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        288,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 336,
        "content": "## Schedule and configure\n\nStarts the workflow every Monday morning and sets reusable configuration values such as the RSS feed URL, AI API base URL, model, and newsletter tone."
      },
      "typeVersion": 1
    },
    {
      "id": "886822ef-e6a0-4626-9fdd-c9064e6ad6a0",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        736,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 320,
        "content": "## Fetch recent posts\n\nReads the configured blog RSS feed, keeps only posts published in the last seven days, and checks whether there is anything to turn into a digest."
      },
      "typeVersion": 1
    },
    {
      "id": "ddaafa41-d266-4418-bee1-0ba5d67c0a43",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1424,
        -240
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 336,
        "content": "## Generate newsletter draft\n\nWhen recent posts exist, sends the compact post list to the configured AI endpoint and extracts the returned newsletter markdown for copying."
      },
      "typeVersion": 1
    },
    {
      "id": "cd350cb2-928f-4950-af43-aca09a773f18",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1424,
        128
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 336,
        "content": "## Handle empty week\n\nHandles the no-posts branch by ending the workflow without generating a digest."
      },
      "typeVersion": 1
    },
    {
      "id": "weekly-trigger",
      "name": "When Weekly Triggered",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        340,
        40
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                1
              ],
              "triggerAtHour": 8
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "configure2",
      "name": "Set Configuration Parameters",
      "type": "n8n-nodes-base.set",
      "position": [
        560,
        40
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg-feed",
              "name": "feedUrl",
              "type": "string",
              "value": "https://YOUR-SITE.com/feed/"
            },
            {
              "id": "cfg-baseurl",
              "name": "apiBaseUrl",
              "type": "string",
              "value": "https://api.openai.com/v1"
            },
            {
              "id": "cfg-model",
              "name": "model",
              "type": "string",
              "value": "gpt-4o-mini"
            },
            {
              "id": "cfg-tone",
              "name": "newsletterTone",
              "type": "string",
              "value": "friendly, helpful, no hype"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "rss-read",
      "name": "Fetch Blog RSS Feed",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        780,
        40
      ],
      "parameters": {
        "url": "={{ $json.feedUrl }}",
        "options": {}
      },
      "typeVersion": 1.1
    },
    {
      "id": "filter-week",
      "name": "Filter Recent Posts",
      "type": "n8n-nodes-base.code",
      "position": [
        1000,
        40
      ],
      "parameters": {
        "jsCode": "// Keep only posts from the last 7 days and build a compact list for the AI\nconst sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;\nconst posts = [];\nfor (const item of $input.all()) {\n  const d = new Date(item.json.isoDate || item.json.pubDate || 0).getTime();\n  if (d >= sevenDaysAgo) {\n    posts.push({\n      title: item.json.title,\n      link: item.json.link,\n      snippet: (item.json.contentSnippet || item.json.content || '').slice(0, 300),\n    });\n  }\n}\nif (posts.length === 0) {\n  return [{ json: { skip: true, message: 'No new posts this week - nothing to send.' } }];\n}\nreturn [{ json: { skip: false, count: posts.length, posts } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "if-has-posts",
      "name": "Check for New Posts",
      "type": "n8n-nodes-base.if",
      "position": [
        1220,
        40
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-has-posts",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.skip }}",
              "rightValue": false
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "ai-digest",
      "name": "Post AI Digest Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1472,
        -64
      ],
      "parameters": {
        "url": "={{ $('Set Configuration Parameters').item.json.apiBaseUrl }}/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ model: $('Set Configuration Parameters').item.json.model, messages: [ { role: 'system', content: 'You write short, warm blog newsletters. Tone: ' + $('Set Configuration Parameters').item.json.newsletterTone + '. Output clean markdown: a 2-sentence intro, then one bullet per post with the title as a link and a one-line teaser, then a single-sentence sign-off. No subject line, no placeholders.' }, { role: 'user', content: 'Write this week\\'s digest from these posts: ' + JSON.stringify($json.posts) } ] }) }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "typeVersion": 4.2
    },
    {
      "id": "extract-digest",
      "name": "Set Digest Markdown",
      "type": "n8n-nodes-base.set",
      "position": [
        1696,
        -64
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "out-md",
              "name": "digestMarkdown",
              "type": "string",
              "value": "={{ $json.choices[0].message.content }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "noop-skip",
      "name": "No New Posts Action",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1472,
        304
      ],
      "parameters": {},
      "typeVersion": 1
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "Check for New Posts": {
      "main": [
        [
          {
            "node": "Post AI Digest Request",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No New Posts Action",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Blog RSS Feed": {
      "main": [
        [
          {
            "node": "Filter Recent Posts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Recent Posts": {
      "main": [
        [
          {
            "node": "Check for New Posts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Weekly Triggered": {
      "main": [
        [
          {
            "node": "Set Configuration Parameters",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post AI Digest Request": {
      "main": [
        [
          {
            "node": "Set Digest Markdown",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Configuration Parameters": {
      "main": [
        [
          {
            "node": "Fetch Blog RSS Feed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}