This workflow corresponds to n8n.io template #10236 — we link there as the canonical source.
This workflow follows the Agent → Gmail 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 →
{
"id": "z301sXBDAZd8EDCw",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Send scheduled n8n release notes notifications to Gmail",
"tags": [
{
"id": "W3G9QjFn5zCWN18M",
"name": "Notifications",
"createdAt": "2025-10-27T20:32:25.385Z",
"updatedAt": "2025-10-27T20:32:25.385Z"
},
{
"id": "dF0HqEuaD5GnFCI0",
"name": "n8n",
"createdAt": "2025-10-27T20:32:30.037Z",
"updatedAt": "2025-10-27T20:32:30.037Z"
},
{
"id": "CF6Q37w8HHllwE7l",
"name": "gmail",
"createdAt": "2025-10-27T20:32:34.939Z",
"updatedAt": "2025-10-27T20:32:34.939Z"
}
],
"nodes": [
{
"id": "09d6bcf3-9cf2-40da-83b5-89833fe663d6",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
648,
224
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-5-mini",
"cachedResultName": "gpt-5-mini"
},
"options": {}
},
"typeVersion": 1.2
},
{
"id": "a3e60adf-ed32-4f6b-9903-39094c5697d3",
"name": "Structured Output Parser",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
776,
224
],
"parameters": {
"jsonSchemaExample": "{\n\t\"releaseBugFixes\": [\"\"],\n\t\"releaseFeatures\": [\"\"]\n}"
},
"typeVersion": 1.3
},
{
"id": "d3d79b32-6405-405a-864a-4953f824ca6b",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-256,
0
],
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 8
}
]
}
},
"executeOnce": false,
"notesInFlow": false,
"typeVersion": 1.2,
"alwaysOutputData": false
},
{
"id": "7a1ec69a-dc91-4365-9686-9d0b2a361736",
"name": "Extract HTML for updates",
"type": "n8n-nodes-base.html",
"position": [
192,
0
],
"parameters": {
"options": {},
"operation": "extractHtmlContent",
"extractionValues": {
"values": [
{
"key": "sections",
"cssSelector": "section",
"returnArray": true,
"returnValue": "html"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "160368b0-4fcd-4eca-b478-4154d9aa35c9",
"name": "Format Data and Filter based on Trigger",
"type": "n8n-nodes-base.code",
"position": [
416,
0
],
"parameters": {
"jsCode": "const cheerio = require('cheerio');\n\n// Get the array of section HTML strings\nconst allSections = $input.first().json.sections;\n\n// Get schedule trigger configuration\nconst scheduleParams = $(\"Schedule Trigger\").params;\nlet checkWindowHours = 24; // Default fallback\n\n// Calculate the time window based on schedule trigger settings\nif (scheduleParams?.rule?.interval?.[0]) {\n const interval = scheduleParams.rule.interval[0];\n const field = interval.field;\n \n if (field === 'days' && interval.daysInterval) {\n checkWindowHours = interval.daysInterval * 24;\n } else if (field === 'hours' && interval.hoursInterval) {\n checkWindowHours = interval.hoursInterval;\n } else if (field === 'minutes' && interval.minutesInterval) {\n checkWindowHours = (interval.minutesInterval / 60);\n } else if (field === 'seconds' && interval.secondsInterval) {\n checkWindowHours = (interval.secondsInterval / 3600);\n } else if (field === 'weeks' && interval.weeksInterval) {\n checkWindowHours = interval.weeksInterval * 7 * 24;\n } else if (field === 'months' && interval.monthsInterval) {\n checkWindowHours = interval.monthsInterval * 30 * 24;\n }\n}\n\nconsole.log(`Using time window of ${checkWindowHours} hours based on schedule trigger`);\n\n// Get current date/time\nconst now = DateTime.now();\n\nconst results = [];\n\n// Process each section HTML string\nallSections.forEach((sectionHtml, index) => {\n // Load this section's HTML with cheerio\n const $ = cheerio.load(sectionHtml);\n \n // Get the relative time element's datetime attribute\n const relativeTime = $('relative-time');\n if (relativeTime.length === 0) return;\n \n const dateTimeAttr = relativeTime.attr('datetime');\n if (!dateTimeAttr) return;\n \n // Parse the ISO datetime (format: \"2025-10-27T12:23:36Z\")\n const releaseDateTime = DateTime.fromISO(dateTimeAttr);\n \n if (!releaseDateTime.isValid) {\n console.log(`Failed to parse datetime: ${dateTimeAttr}`);\n return;\n }\n \n // Check if within the dynamic time window based on schedule trigger\n const diffInHours = now.diff(releaseDateTime, 'hours').hours;\n if (diffInHours > checkWindowHours || diffInHours < 0) return;\n \n // Extract releaseVersion from first h2\n const firstH2 = $('h2').first();\n const releaseVersion = firstH2.text().trim();\n \n // Format releaseDate\n const releaseDate = releaseDateTime.toFormat('d MMMM, yyyy HH:mm');\n \n // Extract releaseLink from div.markdown-body > h2 > a\n const markdownBody = $('div.markdown-body');\n \n const releaseLink2 = $('div.flex-1 span.f1 a.Link--primary').attr('href') || '';\n const releaseLink = releaseLink2 ? ('https://github.com/'+releaseLink2) :''\n \n // Extract bug fixes and features\n let releaseBugFixes = [];\n let releaseFeatures = [];\n \n if (markdownBody.length > 0) {\n markdownBody.find('h3').each((i, h3Element) => {\n const h3 = $(h3Element);\n const h3Text = h3.text().trim();\n \n // Find Bug Fixes\n if (h3Text === 'Bug Fixes' || h3Text.includes('Bug Fix')) {\n let nextEl = h3.next();\n // Look for next ul, but stop at next heading\n while (nextEl.length > 0 && !nextEl.is('ul')) {\n if (nextEl.is('h2, h3')) break;\n nextEl = nextEl.next();\n }\n if (nextEl.is('ul')) {\n nextEl.find('li').each((j, li) => {\n releaseBugFixes.push($(li).text().trim());\n });\n }\n }\n \n // Find Features\n if (h3Text === 'Features' || h3Text.includes('Feature')) {\n let nextEl = h3.next();\n // Look for next ul, but stop at next heading\n while (nextEl.length > 0 && !nextEl.is('ul')) {\n if (nextEl.is('h2, h3')) break;\n nextEl = nextEl.next();\n }\n if (nextEl.is('ul')) {\n nextEl.find('li').each((j, li) => {\n releaseFeatures.push($(li).text().trim());\n });\n }\n }\n });\n }\n \n results.push({\n releaseVersion,\n releaseDate,\n releaseLink,\n releaseBugFixes,\n releaseFeatures\n });\n});\n\n// Return results in n8n format\nreturn results.map(item => ({ json: item }));"
},
"typeVersion": 2
},
{
"id": "d60758f6-313d-4d95-a5a4-6f22df51f4d0",
"name": "Format Data",
"type": "n8n-nodes-base.set",
"position": [
992,
0
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "38260412-2d4d-4f9e-ab33-1839ea1e5b6a",
"name": "releaseVersion",
"type": "string",
"value": "={{ $('Format Data and Filter based on Trigger').item.json.releaseVersion }}"
},
{
"id": "601016bd-9724-4608-bd41-cd4127c21268",
"name": "releaseDate",
"type": "string",
"value": "={{ $('Format Data and Filter based on Trigger').item.json.releaseDate }}"
},
{
"id": "70fdeddb-fd07-439c-8ec8-a2b7b9bfc1d4",
"name": "releaseLink",
"type": "string",
"value": "={{ $('Format Data and Filter based on Trigger').item.json.releaseLink }}"
},
{
"id": "dda79d93-e36a-40b2-9874-5564f6d4336f",
"name": "output.releaseFeatures",
"type": "array",
"value": "={{ $json.output.releaseFeatures }}"
},
{
"id": "ae95cbf9-531e-4a3b-8d59-cb5162209d03",
"name": "output.releaseBugFixes",
"type": "array",
"value": "={{ $json.output.releaseBugFixes }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "796aa3f1-6f22-4583-b6cc-ace9616c3fe1",
"name": "Generate HTML template",
"type": "n8n-nodes-base.code",
"position": [
1216,
0
],
"parameters": {
"jsCode": "// Get the input data\nconst items = $input.all();\n\n// Start building the HTML\nlet html = `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>n8n Daily Update</title>\n <style>\n body {\n font-family: Arial, sans-serif;\n line-height: 1.6;\n color: #333;\n max-width: 800px;\n margin: 0 auto;\n padding: 20px;\n background-color: #f4f4f4;\n }\n .container {\n background-color: #ffffff;\n border-radius: 8px;\n padding: 30px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n .header {\n text-align: center;\n border-bottom: 3px solid #d62854;\n padding-bottom: 20px;\n margin-bottom: 30px;\n }\n .header h1 {\n color: #d62854;\n margin: 0;\n font-size: 28px;\n }\n .header p {\n color: #666;\n margin: 10px 0 0 0;\n }\n .release {\n margin-bottom: 40px;\n border-left: 4px solid #d62854;\n padding-left: 20px;\n }\n .release-header {\n margin-bottom: 15px;\n }\n .release-version {\n font-size: 22px;\n font-weight: bold;\n color: #333;\n margin: 0 0 5px 0;\n }\n .release-date {\n color: #666;\n font-size: 14px;\n margin: 0 0 10px 0;\n }\n .release-link {\n display: inline-block;\n color: #d62854;\n text-decoration: none;\n font-size: 14px;\n font-weight: 500;\n }\n .release-link:hover {\n text-decoration: underline;\n }\n .section {\n margin-top: 20px;\n }\n .section-title {\n font-size: 16px;\n font-weight: bold;\n color: #d62854;\n margin-bottom: 10px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n .items-list {\n margin: 0;\n padding-left: 20px;\n }\n .items-list li {\n margin-bottom: 10px;\n color: #555;\n }\n .no-items {\n color: #999;\n font-style: italic;\n }\n .footer {\n text-align: center;\n margin-top: 40px;\n padding-top: 20px;\n border-top: 1px solid #ddd;\n color: #666;\n font-size: 12px;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"header\">\n <h1>\ud83d\ude80 n8n Updates</h1>\n <p>Latest releases, features, and bug fixes</p>\n </div>\n`;\n\n// Loop through each release\nitems.forEach((item) => {\n const data = item.json;\n const version = data.releaseVersion || 'Unknown Version';\n const date = data.releaseDate || 'Unknown Date';\n const link = data.releaseLink || '#';\n const features = data.output?.releaseFeatures || [];\n const bugFixes = data.output?.releaseBugFixes || [];\n\n html += `\n <div class=\"release\">\n <div class=\"release-header\">\n <h2 class=\"release-version\">${version}</h2>\n <p class=\"release-date\">\ud83d\udcc5 ${date}</p>\n <a href=\"${link}\" class=\"release-link\" target=\"_blank\">View on GitHub \u2192</a>\n </div>\n `;\n\n // Add Features section\n html += `<div class=\"section\"><div class=\"section-title\">\ud83c\udf89 New Features</div>`;\n \n if (features.length > 0) {\n html += `<ul class=\"items-list\">`;\n features.forEach(feature => {\n html += `<li>${feature}</li>`;\n });\n html += `</ul>`;\n } else {\n html += `<p class=\"no-items\">No new features in this release</p>`;\n }\n html += `</div>`;\n\n // Add Bug Fixes section\n html += `<div class=\"section\"><div class=\"section-title\">\ud83d\udd27 Bug Fixes</div>`;\n \n if (bugFixes.length > 0) {\n html += `<ul class=\"items-list\">`;\n bugFixes.forEach(fix => {\n html += `<li>${fix}</li>`;\n });\n html += `</ul>`;\n } else {\n html += `<p class=\"no-items\">No bug fixes in this release</p>`;\n }\n html += `</div></div>`;\n});\n\n// Return the HTML\nreturn [{ json: { html } }];"
},
"typeVersion": 2
},
{
"id": "4d8a12ea-5ae3-4e4a-9e93-df5dc53cdb06",
"name": "Summarize n8n Update Data",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
640,
0
],
"parameters": {
"text": "=Give me a summary of the Release Bug Fixes and Release Features as a list of important releases. Include only the important ones, and summarize as much as possible. Use simple language.\n\n{releaseBugFixes: {{ $json.releaseBugFixes }},\nreleaseFeatures: {{ $json.releaseFeatures }}\n} ",
"options": {
"maxIterations": 3
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 3
},
{
"id": "12e67c90-bc13-458d-a45b-14ab5881d31c",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-688,
-352
],
"parameters": {
"width": 368,
"height": 528,
"content": "## n8n Release Notifications Workflow\n\n**Stay updated with the latest n8n releases automatically!**\n\n## What this workflow does:\n- Runs on a schedule (configurable)\n- Fetches latest release notes from n8n GitHub\n- Uses AI to summarize key features and bug fixes\n- Sends formatted email notifications via Gmail\n\n## Setup required:\n1. **Schedule Trigger** - Adjust frequency if needed\n2. **OpenAI credentials** - Add your API key or connect different LLM\n3. **Gmail credentials** - Connect your Google account\n4. **Recipient email** - Set the \"To\" address in the Gmail node"
},
"typeVersion": 1
},
{
"id": "be26a459-0049-46a8-b4a7-4efd9549a30c",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-296,
-128
],
"parameters": {
"color": 7,
"width": 176,
"height": 304,
"content": "### 1. Schedule Trigger\n\nSet your preferred frequency."
},
"typeVersion": 1
},
{
"id": "1baae255-a154-46bd-af66-fdaed8ad6d95",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-88,
-224
],
"parameters": {
"color": 7,
"width": 656,
"height": 400,
"content": "### 2. Get n8n release notes and filter\n\n- Get all release notes\n- Filters releases based on timeframe\n- Formats data\n\nNo configuration needed - it's automatic!"
},
"typeVersion": 1
},
{
"id": "9f097a51-1167-4c61-a17d-8c574140c0bd",
"name": "Get n8n release notes",
"type": "n8n-nodes-base.httpRequest",
"position": [
-32,
0
],
"parameters": {
"url": "https://github.com/n8n-io/n8n/releases",
"options": {}
},
"typeVersion": 4.2
},
{
"id": "a9dcc608-56f9-4e94-ab8a-2401c1675484",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
608,
-272
],
"parameters": {
"color": 7,
"width": 288,
"height": 640,
"content": "### AI Summarization\n\nOpenAI analyzes release notes and extracts:\n- Important bug fixes\n- New features\n\n**\u26a0\ufe0fSetup Required:**\nAdd your OpenAI API credentials here or connect a different LLM provider."
},
"typeVersion": 1
},
{
"id": "7d414dfc-9171-4bf2-9e79-64f9e52b637e",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
960,
-144
],
"parameters": {
"color": 7,
"width": 384,
"height": 304,
"content": "### Format for Email\n\nBuild an HTML template for email."
},
"typeVersion": 1
},
{
"id": "f1260b97-38b0-4791-baa4-08a4a4aad868",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
1392,
-224
],
"parameters": {
"color": 7,
"height": 384,
"content": "### Send Email\n\nSend via Gmail.\n\n**\u26a0\ufe0f Setup Required:**\n1. Add Gmail credentials\n2. Set recipient email address in the \"To\" field"
},
"typeVersion": 1
},
{
"id": "fafd7a5e-0e9a-49ec-b097-6019d068c1cd",
"name": "Send a message",
"type": "n8n-nodes-base.gmail",
"position": [
1456,
0
],
"parameters": {
"message": "={{ $json.html }}",
"options": {
"appendAttribution": false
},
"subject": "=n8n Updates - {{ $now.format('DDD') }}"
},
"typeVersion": 2.1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "0f73b185-10b8-4ab7-87a8-c441fd924d13",
"connections": {
"Format Data": {
"main": [
[
{
"node": "Generate HTML template",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Get n8n release notes",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "Summarize n8n Update Data",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Get n8n release notes": {
"main": [
[
{
"node": "Extract HTML for updates",
"type": "main",
"index": 0
}
]
]
},
"Generate HTML template": {
"main": [
[
{
"node": "Send a message",
"type": "main",
"index": 0
}
]
]
},
"Extract HTML for updates": {
"main": [
[
{
"node": "Format Data and Filter based on Trigger",
"type": "main",
"index": 0
}
]
]
},
"Structured Output Parser": {
"ai_outputParser": [
[
{
"node": "Summarize n8n Update Data",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Summarize n8n Update Data": {
"main": [
[
{
"node": "Format Data",
"type": "main",
"index": 0
}
]
]
},
"Format Data and Filter based on Trigger": {
"main": [
[
{
"node": "Summarize n8n Update Data",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow is perfect for n8n users and teams who want to stay up-to-date with the latest n8n releases without manually checking GitHub. Get AI-powered summaries of new features and bug fixes delivered straight to your inbox.
Source: https://n8n.io/workflows/10236/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This n8n automation workflow automates the creation, scripting, production, and posting of YouTube videos. It leverages AI (OpenAI), image generation (PIAPI), video rendering (Shotstack), and platform
Created by: Peyton Leveillee Last updated: October 2025
SEO Blog Article Generation Workflow. Uses outputParserStructured, httpRequest, agent, lmChatOpenAi. Scheduled trigger; 56 nodes.
This workflow was born out of a very real problem.
This workflow automates comprehensive real estate investment analysis by orchestrating specialized AI agents to evaluate property data, market trends, and financial metrics. Designed for real estate i