AutomationFlowsWeb Scraping › Transform Readwise Highlights Into Weekly Content Ideas with Gemini AI

Transform Readwise Highlights Into Weekly Content Ideas with Gemini AI

ByJulian Kaiser @jksr on n8n.io

This workflow is built for one core purpose: to maximize the return on your reading time. It turns your passive consumption of articles and highlights into an active system for generating original content and rediscovering valuable ideas you may have forgotten.

Cron / scheduled trigger★★★★☆ complexityAI-powered21 nodesHTTP RequestChain LlmOpenRouter Chat
Web Scraping Trigger: Cron / scheduled Nodes: 21 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Chainllm → HTTP Request 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
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "d658ca25-1a80-4f28-ac28-6b36b60d2ffa",
      "name": "Fetch Articles",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -672,
        -256
      ],
      "parameters": {
        "url": "https://readwise.io/api/v3/list",
        "options": {
          "pagination": {
            "pagination": {
              "nextURL": "={{ $response.body.nextPageCursor ? `https://readwise.io/api/v3/list?pageCursor=$response.body.nextPageCursor` : 'https://readwise.io/api/v3/list'}}",
              "paginationMode": "responseContainsNextURL",
              "requestInterval": 500,
              "completeExpression": "={{!$response.body.nextPageCursor }}",
              "paginationCompleteWhen": "other"
            }
          }
        },
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "updatedAfter",
              "value": "={{ $now.minus(7, 'days') }}"
            },
            {
              "name": "withHtmlContent",
              "value": "true"
            },
            {
              "name": "category",
              "value": "article"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "e9ab5e55-6500-4ffd-b19f-88921321d0b3",
      "name": "Split Article Results",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        -448,
        -256
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "results"
      },
      "typeVersion": 1
    },
    {
      "id": "564a1d51-de71-4d39-badd-bfcb0653c3c8",
      "name": "Fetch Highlights",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        0,
        -256
      ],
      "parameters": {
        "url": "=https://readwise.io/api/v3/list/",
        "options": {
          "pagination": {
            "pagination": {
              "nextURL": "={{ $response.body.nextPageCursor ? `https://readwise.io/api/v3/list?pageCursor=$response.body.nextPageCursor` : 'https://readwise.io/api/v3/list'}}",
              "paginationMode": "responseContainsNextURL",
              "requestInterval": 500,
              "completeExpression": "={{!$response.body.nextPageCursor }}",
              "paginationCompleteWhen": "other"
            }
          }
        },
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "category",
              "value": "=highlight"
            },
            {
              "name": "updatedAfter",
              "value": "={{ $now.minus(7, 'days') }}"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "4105eb45-90d4-4557-9465-3437247199e0",
      "name": "Split Highlights Results",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        224,
        -256
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "results"
      },
      "typeVersion": 1
    },
    {
      "id": "4b4b5b76-8c80-4845-ae40-c053a7ec0635",
      "name": "Merge Articles & Highlights",
      "type": "n8n-nodes-base.code",
      "position": [
        672,
        -256
      ],
      "parameters": {
        "jsCode": "const articles = $('Filter Articles >10% Read').all();\nconst highlights = $('Find Highlights for Article').all();\n\n  return articles.map(a => {\n    const article = a.json;\n    const matched_highlights = highlights\n      .filter(h => h.json.parent_id === article.id)\n      .map(h => h.json);\n\n    return {\n      json: {\n        title: article.title,\n        url: article.url,\n        original_url: article.source_url || article.url,\n        author: article.author,\n        summary: article.summary,\n        content: article.html_content,\n        reading_progress: article.reading_progress,\n        highlight_count: matched_highlights.length,\n        highlights: matched_highlights.map(h => ({\n          text: h.content || h.text,\n          note: h.notes || h.note\n        }))\n      }\n    };\n  });"
      },
      "typeVersion": 2
    },
    {
      "id": "55c72541-46c7-434b-93a2-f135586045c9",
      "name": "Prepare Prompt",
      "type": "n8n-nodes-base.code",
      "position": [
        896,
        -256
      ],
      "parameters": {
        "jsCode": "const articles = $input.all().map(item => item.json);\n\n// Build article content\n  const combinedContent = articles.map(article => {\n    let content = `## ${article.title}\\n`;\n    if (article.original_url) content += `**Original URL:** ${article.original_url}\\n`;\n    if (article.author) content += `**Author:** ${article.author}\\n`;\n    if (article.content) content += `**Summary:** ${article.content}\\n`;\n    content += `**Highlights:** ${article.highlight_count}\\n`;\n    content += `**Reading Progress:** ${Math.round(article.reading_progress * 100)}%\\n\\n`;\n\n    if (article.highlights && article.highlights.length > 0) {\n      content += `**Key Highlights:**\\n`;\n      article.highlights.forEach(highlight => {\n        content += `- \"${highlight.text}\"\\n`;\n        if (highlight.note) {\n          content += `  *Note: ${highlight.note}*\\n`;\n        }\n      });\n    }\n\n    content += `\\n---\\n\\n`;\n    return content;\n  }).join('');\n\n// Build the prompt with EXPLICIT formatting instructions\nconst prompt = `You are a reading analyst helping a tech consultant and AI engineering freelancer extract valuable insights from their weekly reading habits.\n\nAnalyze the following articles and highlights from the past week and create insights that would be valuable for:\n1. Professional development in tech consulting and AI engineering\n2. Content creation and thought leadership\n3. Business strategy and industry trends\n4. Technical knowledge and best practices\n\nFocus on creating actionable insights that could become:\n- LinkedIn posts about industry trends\n- Technical blog articles\n- Business insights for consulting\n- Learning priorities for skill development\n- Content ideas based on interesting findings\n\nWeekly reading data:\n${combinedContent}\n\nCRITICAL FORMATTING RULES:\n1. When referencing articles, ALWAYS use this exact markdown link format: [Article Title](URL)\n2. NEVER write bare URLs - always wrap them in markdown links\n3. Example: [The Majority AI View](https://www.anildash.com/2025/10/17/the-majority-ai-view/)\n4. For bullet points with links: \"- Read [Article Title](URL) for more details\"\n5. Use the ORIGINAL article URL (not Readwise URLs) in all links\n\nVALID markdown link examples:\n\u2705 [The Sprinter Developer](https://example.com/article)\n\u2705 Read more in [Ruby AI: Introducing Phoenix](https://example.com)\n\u2705 - [Article Title](https://example.com) discusses...\n\nINVALID examples (DO NOT USE):\n\u274c https://example.com (bare URL)\n\u274c Article Title: https://example.com (URL not in markdown format)\n\u274c [Article Title] - https://example.com (incorrect syntax)\n\nPlease provide your analysis in the following format:\n\n# Weekly Reading Insights\n\n## \ud83d\udcca Reading Pattern Analysis\n[Brief analysis of reading habits, topics covered, and engagement levels]\n\n## \ud83d\udd0d Key Themes & Trends\n[3-5 major themes or trends identified across the articles]\n\n## \ud83d\udca1 Top Insights & Takeaways\n[5-7 most valuable insights. When mentioning specific articles, use markdown links: [Article Title](URL)]\n\n## \ud83c\udfaf Content Creation Opportunities\n[4-6 specific content ideas. Reference articles using markdown links.]\n\n## \ud83d\udcda Most Valuable Articles\n[Top 3-4 articles. Format each as: [Article Title](URL) - Brief summary]\n\n## \ud83d\udd17 Notable Quotes & Highlights\n[Best quotes. Format as: \"Quote text\" - [Source Article](URL)]\n\n## \ud83d\udcc8 Learning & Development Priorities\n[Suggested areas for deeper learning based on reading patterns]\n\nRemember: Every article reference MUST be a properly formatted markdown link: [Title](URL)`;\n\nreturn [{\n  json: {\n    prompt: prompt,\n    articles_count: articles.length,\n    total_highlights: articles.reduce((sum, a) => sum + a.highlight_count, 0)\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "f3691550-22f6-4374-a07f-6652802fa017",
      "name": "Filter Articles >10% Read",
      "type": "n8n-nodes-base.filter",
      "position": [
        -224,
        -256
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "075acdec-fb32-4680-a807-09316a782e49",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.reading_progress }}",
              "rightValue": 0.1
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "bfa61775-01fb-4f89-bdb6-ec3df344c643",
      "name": "Find Highlights for Article",
      "type": "n8n-nodes-base.filter",
      "position": [
        448,
        -256
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "37db4560-d8c7-4a06-bf29-dbc1adde58c2",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.parent_id }}",
              "rightValue": "={{ $('Filter Articles >10% Read').item.json.id }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "f7a94120-67a5-4301-8e49-df99417a72df",
      "name": "Generate Weekly Insights",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1120,
        -256
      ],
      "parameters": {
        "text": "={{ $json.prompt }}",
        "batching": {},
        "promptType": "define"
      },
      "retryOnFail": true,
      "typeVersion": 1.7
    },
    {
      "id": "2d6c8414-6c61-4e3b-99b9-1f22f467242d",
      "name": "AI Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        1200,
        -32
      ],
      "parameters": {
        "model": "google/gemini-2.5-pro",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "51c9c8d4-64ff-4b46-bcea-58247340c540",
      "name": "Convert Insights to HTML",
      "type": "n8n-nodes-base.markdown",
      "position": [
        1472,
        -256
      ],
      "parameters": {
        "mode": "markdownToHtml",
        "options": {
          "tables": true,
          "simplifiedAutoLink": true,
          "openLinksInNewWindow": true
        },
        "markdown": "={{ $json.text }}"
      },
      "typeVersion": 1
    },
    {
      "id": "52d42ad7-9c68-4c78-aa47-3c950b6583c4",
      "name": "Format for Readwise Save API",
      "type": "n8n-nodes-base.code",
      "position": [
        1696,
        -256
      ],
      "parameters": {
        "jsCode": "  const insights = $input.first().json.data;\n  const timestamp = new Date().toISOString().split('T')[0];\n\n  return [{\n    json: {\n      url: `https://weekly-insights.local/${timestamp}`,\n      html: insights, // Just convert newlines to <br>\n      title: `Weekly Reading Insights - ${timestamp}`,\n      author: \"AI Reading Analyst\",\n      summary: \"AI-generated insights from weekly reading highlights\",\n      should_clean_html: true, // Let Readwise clean/format it\n      location: \"new\",\n      category: \"article\"\n    }\n  }];"
      },
      "typeVersion": 2
    },
    {
      "id": "8f07a901-ea39-415d-99e7-4bce43ba36c7",
      "name": "Save Insights to Readwise",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1920,
        -256
      ],
      "parameters": {
        "url": "https://readwise.io/api/v3/save/",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ $json }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "e362501c-ab5a-492d-a94b-679063d9d4f0",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -960,
        -704
      ],
      "parameters": {
        "color": 7,
        "width": 272,
        "height": 256,
        "content": "## \ud83d\udccc START\nThis workflow can be triggered in two ways:\n1. Manually by clicking 'Execute Workflow'.\n2. Automatically on a schedule (default is every Monday at 09:00).\nBoth triggers start the same process of fetching data from Readwise."
      },
      "typeVersion": 1
    },
    {
      "id": "995257c2-e0ad-42b5-9be7-d86c55630540",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -432,
        -704
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 256,
        "content": "## \ud83d\udccc FETCH READWISE DATA\nThese nodes connect to the Readwise API.\n- Fetch Articles: Gets all articles updated in the last 7 days.\n- Fetch Highlights: Gets all highlights updated in the last 7 days.\nEnsure your Readwise credentials are set up for all four nodes that access the API."
      },
      "typeVersion": 1
    },
    {
      "id": "b1b348fb-9deb-4d32-8bd7-3b73b793ba3c",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        -704
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 256,
        "content": "## \ud83d\udccc FILTER & MATCH DATA\nHere, we refine the data:\n1. We split the articles and highlights into individual items.\n2. We only keep articles where reading progress is over 10%.\n3. We then find and match all highlights that belong to those specific articles."
      },
      "typeVersion": 1
    },
    {
      "id": "87a101df-925e-4b81-8277-e1b3f681ced0",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        624,
        -704
      ],
      "parameters": {
        "color": 7,
        "width": 384,
        "height": 256,
        "content": "## \ud83d\udccc PREPARE AI PROMPT\nThis is the 'brain' of the operation.\n- Merge...: This node combines the filtered articles and their highlights into a clean data structure.\n- Prepare Prompt: This node assembles the data into a detailed prompt for.\n\n **CUSTOMIZE THIS**: Go into the Prepare Prompt node to change the AI's persona, the questions it answers, and the final output format to fit your needs!"
      },
      "typeVersion": 1
    },
    {
      "id": "cac3fd5f-1196-4dd4-82e2-d0e3d4254f5b",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1072,
        -704
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 256,
        "content": "## \ud83d\udccc GENERATE AI INSIGHTS\nThe prepared prompt is sent to the AI model connected here.\nThis workflow uses OpenRouter to run Google's Gemini 2.5 Pro model, but you can swap it with any supported LLM (like OpenAI or Anthropic).\nThe output will be a detailed analysis in markdown format."
      },
      "typeVersion": 1
    },
    {
      "id": "fb5fc2ae-d8f6-4f86-b926-ffc090789818",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1536,
        -704
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 256,
        "content": "## \ud83d\udccc SAVE INSIGHTS BACK TO READWISE\nThe final steps:\n1. Convert Insights to HTML: The AI's markdown response is converted into HTML suitable for Readwise.\n2. Format for Readwise...: The HTML is packaged into a JSON object that the Readwise /save API endpoint expects.\n3. Save Insights...: The final payload is sent to Readwise, creating a new article with your weekly summary."
      },
      "typeVersion": 1
    },
    {
      "id": "d5f335d3-8610-454d-aa0d-ad27b75ab59a",
      "name": "Monday - 09:00",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -896,
        -416
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 9 * * 1"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "0f971879-dc47-477a-9342-f7f102220953",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -896,
        -256
      ],
      "parameters": {},
      "typeVersion": 1
    }
  ],
  "connections": {
    "AI Model": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Weekly Insights",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Articles": {
      "main": [
        [
          {
            "node": "Split Article Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Monday - 09:00": {
      "main": [
        [
          {
            "node": "Fetch Articles",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Prompt": {
      "main": [
        [
          {
            "node": "Generate Weekly Insights",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Highlights": {
      "main": [
        [
          {
            "node": "Split Highlights Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Article Results": {
      "main": [
        [
          {
            "node": "Filter Articles >10% Read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert Insights to HTML": {
      "main": [
        [
          {
            "node": "Format for Readwise Save API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Weekly Insights": {
      "main": [
        [
          {
            "node": "Convert Insights to HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Highlights Results": {
      "main": [
        [
          {
            "node": "Find Highlights for Article",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Articles >10% Read": {
      "main": [
        [
          {
            "node": "Fetch Highlights",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Highlights for Article": {
      "main": [
        [
          {
            "node": "Merge Articles & Highlights",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Articles & Highlights": {
      "main": [
        [
          {
            "node": "Prepare Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format for Readwise Save API": {
      "main": [
        [
          {
            "node": "Save Insights to Readwise",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Fetch Articles",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

This workflow is built for one core purpose: to maximize the return on your reading time. It turns your passive consumption of articles and highlights into an active system for generating original content and rediscovering valuable ideas you may have forgotten.

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

More Web Scraping workflows → · Browse all categories →

Related workflows

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

Web Scraping

Animal advocates & campaigners who want a weekly briefing on animal-related bills with clear, actionable steps—no manual research needed.

OpenRouter Chat, HTTP Request, Information Extractor +3
Web Scraping

Automate your n8n community job board monitoring with this intelligent workflow that scrapes, analyzes, and delivers opportunities straight to your inbox. Perfect for freelancers, agencies, and develo

HTTP Request, Output Parser Structured, OpenRouter Chat +2
Web Scraping

Scraping Articles Dev.to Prod. Uses itemLists, stickyNote, nocoDb, scheduleTrigger. Scheduled trigger; 44 nodes.

Item Lists, Noco Db, HTTP Request +2
Web Scraping

Unlock the power of automation with the Automatically Generate Content and Post to Bluesky with LLM Workflow, an n8n-powered solution that uses Large Language Model (LLM) APIs to create engaging conte

HTTP Request, Groq Chat, Stop And Error +1
Web Scraping

Transform your customer support workflow with intelligent ticket classification. This automation leverages AI to automatically categorize incoming support tickets in Zoho Desk, reducing manual work an

OpenRouter Chat, HTTP Request, Chain Llm