Workflow: Stickynote Workflow
Integrations: code, compareDatasets, filter, merge, noOp, notion, scheduleTrigger, set, slack, splitInBatches, stickyNote, stopAndError, webflow

{"nodes": [{"id": "adb2d3bc-c6ab-4bb6-b954-61956ca2836d", "name": "Sticky Note", "type": "n8n-nodes-base.stickyNote", "position": [-1528.3572519550153, 3540], "parameters": {"width": 830.4857444594224, "height": 495.4835100729081, "content": "## Workflow installation\n* Add a \"slug\" text property to each blog post (this parameter will be synced with Webflow and will be used to determine if a post is new or already present in your Webflow collection)\n* Add a \"Sync to Webflow?\" checkbox to each blog post\n* Connect your accounts and run a test to fill Webflow nodes with the right fields\n\n[![image.png]({{ $env.WEBHOOK_URL }}]({{ $env.WEBHOOK_URL }}"}, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow."}, {"id": "a5a79fd3-7adb-4e56-8aa7-2fd0cfc22927", "name": "Get simple page data", "type": "n8n-nodes-base.notion", "position": [-80, 4520], "parameters": {"pageId": {"__rl": true, "mode": "id", "value": "={{ $json.id }}"}, "resource": "databasePage", "operation": "get"}, "credentials": {"notionApi": {"id": "rxtaEXgFPg96muhy", "name": "My Notion account"}}, "executeOnce": true, "typeVersion": 2.2, "notes": "This notion node performs automated tasks as part of the workflow."}, {"id": "dbb56719-e091-4475-94fb-430cd58ce8bb", "name": "Get all page data", "type": "n8n-nodes-base.notion", "position": [-120, 4840], "parameters": {"pageId": {"__rl": true, "mode": "id", "value": "={{ $json.id }}"}, "simple": false, "resource": "databasePage", "operation": "get"}, "credentials": {"notionApi": {"id": "rxtaEXgFPg96muhy", "name": "My Notion account"}}, "executeOnce": true, "typeVersion": 2.2, "notes": "This notion node performs automated tasks as part of the workflow."}, {"id": "af3fd27a-642e-4ec6-bc07-5d02076830e2", "name": "Take cover url", "type": "n8n-nodes-base.set", "position": [100, 4840], "parameters": {"options": {}, "assignments": {"assignments": [{"id": "7f9960fb-9898-4d1a-b4d9-29c95fb7c144", "name": "cover_url", "type": "string", "value": "={{ $json.cover.external.url }}"}]}}, "typeVersion": 3.3, "notes": "This set node performs automated tasks as part of the workflow."}, {"id": "5910292c-2548-4ca2-b7e4-304f99712e8d", "name": "Merge1", "type": "n8n-nodes-base.merge", "position": [320, 4640], "parameters": {"mode": "combine", "options": {}, "combinationMode": "mergeByPosition"}, "typeVersion": 2.1, "notes": "This merge node performs automated tasks as part of the workflow."}, {"id": "65c81d79-770c-48d4-97b9-f22328c22465", "name": "Data transporter1", "type": "n8n-nodes-base.noOp", "position": [3220, 4900], "parameters": {}, "typeVersion": 1, "notes": "This noOp node performs automated tasks as part of the workflow."}, {"id": "1bc81efb-d293-4c97-bcb8-e114de0e482c", "name": "Get all blog posts1", "type": "n8n-nodes-base.notion", "position": [-1220, 4640], "parameters": {"options": {}, "resource": "databasePage", "operation": "getAll", "returnAll": true, "databaseId": {"__rl": true, "mode": "list", "value": "4587b66c-d670-45b5-93f0-69ba1b0f3924", "cachedResultUrl": "{{ $env.WEBHOOK_URL }}", "cachedResultName": "My blog"}}, "credentials": {"notionApi": {"id": "rxtaEXgFPg96muhy", "name": "My Notion account"}}, "typeVersion": 2.2, "notes": "This notion node performs automated tasks as part of the workflow."}, {"id": "56392232-05c7-477f-911f-7713d6cfa25f", "name": "Is sync checked?1", "type": "n8n-nodes-base.filter", "position": [-940, 4640], "parameters": {"options": {}, "conditions": {"options": {"leftValue": "", "caseSensitive": true, "typeValidation": "strict"}, "combinator": "and", "conditions": [{"id": "461a5a59-f894-4dda-9233-175a1e228d23", "operator": {"type": "boolean", "operation": "true", "singleValue": true}, "leftValue": "={{ $json.property_sync_to_webflow }}", "rightValue": ""}]}}, "typeVersion": 2, "notes": "This filter node performs automated tasks as part of the workflow."}, {"id": "2a9fab27-612e-4eb9-935c-fd802f39c96e", "name": "For each blog post1", "type": "n8n-nodes-base.splitInBatches", "position": [-360, 4640], "parameters": {"options": {}}, "typeVersion": 3, "notes": "This splitInBatches node performs automated tasks as part of the workflow."}, {"id": "8f6d8e51-b92b-4780-b782-3f72203f40aa", "name": "Sticky Note17", "type": "n8n-nodes-base.stickyNote", "position": [540, 4720], "parameters": {"width": 777.880012347261, "height": 287.94399632670337, "content": "### \u2699\ufe0f Turn blocks into rich text\nThis is where the magic happens \u2014 Notion blocks are mapped and turned into their respective html version. Works with all the major rich text elements: headings 1, headings 2, headings 3, normal, bold and italic text, quotes, bulleted lists, numbered lists and images with captions."}, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow."}, {"id": "9592c56d-9bb2-433e-b49c-ec634e3d1db2", "name": "Sticky Note18", "type": "n8n-nodes-base.stickyNote", "position": [1980, 4420], "parameters": {"width": 218.00983675699544, "height": 394.8629861599825, "content": "### \u2705 Create a new post or update an existing one?\nThis node compares (by slug) your Notion post with all your Webflow posts and chooses whether to create a new one (in \"A only\" branch) or update an existing one (in \"different\" branch)."}, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow."}, {"id": "3ffb06d2-c1f1-4ce1-961f-8ece894d6cca", "name": "Create post1", "type": "n8n-nodes-base.webflow", "position": [2400, 4460], "parameters": {"siteId": "65a40576635069142ed11d7c", "fieldsUi": {"fieldValues": [{"fieldId": "name", "fieldValue": "={{ $json[\"name\"] }}"}, {"fieldId": "slug", "fieldValue": "={{ $json.property_slug }}"}, {"fieldId": "blog-post-richt-text", "fieldValue": "={{ $json.newRichText }}"}, {"fieldId": "_archived", "fieldValue": "false"}, {"fieldId": "_draft", "fieldValue": "true"}, {"fieldId": "blog-post-featured-image-photo", "fieldValue": "={{ $json.cover_url }}"}, {"fieldId": "blog-post-thumbnail-image-photo", "fieldValue": "={{ $json.cover_url }}"}]}, "operation": "create", "collectionId": "65a40577635069142ed11dd8", "authentication": "{{ $credentials.oAuth2 }}"}, "credentials": {"webflowOAuth2Api": {"id": "cGhEXKKL99szTUa1", "name": "Webflow account"}}, "retryOnFail": true, "typeVersion": 1, "notes": "This webflow node performs automated tasks as part of the workflow."}, {"id": "e6490f39-b420-488c-b407-948425615764", "name": "Sticky Note19", "type": "n8n-nodes-base.stickyNote", "position": [-140, 3960], "parameters": {"width": 233.87813121439967, "height": 389.3234455133497, "content": "### \ud83c\udf89 Success\nSend a success message where you want.\n\nYou can remove this node.\n\nNote: If you're on it, you may need to refresh the Webflow page."}, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow."}, {"id": "13568b0a-9665-4149-b848-2dc355b91126", "name": "Update slug on posts1", "type": "n8n-nodes-base.notion", "position": [2920, 4760], "parameters": {"pageId": {"__rl": true, "mode": "id", "value": "={{ $('Compare by slug1').item.json.different.id.inputA }}"}, "options": {}, "resource": "databasePage", "operation": "update", "propertiesUi": {"propertyValues": [{"key": "YOUR_CREDENTIAL_HERE", "textContent": "={{ $json.slug }}"}]}}, "credentials": {"notionApi": {"id": "rxtaEXgFPg96muhy", "name": "My Notion account"}}, "retryOnFail": true, "typeVersion": 2.2, "notes": "This notion node performs automated tasks as part of the workflow."}, {"id": "8574c1d2-491d-4bbb-bcc1-0bef64b321a2", "name": "Slug uniqueness checker and differentiator1", "type": "n8n-nodes-base.code", "notes": "Add a number to the slug if it's not unique", "position": [-660, 4640], "parameters": {"jsCode": "const data = $input.all().map(item => item.json)\nconst slugCount = {};\n\nreturn data.map(item => {\n  let slug = item.property_slug;\n  \n  if (slugCount[slug]) {\n    slugCount[slug] += 1;\n    slug = `${slug}-${slugCount[slug]}`;\n  } else {\n    slugCount[slug] = 1;\n  }\n  \n  item.property_slug = slug;\n  return item;\n});"}, "notesInFlow": true, "typeVersion": 2}, {"id": "21755856-9123-4acd-b343-3af878d665ad", "name": "Success message1", "type": "n8n-nodes-base.slack", "position": [-80, 4175], "parameters": {"text": "=[Notion to Webflow] \u2014 \"{{ $json.name }}\" successfully synced \ud83c\udf89", "select": "channel", "channelId": {"__rl": true, "mode": "list", "value": "C07719A0GF5", "cachedResultName": "general"}, "otherOptions": {}, "authentication": "{{ $credentials.oAuth2 }}"}, "credentials": {"slackOAuth2Api": {"id": "qY28oJXU3BH6OrP3", "name": "Desengineers Account"}}, "typeVersion": 2.2, "notes": "This slack node performs automated tasks as part of the workflow."}, {"id": "6c232d4a-464b-4d5a-992b-f649d955eb1e", "name": "Merge2", "type": "n8n-nodes-base.merge", "position": [2660, 4540], "parameters": {"mode": "combine", "options": {}, "combinationMode": "mergeByPosition"}, "typeVersion": 2.1, "notes": "This merge node performs automated tasks as part of the workflow."}, {"id": "6af0cab5-8f70-435f-a341-c22d157d9200", "name": "Compare by slug1", "type": "n8n-nodes-base.compareDatasets", "position": [2040, 4640], "parameters": {"options": {}, "mergeByFields": {"values": [{"field1": "property_slug", "field2": "slug"}]}}, "typeVersion": 2.3, "notes": "This compareDatasets node performs automated tasks as part of the workflow."}, {"id": "54a7dcf6-188e-4ca5-bc1e-3e76d5536236", "name": "Add slug to posts1", "type": "n8n-nodes-base.notion", "position": [2900, 4540], "parameters": {"pageId": {"__rl": true, "mode": "id", "value": "={{ $json.id }}"}, "options": {}, "resource": "databasePage", "operation": "update", "propertiesUi": {"propertyValues": [{"key": "YOUR_CREDENTIAL_HERE", "textContent": "={{ $json.slug }}"}]}}, "credentials": {"notionApi": {"id": "rxtaEXgFPg96muhy", "name": "My Notion account"}}, "retryOnFail": true, "typeVersion": 2.2, "notes": "This notion node performs automated tasks as part of the workflow."}, {"id": "f9a66b20-ce82-4f36-b145-283dadf97d34", "name": "Get all collection posts1", "type": "n8n-nodes-base.webflow", "position": [1720, 4780], "parameters": {"siteId": "65a40576635069142ed11d7c", "operation": "getAll", "returnAll": true, "collectionId": "65a40577635069142ed11dd8", "authentication": "{{ $credentials.oAuth2 }}"}, "credentials": {"webflowOAuth2Api": {"id": "cGhEXKKL99szTUa1", "name": "Webflow account"}}, "typeVersion": 1, "notes": "This webflow node performs automated tasks as part of the workflow."}, {"id": "c09f3782-12a1-4a91-945d-cd1ed14bfeb3", "name": "Data transporter, Notion posts to sync1", "type": "n8n-nodes-base.noOp", "position": [1720, 4480], "parameters": {}, "typeVersion": 1, "notes": "This noOp node performs automated tasks as part of the workflow."}, {"id": "9dc3ee15-4b4c-463c-a3b5-17b1dcb275da", "name": "Craft the rich text element1", "type": "n8n-nodes-base.code", "position": [1160, 4836], "parameters": {"jsCode": "const blocks = $input.all().map(item => item.json);\n\nlet newRichText = '';\nlet bulletedListItems = [];\nlet numberedListItems = [];\n\nblocks.forEach(block => {\n  if (block.type === 'bulleted_list_item') {\n    bulletedListItems.push(block.html);\n  } else if (block.type === 'numbered_list_item') {\n    numberedListItems.push(block.html);\n  } else {\n    if (bulletedListItems.length > 0) {\n      newRichText += `<ul>${bulletedListItems.join('')}</ul>`;\n      bulletedListItems = [];\n    }\n    if (numberedListItems.length > 0) {\n      newRichText += `<ol>${numberedListItems.join('')}</ol>`;\n      numberedListItems = [];\n    }\n    newRichText += block.html;\n  }\n});\n\nif (bulletedListItems.length > 0) {\n  newRichText += `<ul>${bulletedListItems.join('')}</ul>`;\n}\nif (numberedListItems.length > 0) {\n  newRichText += `<ol>${numberedListItems.join('')}</ol>`;\n}\n\nconst output = [{ newRichText }];\nreturn output;\n\n"}, "typeVersion": 2, "notes": "This code node performs automated tasks as part of the workflow."}, {"id": "e4ca0e5a-21bb-4d38-8448-8195b8994c12", "name": "Turn blocks into HTML1", "type": "n8n-nodes-base.code", "position": [860, 4840], "parameters": {"jsCode": "const blocks = $input.all().map(item => item.json);\nconst output = [];\n\nblocks.forEach(block => {\n  let html = '';\n  \n  switch (block.type) {\n    case 'heading_1':\n      html = block.heading_1.text.map(item => item.text.content).join(' ');\n      html = `<h1>${html}</h1>`;\n      break;\n    case 'heading_2':\n      html = block.heading_2.text.map(item => item.text.content).join(' ');\n      html = `<h2>${html}</h2>`;\n      break;\n    case 'heading_3':\n      html = block.heading_3.text.map(item => item.text.content).join(' ');\n      html = `<h3>${html}</h3>`;\n      break;\n    case 'paragraph':\n      html = `<p>${block.paragraph.text.map(item => {\n        let content = item.text.content.trim();\n        if (item.annotations.bold) content = `<b>${content}</b>`;\n        if (item.annotations.italic) content = `<i>${content}</i>`;\n        if (item.text.link) content = `<a href=\"${item.text.link.url}\">${content}</a>`;\n        return content;\n      }).join(' ') || '   '}</p>`; // the space inside the apostrophes is on purpose, otherwise Webflow will automatically delete the empty blocks\n      break;\n    case 'quote':\n      html = block.quote.text.map(item => item.text.content).join(' ');\n      html = `<blockquote>${html}</blockquote>`;\n      break;\n    case 'bulleted_list_item':\n      html = block.bulleted_list_item.text.map(item => item.text.content).join(' ');\n      html = `<li>${html}</li>`;\n      break;\n    case 'numbered_list_item':\n      html = block.numbered_list_item.text.map(item => item.text.content).join(' ');\n      html = `<li>${html}</li>`;\n      break;\n    case 'image':\n      const caption = block.image.caption.map(item => item.text.content).join(' ');\n      html = `<figure><img src=\"${block.image.file.url}\" alt=\"${caption}\" /><figcaption>${caption}</figcaption></figure>`;\n      break;\n    case 'code':\n      const codeContent = block.code.text.map(item => item.text.content).join('\\n')\n      html = `<pre><code>${codeContent}</code></pre>`\n      break\n    default:\n      html = block.content ? `<div>${block.content}</div>` : '';\n  }\n\n  if (html) {\n    output.push({\n      block_id: block.id,\n      type: block.type,\n      html\n    });\n  }\n});\n\nreturn output;\n"}, "typeVersion": 2, "notes": "This code node performs automated tasks as part of the workflow."}, {"id": "719f5116-5e60-488c-81c2-d55cea2e2646", "name": "Get blocks1", "type": "n8n-nodes-base.notion", "position": [580, 4837], "parameters": {"blockId": {"__rl": true, "mode": "id", "value": "={{ $json.id }}"}, "resource": "block", "operation": "getAll", "returnAll": true, "simplifyOutput": false}, "credentials": {"notionApi": {"id": "rxtaEXgFPg96muhy", "name": "My Notion account"}}, "typeVersion": 2.2, "notes": "This notion node performs automated tasks as part of the workflow."}, {"id": "23f88f9c-ef4a-4158-bff5-728e2cf0383a", "name": "Update in \"Blog Posts\"", "type": "n8n-nodes-base.webflow", "maxTries": 3, "position": [2660, 4780], "parameters": {"itemId": "={{ $json.webflow_item_id }}", "siteId": "65a40576635069142ed11d7c", "fieldsUi": {"fieldValues": [{"fieldId": "_draft", "fieldValue": "true"}, {"fieldId": "_archived", "fieldValue": "false"}, {"fieldId": "name", "fieldValue": "={{ $json.name }}"}, {"fieldId": "slug", "fieldValue": "={{ $json.property_slug }}"}, {"fieldId": "blog-post-richt-text", "fieldValue": "={{ $json.newRichText }}"}, {"fieldId": "blog-post-featured-image-photo", "fieldValue": "={{ $json.cover_url }}"}, {"fieldId": "blog-post-thumbnail-image-photo", "fieldValue": "={{ $json.cover_url }}"}]}, "operation": "update", "collectionId": "65a40577635069142ed11dd8", "authentication": "{{ $credentials.oAuth2 }}"}, "credentials": {"webflowOAuth2Api": {"id": "cGhEXKKL99szTUa1", "name": "Webflow account"}}, "retryOnFail": true, "typeVersion": 1, "alwaysOutputData": false, "notes": "This webflow node performs automated tasks as part of the workflow."}, {"id": "6db40a4d-4acd-40f3-8830-f17e00678e39", "name": "Add Webflow item id to Notion data", "type": "n8n-nodes-base.code", "position": [2400, 4760], "parameters": {"mode": "runOnceForEachItem", "jsCode": "const compareResult = $json\nconst notionData = $('Final Notion post data').item.json\n\nconst output = {\n  ...notionData, // spread notion data\n  webflow_item_id: compareResult.different._id.inputB // add the webflow item id\n}\n\nreturn output"}, "typeVersion": 2, "notes": "This code node performs automated tasks as part of the workflow."}, {"id": "49e3d52c-a95a-4ac0-ae6a-69e4a722a628", "name": "Final Notion post data", "type": "n8n-nodes-base.merge", "position": [1380, 4640], "parameters": {"mode": "combine", "options": {}, "combinationMode": "mergeByPosition"}, "typeVersion": 2.1, "notes": "This merge node performs automated tasks as part of the workflow."}, {"id": "23755e8c-0012-4a72-ad9e-f450ceca1de4", "name": "Sticky Note1", "type": "n8n-nodes-base.stickyNote", "position": [-146, 4720], "parameters": {"width": 366.7438380520149, "height": 282.04364735085795, "content": "### No wastes\nThese nodes extract the cover image url of the Notion page to make it easy for you to use it in the collection fields."}, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow."}, {"id": "cb16a61b-73bc-491b-b4ce-b4dc5a5f21fc", "name": "Schedule Trigger", "type": "n8n-nodes-base.scheduleTrigger", "position": [-1480, 4640], "parameters": {"rule": {"interval": [{}]}}, "typeVersion": 1.2, "notes": "This scheduleTrigger node performs automated tasks as part of the workflow."}, {"id": "error-5939f432", "name": "Error Handler", "type": "n8n-nodes-base.stopAndError", "typeVersion": 1, "position": [1000, 400], "parameters": {"message": "Workflow execution error", "options": {}}}], "connections": {"21755856-9123-4acd-b343-3af878d665ad": {"main": [[{"node": "error-handler-21755856-9123-4acd-b343-3af878d665ad-1541f629", "type": "main", "index": 0}]]}}, "name": "Stickynote Workflow", "settings": {"executionOrder": "v1", "saveManualExecutions": true, "callerPolicy": "workflowsFromSameOwner", "errorWorkflow": null, "timezone": "UTC", "executionTimeout": 3600, "maxExecutions": 1000, "retryOnFail": true, "retryCount": 3, "retryDelay": 1000}, "description": "Automated workflow: Stickynote Workflow. This workflow integrates 13 different services: stickyNote, filter, code, scheduleTrigger, merge. It contains 30 nodes and follows best practices for error handling and security.", "meta": {"instanceId": "workflow-9b907a68", "versionId": "1.0.0", "createdAt": "2025-09-29T07:07:42.530720", "updatedAt": "2025-09-29T07:07:42.530735", "owner": "n8n-user", "license": "MIT", "category": "automation", "status": "active", "priority": "high", "environment": "production"}, "tags": ["automation", "n8n", "production-ready", "excellent", "optimized"], "notes": "Excellent quality workflow: Stickynote Workflow. This workflow has been optimized for production use with comprehensive error handling, security, and documentation."}