{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "e631d7fb-dbe8-4ce2-ad9c-27149bcae749",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        416,
        1696
      ],
      "parameters": {
        "width": 576,
        "height": 544,
        "content": "## Daily AI News Digest\n\n### How it works\n1. A schedule trigger runs every morning at your chosen time\n2. RSS Feed nodes pull latest articles from your configured news sources\n3. A Code node merges and deduplicates the articles\n4. Google Gemini summarizes each article and assigns an importance score (1-10)\n5. Another Code node builds a formatted daily digest sorted by importance\n6. The digest is posted to Slack as your morning briefing\n7. A copy goes out via Gmail for people who prefer email\n\n### Setup steps\n1. Add your RSS feed URLs in each RSS Feed Read node\n2. Connect Google Gemini API credentials (free tier)\n3. Connect Slack and pick the channel for daily posts\n4. Connect Gmail and set the recipient list\n5. Adjust the schedule time to match your morning routine\n\n### Customization\n- Add more RSS Feed nodes for additional sources\n- Change the importance scoring criteria in the AI prompt\n- Filter out articles below a certain score in the Code node"
      },
      "typeVersion": 1
    },
    {
      "id": "6429f1dc-4610-4d4b-baee-83df5f7c1188",
      "name": "Note - Collection",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1008,
        1696
      ],
      "parameters": {
        "color": 7,
        "width": 520,
        "height": 500,
        "content": "## Feed collection\nPulls articles from multiple RSS sources and merges them."
      },
      "typeVersion": 1
    },
    {
      "id": "4c299734-dbc8-43eb-b496-131085e904bf",
      "name": "Note - AI Summary",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1552,
        1696
      ],
      "parameters": {
        "color": 7,
        "width": 520,
        "height": 508,
        "content": "## AI summarization\nGemini reads each article and creates a scored summary."
      },
      "typeVersion": 1
    },
    {
      "id": "151082d3-4c0b-4aa7-b73a-875d1c7d305a",
      "name": "Note - Delivery",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2096,
        1696
      ],
      "parameters": {
        "color": 7,
        "width": 428,
        "height": 500,
        "content": "## Digest delivery\nFormats the digest and delivers via Slack and Gmail."
      },
      "typeVersion": 1
    },
    {
      "id": "3192de6a-a0ae-4b8a-bd6c-1660ea9b4121",
      "name": "Morning Schedule",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        1040,
        1904
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * 1-5"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "566d87bf-df76-4fb7-979a-c0f1dfda1d8a",
      "name": "Tech News Feed",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        1296,
        1808
      ],
      "parameters": {
        "url": "https://feeds.arstechnica.com/arstechnica/technology-lab",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "c34c2132-0606-4b78-a49c-3a2bc6d93a48",
      "name": "Hacker News Feed",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        1296,
        2000
      ],
      "parameters": {
        "url": "https://hnrss.org/frontpage",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "ecdbbee0-e35d-488a-a740-021abbfa1f9c",
      "name": "Merge and Deduplicate",
      "type": "n8n-nodes-base.code",
      "position": [
        1616,
        1904
      ],
      "parameters": {
        "jsCode": "// Merge and deduplicate articles from multiple RSS feeds\nconst techItems = $('Tech News Feed').all();\nconst hnItems = $('Hacker News Feed').all();\n\nconst allArticles = [];\nconst seenUrls = new Set();\n\nconst processItems = (items, source) => {\n  for (const item of items.slice(0, 10)) {\n    const url = item.json.link || item.json.guid || '';\n    if (url && !seenUrls.has(url)) {\n      seenUrls.add(url);\n      allArticles.push({\n        title: item.json.title || 'Untitled',\n        url,\n        description: (item.json.contentSnippet || item.json.description || '').substring(0, 500),\n        pubDate: item.json.pubDate || item.json.isoDate || '',\n        source\n      });\n    }\n  }\n};\n\nprocessItems(techItems, 'Ars Technica');\nprocessItems(hnItems, 'Hacker News');\n\n// Sort by date, newest first\nallArticles.sort((a, b) => new Date(b.pubDate) - new Date(a.pubDate));\n\nreturn [{ json: { articles: allArticles.slice(0, 15), count: allArticles.length, fetchedAt: new Date().toISOString() } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "08c9895e-990c-4dc3-8406-9898f1e595b6",
      "name": "Summarize and Score",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1792,
        1904
      ],
      "parameters": {},
      "typeVersion": 1.4
    },
    {
      "id": "f62c1dd3-311c-4c59-a36f-def2cb136d85",
      "name": "Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1792,
        2080
      ],
      "parameters": {
        "options": {
          "temperature": 0.3
        },
        "modelName": "models/gemini-1.5-flash"
      },
      "typeVersion": 1
    },
    {
      "id": "140bb95a-5122-49b3-8546-9a93c9a43530",
      "name": "Build Digest",
      "type": "n8n-nodes-base.code",
      "position": [
        2128,
        1904
      ],
      "parameters": {
        "jsCode": "// Build the formatted daily digest\nconst aiResponse = $input.first().json.text || '';\nconst articles = $('Merge and Deduplicate').first().json.articles;\nlet scored = [];\n\ntry {\n  const match = aiResponse.match(/\\[[\\s\\S]*\\]/);\n  if (match) scored = JSON.parse(match[0]);\n} catch (e) {\n  scored = articles.map((a, i) => ({\n    index: i + 1,\n    title: a.title,\n    summary: a.description.substring(0, 100),\n    score: 5,\n    category: 'other'\n  }));\n}\n\n// Sort by score descending\nscored.sort((a, b) => b.score - a.score);\n\n// Build Slack-formatted digest\nconst today = new Date().toISOString().split('T')[0];\nconst topStories = scored.filter(s => s.score >= 7);\nconst otherStories = scored.filter(s => s.score < 7);\n\nlet slackText = `\ud83d\udcf0 *Daily News Digest \u2014 ${today}*\\n\\n`;\n\nif (topStories.length > 0) {\n  slackText += `*\ud83d\udd25 Top Stories*\\n`;\n  topStories.forEach(s => {\n    const article = articles[s.index - 1];\n    slackText += `\u2022 *${s.title}* (\u2b50 ${s.score}/10)\\n  ${s.summary}\\n  ${article ? article.url : ''}\\n\\n`;\n  });\n}\n\nif (otherStories.length > 0) {\n  slackText += `*\ud83d\udccb Other News*\\n`;\n  otherStories.forEach(s => {\n    slackText += `\u2022 ${s.title} (${s.score}/10) \u2014 ${s.summary}\\n`;\n  });\n}\n\n// Build email HTML\nlet emailBody = `Daily News Digest \u2014 ${today}\\n\\n`;\nscored.forEach(s => {\n  const article = articles[s.index - 1];\n  emailBody += `[${s.score}/10] ${s.title}\\n${s.summary}\\n${article ? article.url : ''}\\n\\n`;\n});\n\nreturn [{\n  json: {\n    slackText,\n    emailBody,\n    date: today,\n    totalArticles: scored.length,\n    topStoriesCount: topStories.length\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "ffe915dc-c221-4934-bde9-ee8add47ad9c",
      "name": "Post to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        2336,
        1808
      ],
      "parameters": {
        "text": "={{ $json.slackText }}",
        "otherOptions": {}
      },
      "typeVersion": 2.2
    },
    {
      "id": "acce60cf-382f-4789-b37c-94a9665c3cb7",
      "name": "Email Digest",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2336,
        2016
      ],
      "parameters": {
        "message": "={{ $json.emailBody }}",
        "options": {},
        "subject": "=\ud83d\udcf0 Daily News Digest \u2014 {{ $json.date }} ({{ $json.topStoriesCount }} top stories)"
      },
      "typeVersion": 2.1
    }
  ],
  "connections": {
    "Build Digest": {
      "main": [
        [
          {
            "node": "Post to Slack",
            "type": "main",
            "index": 0
          },
          {
            "node": "Email Digest",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tech News Feed": {
      "main": [
        [
          {
            "node": "Merge and Deduplicate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hacker News Feed": {
      "main": [
        [
          {
            "node": "Merge and Deduplicate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Morning Schedule": {
      "main": [
        [
          {
            "node": "Tech News Feed",
            "type": "main",
            "index": 0
          },
          {
            "node": "Hacker News Feed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Summarize and Score",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Summarize and Score": {
      "main": [
        [
          {
            "node": "Build Digest",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge and Deduplicate": {
      "main": [
        [
          {
            "node": "Summarize and Score",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}