{"workflow":{"id":13505,"name":"Automate daily standups using Slack, Notion, and Redis","views":77,"recentViews":1,"totalViews":77,"createdAt":"2026-02-19T04:37:53.236Z","description":"# Run automated daily standups using Slack, Notion, and Redis\n\n## 📌 Overview\n\nThis workflow fully automates your team's daily standup process using **Slack** for communication, **Notion** for structured data storage, and **Redis** for real-time session management.\n\nIt automatically sends standup questions to active team members, collects and stores their responses, manages conversation sessions, and generates structured summary reports for managers.\n\nMorning and evening standups run on schedule without manual intervention. Redis ensures fast and reliable session tracking, prevents duplicate standups, and maintains conversation state. All responses are securely stored in Notion for long-term reporting and tracking.\n\nThis workflow eliminates manual follow-ups, improves reporting consistency, and gives managers full visibility into team progress, blockers, and attendance.\n\n---\n\n## ⚙️ How it works\n\nThis workflow runs automatically based on configured schedules.\n\n### Morning standup\n\n- Fetches active team members from the Notion database  \n- Creates standup sessions in Redis  \n- Sends standup questions to each team member via Slack direct message  \n- Stores responses in Notion  \n- Tracks session state using Redis  \n\n### Automated reports\n\nThe workflow automatically generates:\n\n- Morning summary report showing attendance, responses, and blockers  \n- Evening summary report showing accomplishments, completion status, and help requests  \n\nBoth reports are automatically sent to the Slack admin channel.\n\nRedis ensures session tracking and prevents duplicate standups.\n\n---\n\n## 🛠 Setup steps\n\n1. Import this workflow into n8n  \n2. Connect your Slack credentials  \n3. Connect your Notion credentials  \n4. Connect your Redis credentials  \n5. Configure your Notion database IDs  \n6. Configure your Slack admin channel ID  \n7. Activate the workflow  \n\nThe workflow will run automatically based on the configured schedule.\n\n---\n\n## 🚀 Features\n\n### Automated standup management\n\n- Automatically sends standup questions  \n- Tracks team responses  \n- Stores responses securely in Notion  \n- Prevents duplicate standup sessions  \n\n### Automated reporting\n\n- Attendance tracking  \n- Task completion tracking  \n- Blocker detection  \n- Missing response detection  \n- Automatic Slack summary reports  \n\n---\n\n## 📋 Requirements\n\nYou need the following accounts:\n\n- n8n  \n- Slack  \n- Notion  \n- Redis  \n\n---\n\n## 🎯 Benefits\n\n- Fully automated standup system  \n- No manual follow-ups required  \n- Automatic attendance tracking  \n- Identifies blockers early  \n- Improves team visibility  \n- Saves management time  \n\n---\n\n## 👨‍💻 Author\n\n**BytezTech Pvt Ltd**\n\n---","workflow":{"meta":{"instanceId":"01d5a2fc10ab8549ddb03f83f7ba51316ff6e8d41eb184a858a745f93cf019f4"},"nodes":[{"id":"6f110ebd-9f44-4f0a-9227-bae4470cd24c","name":"📋 Template Overview","type":"n8n-nodes-base.stickyNote","position":[-8368,1184],"parameters":{"width":680,"height":520,"content":"# Automated daily standup system with Slack, Notion and Redis\n\n## How it works\nThis workflow automates daily standups for your team across two sessions — morning and evening — using Slack as the interface, Notion as the data store, and Redis for real-time session state management.\n\n**Morning standup (Mon–Sat, 9:40 AM IST)**\nThe bot messages each active team member on Slack asking 4 questions: how they're feeling, what they plan to work on, any blockers, and which tickets/tasks. Responses are saved to Notion's `Daily_Standups` database. At 10:10 AM a summary is posted to the admin Slack channel.\n\n**Evening standup (Mon–Sat, 6:00 PM IST)**\nThe bot asks 3 questions: what was completed, whether help is needed tomorrow, and whether planned tasks were finished. Results are saved to `Daily_Standups_Afternoon`. A summary is posted at 6:30 PM.\n\n**Session management**\nRedis caches active sessions (TTL: 8h morning / 3h evening) so the bot can track where each user is in the conversation. Notion serves as the persistent fallback if Redis expires.\n\n## Setup steps\n1. Add your **Notion API** credentials (connect to `Team_Members`, `Daily_Standups`, `Daily_Standups_Afternoon`, `Conversation_State`, `Conversation_State_Afternoon`, `Blockers_Tracking` databases)\n2. Add your **Slack Bot** credentials and invite the bot to your workspace DMs\n3. Add your **Redis** credentials\n4. Ensure the `Team_Members` Notion database has `Slack_User_ID`, `Developer_ID`, `Active_Status`, and `Daily_Standups` (checkbox) fields\n5. Activate all three workflows: Morning Initiator, Evening Initiator, and the main Slack Handler"},"typeVersion":1},{"id":"367c6c50-f925-4e84-92a8-de0d31e5df8d","name":"🌙 Evening Summary Overview","type":"n8n-nodes-base.stickyNote","position":[-1008,1376],"parameters":{"color":6,"width":404,"height":572,"content":"# 🌙 Evening Standup Summary\n\n## How it works\n1. Triggers Mon–Sat at 6:30 PM IST\n2. Fetches active members from `Team_Members` Notion DB\n3. Fetches today's evening standups from `Daily_Standups_Afternoon` DB\n4. Merges data, builds summary, sends to admin Slack channel\n\n## Setup steps\n1. Connect your Notion integration and set correct DB IDs\n2. Connect Slack bot (SlackBot Chintanbhai)\n3. Confirm Slack channel ID `C07PSV73SK0` is correct\n4. Activate the workflow"},"typeVersion":1},{"id":"73ac0ac6-c917-4de0-9ac5-16ff881cabe5","name":"Trigger Group Note","type":"n8n-nodes-base.stickyNote","position":[-496,1488],"parameters":{"color":7,"width":260,"height":320,"content":"## ⏰ Trigger\nFires Mon–Sat at 6:30 PM IST (`30 18 * * 1-6`). Kicks off both Notion fetches in parallel."},"typeVersion":1},{"id":"f4d8740c-1fd8-4e8c-9da4-8e9ab9fbc2db","name":"Fetch Data Group Note","type":"n8n-nodes-base.stickyNote","position":[-208,1328],"parameters":{"color":7,"width":292,"height":596,"content":"## 📋 Fetch Data\nFetches active members (`Team_Members`) and today's responded evening standups (`Daily_Standups_Afternoon`) from Notion in parallel."},"typeVersion":1},{"id":"d0c3e15f-b77c-4e65-a492-8891574f9724","name":"Merge Build Group Note","type":"n8n-nodes-base.stickyNote","position":[144,1488],"parameters":{"color":7,"width":424,"height":344,"content":"## 🔀 Merge & Build\nMerges both datasets, calculates response rate, missing members, help requests, task completion, and formats the Slack message."},"typeVersion":1},{"id":"876b6513-75a0-4778-960b-a106c6665ec4","name":"Send Slack Group Note","type":"n8n-nodes-base.stickyNote","position":[592,1488],"parameters":{"color":7,"width":320,"height":336,"content":"## 📤 Send to Slack\nPosts the formatted evening summary to the admin Slack channel via SlackBot Chintanbhai."},"typeVersion":1},{"id":"71ef2aec-3f18-4c5b-8a17-e7ae01cbf425","name":"Fetch Active Members","type":"n8n-nodes-base.notion","position":[-112,1728],"parameters":{"filters":{"conditions":[{"key":"Active_Status|status","condition":"equals","statusValue":"Active"},{"key":"Daily_Standups|checkbox","condition":"equals","checkboxValue":true}]},"options":{},"resource":"databasePage","matchType":"allFilters","operation":"getAll","returnAll":true,"databaseId":{"__rl":true,"mode":"list","value":"2d4da36d-2b3d-80ba-931c-fa5646433363","cachedResultUrl":"https://www.notion.so/2d4da36d2b3d80ba931cfa5646433363","cachedResultName":"Team_Members"},"filterType":"manual"},"typeVersion":2.2},{"id":"598c75cc-04ad-4e38-b6ac-edafe14d0383","name":"Merge Data","type":"n8n-nodes-base.merge","position":[160,1632],"parameters":{},"typeVersion":3},{"id":"06b8f6de-7298-421a-89ed-04bbbf00b967","name":"Fetch Evening Standups","type":"n8n-nodes-base.notion","position":[-112,1536],"parameters":{"filters":{"conditions":[{"key":"Responded|checkbox","condition":"equals","checkboxValue":true},{"key":"Date|date","date":"={{ $now.setZone('Asia/Kolkata').toFormat('yyyy-MM-dd') }}","condition":"equals"}]},"options":{},"resource":"databasePage","matchType":"allFilters","operation":"getAll","returnAll":true,"databaseId":{"__rl":true,"mode":"list","value":"2d4da36d-2b3d-8089-9e59-f645221ee1b7","cachedResultUrl":"https://www.notion.so/2d4da36d2b3d80899e59f645221ee1b7","cachedResultName":"Daily_Standups_Afternoon"},"filterType":"manual"},"typeVersion":2.2},{"id":"c41a3b62-1eea-42d8-a350-1e1cc7d7f424","name":"Evening schedule trigger","type":"n8n-nodes-base.scheduleTrigger","position":[-416,1632],"parameters":{"rule":{"interval":[{"field":"cronExpression","expression":"30 18 * * 1-6"}]}},"typeVersion":1.2},{"id":"9de24fc0-0075-4746-9b2d-269adbb48fbc","name":"Build evening summary message","type":"n8n-nodes-base.code","position":[416,1632],"parameters":{"jsCode":"// ============================================\n// BUILD EVENING STANDUP SUMMARY\n// ============================================\n\nconst standups = $('Fetch Evening Standups').all();\nconst activeMembers = $('Fetch Active Members').all();\n\nconst now = $now.setZone('Asia/Kolkata');\nconst today = now.toFormat('EEEE, MMMM d, yyyy');\nconst currentTime = now.toFormat('h:mm a');\n\nconsole.log('=== EVENING SUMMARY ===');\nconsole.log('Date:', today);\nconsole.log('Time:', currentTime);\nconsole.log('Active Members:', activeMembers.length);\nconsole.log('Standups Received:', standups.length);\n\n// Calculate statistics\nconst totalActive = activeMembers.length;\nconst totalResponded = standups.length;\nconst responseRate = totalActive > 0 ? ((totalResponded / totalActive) * 100).toFixed(1) : 0;\n\n// Find missing members\nconst respondedIds = new Set(standups.map(s => {\n  const devId = s.json.property_developer_id || s.json.Developer_ID || '';\n  return devId;\n}));\n\nconst missingMembers = activeMembers\n  .filter(m => {\n    const devId = m.json.property_developer_id || m.json.Developer_ID || '';\n    return !respondedIds.has(devId);\n  })\n  .map(m => m.json.property_full_name || m.json.Full_Name || 'Unknown');\n\nconsole.log('Missing Members:', missingMembers);\n\n// Build message header\nlet message = `🌙 *Evening Standup Summary*\\n`;\nmessage += `📅 ${today}\\n`;\nmessage += `━━━━━━━━━━━━━━━━━━\\n\\n`;\n\n// Response statistics\nmessage += `📈 *Response Statistics*\\n`;\nmessage += `✅ Responded: ${totalResponded}/${totalActive} (${responseRate}%)\\n`;\nif (missingMembers.length > 0) {\n  message += `❌ Missing: ${missingMembers.length}\\n`;\n}\nmessage += `\\n`;\n\n// Missing responses\nif (missingMembers.length > 0) {\n  message += `⚠️ *Missing Responses:*\\n`;\n  missingMembers.forEach(name => {\n    message += `   • ${name}\\n`;\n  });\n  message += `\\n`;\n}\n\n// Help needed section\nconst needHelp = standups.filter(s => {\n  const help = s.json.property_help_needed || s.json.Help_Needed || '';\n  const noHelpPatterns = ['no', 'none', 'n/a', 'na', 'no help needed', 'not needed', 'nope'];\n  const helpLower = help.toLowerCase().trim();\n  return help.trim().length > 0 && \n         !noHelpPatterns.some(pattern => helpLower === pattern || helpLower.includes(pattern));\n});\n\nconsole.log('Help Needed Count:', needHelp.length);\n\nif (needHelp.length > 0) {\n  message += `🆘 *Help Requested (${needHelp.length}):*\\n`;\n  needHelp.forEach(s => {\n    const devId = s.json.property_developer_id || s.json.Developer_ID;\n    const member = activeMembers.find(m => {\n      const memberDevId = m.json.property_developer_id || m.json.Developer_ID;\n      return memberDevId === devId;\n    });\n    const name = member ? (member.json.property_full_name || member.json.Full_Name) : devId;\n    const help = s.json.property_help_needed || s.json.Help_Needed || '';\n    const helpText = help.substring(0, 100);\n    message += `\\n👤 *${name}*\\n`;\n    message += `   ${helpText}${help.length > 100 ? '...' : ''}\\n`;\n  });\n  message += `\\n`;\n} else {\n  message += `✅ *No Help Requested*\\n\\n`;\n}\n\n// Task completion status\nconst completed = standups.filter(s => {\n  const completion = (s.json.property_task_completion_info || s.json.Task_Completion_Info || '').toLowerCase();\n  return completion.includes('yes') || completion.includes('complete') || completion.includes('done') || completion.includes('all complete');\n});\n\nconst incomplete = standups.filter(s => {\n  const completion = (s.json.property_task_completion_info || s.json.Task_Completion_Info || '').toLowerCase();\n  return completion.includes('no') || completion.includes('pending') || completion.includes('incomplete');\n});\n\nconsole.log('Completed:', completed.length);\nconsole.log('Incomplete:', incomplete.length);\n\nmessage += `━━━━━━━━━━━━━━━━━━\\n`;\nmessage += `✅ *Task Completion Status:*\\n`;\nmessage += `   ✓ Completed: ${completed.length}\\n`;\nmessage += `   ⏳ Pending: ${incomplete.length}\\n`;\nmessage += `   ℹ️ Other: ${standups.length - completed.length - incomplete.length}\\n\\n`;\n\n// Today's accomplishments\nmessage += `━━━━━━━━━━━━━━━━━━\\n`;\nmessage += `🎯 *Today's Accomplishments:*\\n\\n`;\n\nconst displayCount = Math.min(5, standups.length);\nstandups.slice(0, displayCount).forEach(s => {\n  const devId = s.json.property_developer_id || s.json.Developer_ID;\n  const member = activeMembers.find(m => {\n    const memberDevId = m.json.property_developer_id || m.json.Developer_ID;\n    return memberDevId === devId;\n  });\n  const name = member ? (member.json.property_full_name || member.json.Full_Name) : devId;\n  const completedWork = s.json.property_today_completed || s.json.Today_Completed || '';\n  \n  if (completedWork.trim()) {\n    const workText = completedWork.substring(0, 80);\n    message += `👤 *${name}*\\n`;\n    message += `   ${workText}${completedWork.length > 80 ? '...' : ''}\\n\\n`;\n  }\n});\n\nif (standups.length > 5) {\n  message += `_...and ${standups.length - 5} more team members_\\n\\n`;\n}\n\n// Footer\nmessage += `━━━━━━━━━━━━━━━━━━\\n`;\nmessage += `🕐 Generated at ${currentTime} IST`;\n\nconsole.log('=== SUMMARY COMPLETE ===');\n\nreturn {\n  message: message,\n  total_active: totalActive,\n  total_responded: totalResponded,\n  response_rate: parseFloat(responseRate),\n  missing_count: missingMembers.length,\n  help_needed_count: needHelp.length,\n  completed_count: completed.length,\n  incomplete_count: incomplete.length,\n  missing_members: missingMembers\n};"},"typeVersion":2},{"id":"c0ff3755-e5da-4608-a265-f85421f5e296","name":"Send to Admin Channel Evening","type":"n8n-nodes-base.slack","position":[704,1632],"webhookId":"evening-summary-webhook","parameters":{"text":"={{ $json.message }}","select":"channel","channelId":{"__rl":true,"mode":"id","value":"={{ $json.slackBotID }}"},"otherOptions":{"includeLinkToWorkflow":false}},"typeVersion":2.2},{"id":"2020c710-a210-42df-a02e-21ade4381f71","name":"🌅 Morning Summary Overview","type":"n8n-nodes-base.stickyNote","position":[-976,480],"parameters":{"color":6,"width":420,"height":584,"content":"# 🌅 Morning Standup Summary\n\n## How it works\n1. Triggers Mon–Sat at 10:10 AM IST\n2. Fetches active members from `Team_Members` Notion DB\n3. Fetches today's responded standups from `Daily_Standups` DB\n4. Merges data, builds summary, sends to admin Slack channel\n5. Output includes attendance, blockers & stats\n\n## Setup steps\n1. Connect your Notion integration and verify DB IDs\n2. Connect Slack bot (SlackBot Chintanbhai)\n3. Confirm Slack channel ID `C07PSV73SK0` is correct\n4. Activate the workflow"},"typeVersion":1},{"id":"a8681070-4e2f-4901-a4b4-9b72bfb644d6","name":"Send to Admin Channel","type":"n8n-nodes-base.slack","position":[864,784],"webhookId":"morning-summary-webhook","parameters":{"text":"={{ $json.message }}","select":"channel","channelId":{"__rl":true,"mode":"id","value":"={{ $json.slackBotID }}"},"otherOptions":{"includeLinkToWorkflow":false}},"typeVersion":2.2},{"id":"d1644f61-afd1-4054-9103-0a887c82aad4","name":"Morning schedule trigger","type":"n8n-nodes-base.scheduleTrigger","position":[-384,768],"parameters":{"rule":{"interval":[{"field":"cronExpression","expression":"10 10 * * 1-6"}]}},"typeVersion":1.2},{"id":"985857f3-5a33-4461-9a8d-7c301e6d682d","name":"Fetch team members (morning)","type":"n8n-nodes-base.notion","position":[-32,640],"parameters":{"filters":{"conditions":[{"key":"Active_Status|status","condition":"equals","statusValue":"Active"},{"key":"Daily_Standups|checkbox","condition":"equals","checkboxValue":true}]},"options":{},"resource":"databasePage","matchType":"allFilters","operation":"getAll","returnAll":true,"databaseId":{"__rl":true,"mode":"list","value":"2d4da36d-2b3d-80ba-931c-fa5646433363","cachedResultUrl":"https://www.notion.so/2d4da36d2b3d80ba931cfa5646433363","cachedResultName":"Team_Members"},"filterType":"manual"},"typeVersion":2.2},{"id":"e269b8d3-f186-46e7-8db4-6779eb8d5ee6","name":"Fetch today's morning standups","type":"n8n-nodes-base.notion","position":[-32,880],"parameters":{"filters":{"conditions":[{"key":"Responded|checkbox","condition":"equals","checkboxValue":true},{"key":"Date|date","date":"={{ $now.setZone('Asia/Kolkata').toFormat('yyyy-MM-dd') }}","condition":"equals"}]},"options":{},"resource":"databasePage","matchType":"allFilters","operation":"getAll","returnAll":true,"databaseId":{"__rl":true,"mode":"list","value":"2d4da36d-2b3d-8008-9194-d8e45419e824","cachedResultUrl":"https://www.notion.so/2d4da36d2b3d80089194d8e45419e824","cachedResultName":"Daily_Standups"},"filterType":"manual"},"typeVersion":2.2},{"id":"484fc410-b4f5-4418-a087-948e464aa90d","name":"Merge morning data","type":"n8n-nodes-base.merge","position":[288,784],"parameters":{},"typeVersion":3.2},{"id":"aa7c5fdd-41a0-46b5-ad69-7265e0f7c13b","name":"Build morning summary message","type":"n8n-nodes-base.code","position":[496,784],"parameters":{"jsCode":"// Get all merged input items\nconst allItems = $input.all();\n\nconsole.log('📥 Total items received:', allItems.length);\n\n// Normalize field names function\nconst normalizeRecord = (record) => ({\n  Developer_ID: record.property_developer_id || record.Developer_ID || '',\n  Full_Name: record.property_full_name || record.Full_Name || '',\n  Active_Status: record.property_active_status || record.Active_Status || '',\n  Responded: record.property_responded || record.Responded || false,\n  Blockers: record.property_blockers || record.Blockers || '',\n  Date: record.property_date || record.Date || '',\n  Completed_Yesterday: record.property_completed_yesterday || record.Completed_Yesterday || '',\n  Goals_Today: record.property_goals_today || record.Goals_Today || '',\n  Plans_Tickets: record.property_plans_tickets || record.Plans_Tickets || '',\n  Help_Needed: record.property_help_needed || record.Help_Needed || '',\n  Slack_User_ID: record.property_slack_user_id || record.Slack_User_ID || ''\n});\n\n// Process all items and separate by Developer_ID\nconst memberMap = new Map();\nconst standupMap = new Map();\n\nallItems.forEach(item => {\n  const normalized = normalizeRecord(item.json);\n  \n  // Skip if no Developer_ID\n  if (!normalized.Developer_ID) return;\n  \n  // If this record has Active_Status, it's a member record\n  if (normalized.Active_Status === 'Active') {\n    memberMap.set(normalized.Developer_ID, normalized);\n  }\n  \n  // If this record has Date and Responded=true, it's a standup response\n  if (normalized.Date && normalized.Responded === true) {\n    standupMap.set(normalized.Developer_ID, normalized);\n  }\n});\n\nconst activeMembers = Array.from(memberMap.values());\nconst standupResponses = Array.from(standupMap.values());\n\nconsole.log('👥 Active members:', activeMembers.length);\nconsole.log('✅ Standup responses:', standupResponses.length);\n\n// Get current India time\nconst now = new Date();\n\nconst todayFormatted = new Intl.DateTimeFormat(\"en-IN\", {\n  timeZone: \"Asia/Kolkata\",\n  weekday: \"long\",\n  year: \"numeric\",\n  month: \"long\",\n  day: \"numeric\"\n}).format(now);\n\nconst currentTime = new Intl.DateTimeFormat(\"en-IN\", {\n  timeZone: \"Asia/Kolkata\",\n  hour: \"numeric\",\n  minute: \"2-digit\",\n  hour12: true\n}).format(now);\n\n// Calculate statistics\nconst totalActive = activeMembers.length;\nconst respondedIds = new Set(standupResponses.map(s => s.Developer_ID));\nconst totalResponded = respondedIds.size;\nconst totalNotAttended = Math.max(0, totalActive - totalResponded);\nconst responseRate = totalActive > 0 ? ((totalResponded / totalActive) * 100).toFixed(1) : \"0.0\";\n\n// Separate members into attended and not attended\nconst respondedMembers = activeMembers.filter(m => respondedIds.has(m.Developer_ID));\nconst notAttendedMembers = activeMembers.filter(m => !respondedIds.has(m.Developer_ID));\n\nconsole.log('✅ Responded members:', respondedMembers.length);\nconsole.log('❌ Not attended members:', notAttendedMembers.length);\n\n// Function to check if text indicates \"no blocker\"\nconst isNoBlocker = (text) => {\n  if (!text) return true;\n  \n  const cleaned = text.toString().trim().toLowerCase();\n  if (cleaned.length === 0) return true;\n  \n  const noneWords = [\n    \"no\", \"none\", \"n/a\", \"na\", \"nil\", \"nothing\", \"nope\",\n    \"no blocker\", \"no blockers\", \"no blocking\", \"no blocks\",\n    \"not applicable\", \"not available\", \"empty\", \"null\"\n  ];\n  \n  if (noneWords.includes(cleaned)) return true;\n  \n  const noBlockerPatterns = [\n    /^no[\\s\\-_]*blocker/i,\n    /^no[\\s\\-_]*block/i,\n    /^none$/i,\n    /^n\\/?a$/i,\n    /^nil$/i\n  ];\n  \n  return noBlockerPatterns.some(pattern => pattern.test(cleaned));\n};\n\n// Find members with actual blockers\nconst membersWithBlockers = standupResponses.filter(s => {\n  const blockerText = s.Blockers || s.Help_Needed || '';\n  return !isNoBlocker(blockerText);\n});\n\nconsole.log('🚧 Members with blockers:', membersWithBlockers.length);\n\n// Build WhatsApp formatted message\nlet message = `📊 *Daily Standup Summary Report*\\n`;\nmessage += `📅 Date: ${todayFormatted}\\n`;\nmessage += `🕐 Time: ${currentTime} IST\\n`;\nmessage += `━━━━━━━━━━━━━━━━━━━━━━━━━━\\n\\n`;\n\nmessage += `📈 *Attendance Overview*\\n`;\nmessage += `👥 Total Active Members: ${totalActive}\\n`;\nmessage += `✅ Attended (Responded): ${totalResponded}\\n`;\nmessage += `❌ Not Attended: ${totalNotAttended}\\n`;\nmessage += `📊 Response Rate: ${responseRate}%\\n\\n`;\n\nif (respondedMembers.length > 0) {\n  message += `✅ *Members Who Attended (${respondedMembers.length}):*\\n`;\n  respondedMembers.forEach(member => {\n    const name = member.Full_Name || member.Developer_ID || 'Unknown';\n    message += `   • ${name}\\n`;\n  });\n  message += `\\n`;\n} else {\n  message += `✅ *No members have attended yet*\\n\\n`;\n}\n\nif (notAttendedMembers.length > 0) {\n  message += `❌ *Members Who Did NOT Attend (${notAttendedMembers.length}):*\\n`;\n  notAttendedMembers.forEach(member => {\n    const name = member.Full_Name || member.Developer_ID || 'Unknown';\n    message += `   • ${name}\\n`;\n  });\n  message += `\\n`;\n} else {\n  message += `🎉 *All members have attended!*\\n\\n`;\n}\n\nmessage += `━━━━━━━━━━━━━━━━━━━━━━━━━━\\n`;\n\nif (membersWithBlockers.length > 0) {\n  message += `🚧 *Blockers Reported (${membersWithBlockers.length}):*\\n\\n`;\n  membersWithBlockers.forEach(member => {\n    const name = member.Full_Name || member.Developer_ID || 'Unknown';\n    const blockerText = member.Blockers || member.Help_Needed || 'Not specified';\n    message += `👤 *${name}*\\n`;\n    message += `   🚫 ${blockerText}\\n\\n`;\n  });\n} else {\n  message += `✅ *No Blockers Reported*\\n\\n`;\n}\n\nmessage += `━━━━━━━━━━━━━━━━━━━━━━━━━━\\n`;\nmessage += `📊 *Summary Statistics*\\n`;\nmessage += `• Team Size: ${totalActive}\\n`;\nmessage += `• Responses: ${totalResponded}\\n`;\nmessage += `• Pending: ${totalNotAttended}\\n`;\nmessage += `• Blockers: ${membersWithBlockers.length}\\n\\n`;\n\nmessage += `━━━━━━━━━━━━━━━━━━━━━━━━━━\\n`;\nmessage += `🤖 Auto-generated Daily Standup Report\\n`;\nmessage += `⏰ Generated at ${currentTime} IST\\n`;\n\nreturn {\n  json: {\n    message,\n    date: todayFormatted,\n    time: currentTime,\n    timestamp: now.toISOString(),\n    total_active: totalActive,\n    total_responded: totalResponded,\n    total_not_attended: totalNotAttended,\n    response_rate: parseFloat(responseRate),\n    blockers_count: membersWithBlockers.length,\n    responded_members: respondedMembers.map(m => ({\n      id: m.Developer_ID,\n      name: m.Full_Name,\n      slack_user_id: m.Slack_User_ID\n    })),\n    not_attended_members: notAttendedMembers.map(m => ({\n      id: m.Developer_ID,\n      name: m.Full_Name,\n      slack_user_id: m.Slack_User_ID\n    })),\n    blockers: membersWithBlockers.map(m => ({\n      id: m.Developer_ID,\n      name: m.Full_Name,\n      blocker: m.Blockers || m.Help_Needed,\n      completed_yesterday: m.Completed_Yesterday,\n      goals_today: m.Goals_Today,\n      plans_tickets: m.Plans_Tickets\n    })),\n    debug: {\n      total_items: allItems.length,\n      active_members_found: activeMembers.length,\n      standup_responses_found: standupResponses.length,\n      responded_ids: Array.from(respondedIds)\n    }\n  }\n};"},"typeVersion":2},{"id":"056d01d8-6b8b-45f0-b1bc-4d8d81fa6594","name":"Trigger Group Note1","type":"n8n-nodes-base.stickyNote","position":[-496,608],"parameters":{"color":7,"width":324,"height":336,"content":"## ⏰ Trigger\nFires Mon–Sat at 10:10 AM IST (`10 10 * * 1-6`). Kicks off both Notion fetches in parallel."},"typeVersion":1},{"id":"9223fba9-3482-4478-955e-002d1545f070","name":"Fetch Data Group Note1","type":"n8n-nodes-base.stickyNote","position":[-144,496],"parameters":{"color":7,"width":320,"height":572,"content":"## 📋 Fetch Data\nFetches active members (`Team_Members`) and today's responded morning standups (`Daily_Standups`) from Notion in parallel."},"typeVersion":1},{"id":"d25db796-f2df-43a6-8feb-9ded9861083e","name":"Merge Build Group Note1","type":"n8n-nodes-base.stickyNote","position":[208,640],"parameters":{"color":7,"width":492,"height":328,"content":"## 🔀 Merge & Build\nMerges both datasets. Code node normalizes fields, calculates attendance stats, detects blockers, and formats the Slack message."},"typeVersion":1},{"id":"45394719-6b96-47a5-8d46-51472c82e029","name":"Send Slack Group Note1","type":"n8n-nodes-base.stickyNote","position":[736,640],"parameters":{"color":7,"width":352,"height":336,"content":"## 📤 Send to Slack\nPosts the formatted morning standup summary to the admin Slack channel via SlackBot Chintanbhai."},"typeVersion":1},{"id":"e9d5f66e-57d8-462f-9bc2-ec3a28db3d22","name":"🌅 Morning Initiator Overview","type":"n8n-nodes-base.stickyNote","position":[-7472,240],"parameters":{"color":6,"width":460,"height":508,"content":"# 🌅 Morning Standup Initiator\n\n## How it works\n1. Triggers Mon–Sat at 9:40 AM IST\n2. Fetches active members from `Team_Members` Notion DB\n3. Loops through each developer one at a time\n4. Validates member data, checks Redis for existing session\n5. Creates Notion session record + saves to Redis\n6. Sends Question 1 via Slack DM, saves channel ID back to Notion\n\n## Setup steps\n1. Connect Notion integration and verify all DB IDs\n2. Connect Redis instance with correct credentials\n3. Connect Slack bot and confirm DM permissions\n4. Activate the workflow"},"typeVersion":1},{"id":"84bbf89f-6820-4ae4-8aec-afadd95438ea","name":"Fetch Gate Group Note","type":"n8n-nodes-base.stickyNote","position":[-6624,336],"parameters":{"color":7,"width":412,"height":336,"content":"## 📋 Fetch & Gate\nFetches active members from `Team_Members` Notion DB. IF node stops the flow if no active members are found."},"typeVersion":1},{"id":"13b3c99e-e92d-432f-a687-f67c5ec512e2","name":"Loop Group Note","type":"n8n-nodes-base.stickyNote","position":[-6128,288],"parameters":{"color":7,"width":300,"height":384,"content":"## 🔁 Developer Loop\n`splitInBatches` iterates one member at a time. All paths (valid, invalid, skipped) converge at `Continue to next` before looping back."},"typeVersion":1},{"id":"d02ad8b0-9326-43fb-95bd-94f22b63f93b","name":"Validate Group Note","type":"n8n-nodes-base.stickyNote","position":[-5760,192],"parameters":{"color":7,"width":448,"height":336,"content":"## ✅ Validate Member\nCode node normalizes Notion fields and checks required values. IF node skips invalid members without breaking the loop."},"typeVersion":1},{"id":"99dc63bc-7092-4a96-a503-decf4694a4c4","name":"Redis Check Group Note","type":"n8n-nodes-base.stickyNote","position":[-5280,128],"parameters":{"color":7,"width":468,"height":408,"content":"## 🔴 Redis Session Check\nGETs existing session key `morning:standup:session:{slack_user_id}`. Code node parses the response — sets `needs_new_session` true/false. IF node skips members with active sessions."},"typeVersion":1},{"id":"11396eb2-cb2a-44cd-82fb-6b1afc5c5d2e","name":"Create Session Group Note","type":"n8n-nodes-base.stickyNote","position":[-4784,96],"parameters":{"color":7,"width":768,"height":420,"content":"## 📝 Create Session\nCreates a `Conversation_State` record in Notion (question 1, In Progress). Code node builds the Redis payload with a 24hr TTL."},"typeVersion":1},{"id":"fefd9e1e-81b4-4a9c-a4d5-d4e3c851ea27","name":"Save Send Group Note","type":"n8n-nodes-base.stickyNote","position":[-3968,0],"parameters":{"color":7,"width":1244,"height":824,"content":"## 🔴 Save & Send\nIF `can_write_redis` is true: SETs session in Redis (86400s TTL), sends Question 1 Slack DM, then saves the DM channel ID back to `Team_Members` in Notion."},"typeVersion":1},{"id":"900c50f1-aebc-4e22-85a6-5d7bce1cfd09","name":"Morning standup initiator trigger","type":"n8n-nodes-base.scheduleTrigger","position":[-6864,480],"parameters":{"rule":{"interval":[{"field":"cronExpression","expression":"0 40 9 * * 1-6"}]}},"typeVersion":1.2},{"id":"828dc392-0297-4856-82a1-9dca2efc75ab","name":"Get active team members","type":"n8n-nodes-base.notion","position":[-6576,480],"parameters":{"filters":{"conditions":[{"key":"Daily_Standups|checkbox","condition":"equals","checkboxValue":true},{"key":"Active_Status|status","condition":"equals","statusValue":"Active"}]},"options":{},"resource":"databasePage","matchType":"allFilters","operation":"getAll","returnAll":true,"databaseId":{"__rl":true,"mode":"list","value":"2d4da36d-2b3d-80ba-931c-fa5646433363","cachedResultUrl":"https://www.notion.so/2d4da36d2b3d80ba931cfa5646433363","cachedResultName":"Team_Members"},"filterType":"manual"},"typeVersion":2.2},{"id":"6aaaacd8-76ae-4428-948b-41860e06a7e7","name":"Check if members found","type":"n8n-nodes-base.if","position":[-6352,480],"parameters":{"options":{},"conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"ef1ed4ff-f356-49a9-9b2a-907619ccbd85","operator":{"type":"boolean","operation":"false","singleValue":true},"leftValue":"={{ $json.isEmpty() }}","rightValue":""}]}},"typeVersion":2},{"id":"ae99b0ff-4147-4ff9-86a2-688156f51893","name":"Developer loop","type":"n8n-nodes-base.splitInBatches","position":[-6048,464],"parameters":{"options":{}},"typeVersion":3},{"id":"86aaa4ea-6e5a-427a-8d13-46622cce5bec","name":"Extract and validate member data","type":"n8n-nodes-base.code","position":[-5712,352],"parameters":{"jsCode":"/**\n * Team Member JSON Validation & Normalization\n */\n\nconst items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n  const data = item.json || {};\n\n  const notionPageId = data.id || '';\n  const fullName = (data.property_full_name || data.name || '').trim();\n  const slackUserId = (data.property_slack_user_id || '').trim();\n  const developerId = (data.property_developer_id || '').trim();\n  const teamRole = (data.property_team_role || '').trim();\n  const activeStatus = (data.property_active_status || '').trim();\n  const communicationTool = (data.property_client_communication || '').trim();\n\n  const errors = [];\n\n  if (!notionPageId) errors.push('Missing Notion Page ID');\n  if (!fullName) errors.push('Missing Full Name');\n  if (!slackUserId) errors.push('Missing Slack User ID');\n  if (!developerId) errors.push('Missing Developer ID');\n  if (!teamRole) errors.push('Missing Team Role');\n  if (!activeStatus) errors.push('Missing Active Status');\n\n  const isValid = errors.length === 0;\n\n  results.push({\n    json: {\n      notion_page_id: notionPageId,\n      full_name: fullName,\n      slack_user_id: slackUserId,\n      developer_id: developerId,\n      team_role: teamRole,\n      active_status: activeStatus,\n      client_communication: communicationTool || null,\n      leave_management: Boolean(data.property_leave_management),\n      leave_type: data.property_leave_type || null,\n      leave_start_date: data.property_leave_start_date || null,\n      leave_end_date: data.property_leave_end_date || null,\n      daily_standups: Boolean(data.property_daily_standups),\n      blockers_tracking: Boolean(data.property_blockers_tracking),\n      is_valid: isValid,\n      validation_errors: errors.length ? errors : null,\n      source: 'notion',\n      validated_at: new Date().toISOString()\n    }\n  });\n}\n\nreturn results;\n"},"typeVersion":2},{"id":"425d4c33-df67-4b4a-a4c1-21b6b3f6efcf","name":"Is valid member","type":"n8n-nodes-base.if","position":[-5440,352],"parameters":{"options":{},"conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"45141cf2-e523-4074-b833-35f4829346c8","operator":{"type":"boolean","operation":"true","singleValue":true},"leftValue":"={{ $json.is_valid }}","rightValue":"true"}]}},"typeVersion":2},{"id":"d1c62232-d310-49e5-984e-f6d35d5488f0","name":"Check existing Redis session","type":"n8n-nodes-base.redis","position":[-5200,336],"parameters":{"key":"={{ \"morning:standup:session:\" + $json.slack_user_id }}","options":{},"operation":"get"},"typeVersion":1},{"id":"f4da8526-ae46-4004-ad4b-ba8fba872e5a","name":"Parse session state","type":"n8n-nodes-base.code","position":[-4944,336],"parameters":{"jsCode":"const items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n  const redisValue = item.json.value;\n  let sessionExists = false;\n  let sessionData = null;\n  \n  if (redisValue && redisValue !== 'null' && redisValue !== '') {\n    try {\n      sessionData = JSON.parse(redisValue);\n      sessionExists = true;\n    } catch (e) {\n      sessionExists = false;\n    }\n  }\n  \n  results.push({\n    json: {\n      ...item.json,\n      session_exists: sessionExists,\n      session_data: sessionData,\n      needs_new_session: !sessionExists\n    }\n  });\n}\n\nreturn results;"},"typeVersion":2},{"id":"6e2c790c-e4bc-4a9c-bcad-77b4202cac15","name":"Needs new session","type":"n8n-nodes-base.if","position":[-4688,320],"parameters":{"options":{},"conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"c3b9efe6-8860-4a54-81bf-b018cdf2f759","operator":{"type":"boolean","operation":"true","singleValue":true},"leftValue":"={{ $json.needs_new_session }}","rightValue":"true"}]}},"typeVersion":2},{"id":"6966a3c3-bc2b-46ad-9f31-96e776b94a53","name":"Create Notion session","type":"n8n-nodes-base.notion","position":[-4400,256],"parameters":{"options":{},"resource":"databasePage","databaseId":{"__rl":true,"mode":"list","value":"2d4da36d-2b3d-80e1-b7c8-e3a96667c823","cachedResultUrl":"https://www.notion.so/2d4da36d2b3d80e1b7c8e3a96667c823","cachedResultName":"Conversation_State"},"propertiesUi":{"propertyValues":[{"key":"User_ID|title","title":"={{ $('Is valid member').item.json.slack_user_id }}"},{"key":"Current_Question|number","numberValue":1},{"key":"Date|date","date":"={{ $now.setZone('Asia/Kolkata').toFormat('M/d/yyyy') }}"},{"key":"Status|status","statusValue":"In Progress"}]}},"typeVersion":2.2},{"id":"a4937e19-26c6-4e8a-930d-66af41f04dba","name":"Prepare session data","type":"n8n-nodes-base.code","position":[-4144,256],"parameters":{"jsCode":"/**\n * Prepare Redis session data with readiness flag\n */\n\nconst items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n  const data = item.json || {};\n\n  const slackUserId =\n    data.property_user_id ||\n    data.name ||\n    '';\n\n  const answers = [\n    data.property_answer_1 || '',\n    data.property_answer_2 || '',\n    data.property_answer_3 || '',\n    data.property_answer_4 || ''\n  ].filter(ans => ans !== '');\n\n  const isSessionReady = Boolean(slackUserId && data.id);\n\n  const sessionData = {\n    notion_page_id: data.id,\n    slack_user_id: slackUserId,\n    current_question: data.property_current_question ?? 0,\n    answers,\n    started_at: data.property_date?.start || new Date().toISOString(),\n    last_updated: new Date().toISOString(),\n    is_session_ready: isSessionReady\n  };\n\n  const redisKey = isSessionReady\n    ? `morning:standup:session:${slackUserId}`\n    : null;\n\n  const redisValue = isSessionReady\n    ? JSON.stringify(sessionData)\n    : null;\n\n  results.push({\n    json: {\n      session_data: sessionData,\n      redis_key: redisKey,\n      redis_value: redisValue,\n      redis_ttl: 86400,\n      can_write_redis: isSessionReady\n    }\n  });\n}\n\nreturn results;\n"},"typeVersion":2},{"id":"0cd88a6f-bcf5-406a-bf2e-8ab7fcafe8d5","name":"Session data ready","type":"n8n-nodes-base.if","position":[-3904,240],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"a188bc1f-ea74-4f52-82c8-393e8414c48c","operator":{"type":"boolean","operation":"true","singleValue":true},"leftValue":"={{ $json.can_write_redis }}","rightValue":""}]}},"typeVersion":2.2},{"id":"2d534d2a-b921-4f26-ac21-39bb38efbe1f","name":"Save session to Redis","type":"n8n-nodes-base.redis","position":[-3648,192],"parameters":{"key":"={{ $json.redis_key }}","ttl":"={{ $json.redis_ttl }}","value":"={{ $json.redis_value }}","expire":true,"operation":"set"},"typeVersion":1},{"id":"976a61ec-965a-440a-82f9-0467a8088f4c","name":"Send standup message","type":"n8n-nodes-base.slack","position":[-3376,192],"webhookId":"4fc88659-584d-4140-aa76-3a45640a4ede","parameters":{"text":"=Good morning {{ $('Is valid member').item.json.full_name }}! 👋\n\n📋 *Daily Standup - Question 1 of 4*\n\n*How are you feeling today?*","select":"channel","channelId":{"__rl":true,"mode":"id","value":"={{ $json.session_data.slack_user_id }}"},"otherOptions":{"includeLinkToWorkflow":false}},"typeVersion":2.3},{"id":"ca0b2a68-fd2c-4bd3-b047-c965beb6ee52","name":"Update Slack channel ID in Notion","type":"n8n-nodes-base.notion","position":[-3104,128],"parameters":{"pageId":{"__rl":true,"mode":"id","value":"={{ $('Developer loop').item.json.id }}"},"options":{},"resource":"databasePage","operation":"update","propertiesUi":{"propertyValues":[{"key":"Slack_Bot_Channel_ID|rich_text","textContent":"={{ $json.channel }}"}]}},"typeVersion":2.2},{"id":"6346f77a-1041-4bc5-88e0-ba53d7cf8bc6","name":"Continue to next (morning)","type":"n8n-nodes-base.noOp","position":[-2976,560],"parameters":{},"typeVersion":1},{"id":"ea8dbfff-e1e1-48b2-89aa-3ac474554cc2","name":"Trigger Group Note2","type":"n8n-nodes-base.stickyNote","position":[-6976,336],"parameters":{"color":7,"width":328,"height":336,"content":"## ⏰ Trigger\nFires Mon–Sat at 9:40 AM IST (`0 40 9 * * 1-6`). Kicks off the standup initiation flow for all active team members."},"typeVersion":1},{"id":"6645947e-7806-4d7b-86e7-aec6a332b340","name":"Main Overview","type":"n8n-nodes-base.stickyNote","position":[-7456,1312],"parameters":{"color":6,"width":464,"height":560,"content":"# 🌙 Evening Standup Initiator\n\n## How it works\nFires Mon–Sat at 6 PM IST. Fetches all active developers from Notion, loops through each one, checks Redis for a duplicate session (skips if today's session already exists), creates a Notion session record, stores state in Redis (TTL 24h), and sends Question 1 of 3 via Slack DM. All paths — skipped, invalid, or completed — return to the loop.\n\n## Setup steps\n1. Add your **Notion** credentials and verify `Team_Members` DB ID\n2. Verify `Conversation_State_Afternoon` Notion DB ID\n3. Add your **Redis** credentials (host, port, password)\n4. Add your **Slack** credentials with `chat:write` scope\n5. Confirm cron timezone is UTC (workflow fires at 12:30 UTC = 6 PM IST)\n6. Test manually with one developer before activating"},"typeVersion":1},{"id":"4a794720-ee6a-40e5-bd87-d2adbf8f1594","name":"Group: Trigger Fetch Gate","type":"n8n-nodes-base.stickyNote","position":[-6912,1440],"parameters":{"color":7,"width":1056,"height":372,"content":"## ⏰ Trigger, Fetch & Gate\nSchedule fires Mon–Sat 6 PM IST. Fetches active members from Notion (`Daily_Standups = true`, `Active_Status = Active`). If no records returned, outputs `NO_DEVELOPERS` status and stops."},"typeVersion":1},{"id":"105aa8a6-8215-41df-8048-a2252287ae9c","name":"Group: Loop Validate","type":"n8n-nodes-base.stickyNote","position":[-5856,1600],"parameters":{"color":7,"width":816,"height":276,"content":"## 🔁 Developer Loop & Validation\nIterates through each member one at a time. Validates required fields (`slack_user_id`, `developer_id`, `full_name`, `team_role`). Invalid members are silently skipped via the false branch."},"typeVersion":1},{"id":"b841778d-7663-48e0-91aa-9dabda821b0d","name":"Group: Redis Check","type":"n8n-nodes-base.stickyNote","position":[-4976,1584],"parameters":{"color":7,"width":848,"height":260,"content":"## 🔴 Redis Session Check\nGETs `standup:evening:{slack_user_id}`. If a session exists with today's date, sets `skip: true` to prevent duplicate standups. Continues safely if Redis is unreachable (`continueOnFail: true`)."},"typeVersion":1},{"id":"df73094b-61e2-41d6-9182-36f0a77c1a1a","name":"Group: Session Create Store","type":"n8n-nodes-base.stickyNote","position":[-4112,1456],"parameters":{"color":7,"width":928,"height":324,"content":"## 📝 Session Creation & Storage\nCreates a Notion record in `Conversation_State_Afternoon` (Question 1, In Progress). Builds Redis session object with answers, timestamps, and record ID. SETs key with 24h TTL."},"typeVersion":1},{"id":"e32eaf2e-c587-4d12-8055-0137fbdc57bd","name":"Group: Slack Log Continue","type":"n8n-nodes-base.stickyNote","position":[-3152,1296],"parameters":{"color":7,"width":1168,"height":996,"content":"## 💬 Send, Log & Loop Back\nSends Question 1 of 3 via Slack DM (`chat:write`). Logs final status (`SUCCESS` or `SLACK_FAILED`). All paths — success, skipped, or failed — converge at `Continue to next`, which loops back to the iterator for the next developer."},"typeVersion":1},{"id":"c3966ff3-dd43-45a3-a7ad-91c2e279edb6","name":"Evening standup initiator trigger","type":"n8n-nodes-base.scheduleTrigger","position":[-6848,1648],"parameters":{"rule":{"interval":[{"field":"cronExpression","expression":"0 18 * * 1-6"}]}},"typeVersion":1.2},{"id":"a1dcd3e0-e402-440b-8d76-059f2e295672","name":"Get active team members (evening)","type":"n8n-nodes-base.notion","position":[-6576,1648],"parameters":{"filters":{"conditions":[{"key":"Daily_Standups|checkbox","condition":"equals","checkboxValue":true},{"key":"Active_Status|status","condition":"equals","statusValue":"Active"}]},"options":{},"resource":"databasePage","matchType":"allFilters","operation":"getAll","returnAll":true,"databaseId":{"__rl":true,"mode":"list","value":"2d4da36d-2b3d-80ba-931c-fa5646433363","cachedResultUrl":"https://www.notion.so/2d4da36d2b3d80ba931cfa5646433363","cachedResultName":"Team_Members"},"filterType":"manual"},"typeVersion":2.2},{"id":"63623162-b826-4913-8c74-42e49f269ec9","name":"Check developers found","type":"n8n-nodes-base.if","position":[-6336,1632],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"has-developers","operator":{"type":"boolean","operation":"true","singleValue":true},"leftValue":"={{ $json.isEmpty() }}","rightValue":0}]}},"typeVersion":2.2},{"id":"d61c8546-6257-49bb-ab43-be9862570360","name":"No developers found","type":"n8n-nodes-base.code","position":[-6112,1536],"parameters":{"jsCode":"const now = new Date();\n\nreturn {\n  status: 'NO_DEVELOPERS',\n  message: 'No active developers found for daily standup',\n  timestamp: now.toISOString(),\n  date: now.toISOString().split('T')[0]\n};"},"typeVersion":2},{"id":"41d9d62d-6903-4b7e-bcfa-ea6bb4f1f2f8","name":"Process each developer","type":"n8n-nodes-base.splitInBatches","position":[-5792,1696],"parameters":{"options":{}},"typeVersion":3},{"id":"63aa7f68-312d-476f-8f59-532126317494","name":"Validate and prepare member data","type":"n8n-nodes-base.code","position":[-5536,1712],"parameters":{"jsCode":"/**\n * Team Member JSON Validation & Normalization\n */\n\nconst items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n  const data = item.json || {};\n\n  const notionPageId = data.id || '';\n  const fullName = (data.property_full_name || data.name || '').trim();\n  const slackUserId = (data.property_slack_user_id || '').trim();\n  const developerId = (data.property_developer_id || '').trim();\n  const teamRole = (data.property_team_role || '').trim();\n  const activeStatus = (data.property_active_status || '').trim();\n  const communicationTool = (data.property_client_communication || '').trim();\n\n  const errors = [];\n\n  if (!notionPageId) errors.push('Missing Notion Page ID');\n  if (!fullName) errors.push('Missing Full Name');\n  if (!slackUserId) errors.push('Missing Slack User ID');\n  if (!developerId) errors.push('Missing Developer ID');\n  if (!teamRole) errors.push('Missing Team Role');\n  if (!activeStatus) errors.push('Missing Active Status');\n\n  const isValid = errors.length === 0;\n\n  results.push({\n    json: {\n      notion_page_id: notionPageId,\n      full_name: fullName,\n      slack_user_id: slackUserId,\n      developer_id: developerId,\n      team_role: teamRole,\n      active_status: activeStatus,\n      client_communication: communicationTool || null,\n      leave_management: Boolean(data.property_leave_management),\n      leave_type: data.property_leave_type || null,\n      leave_start_date: data.property_leave_start_date || null,\n      leave_end_date: data.property_leave_end_date || null,\n      daily_standups: Boolean(data.property_daily_standups),\n      blockers_tracking: Boolean(data.property_blockers_tracking),\n      is_valid: isValid,\n      validation_errors: errors.length ? errors : null,\n      source: 'notion',\n      validated_at: new Date().toISOString()\n    }\n  });\n}\n\nreturn results;\n"},"typeVersion":2},{"id":"e4f2fa1e-1569-4b15-9bd9-272c9b94cfb5","name":"Check if valid member (evening)","type":"n8n-nodes-base.if","position":[-5296,1696],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"is-valid","operator":{"type":"boolean","operation":"true","singleValue":true},"leftValue":"={{ $json.is_valid }}","rightValue":true}]}},"typeVersion":2.2},{"id":"7729190a-eda6-4380-8ffe-c1d5c30698f7","name":"Check evening Redis session","type":"n8n-nodes-base.redis","position":[-4912,1680],"parameters":{"key":"=standup:evening:{{ $json.slack_user_id }}","options":{},"operation":"get","propertyName":"redis_session"},"typeVersion":1,"continueOnFail":true},{"id":"cd413cd2-60f1-4de8-8fa8-7a40cb381b0e","name":"Check evening session status","type":"n8n-nodes-base.code","position":[-4640,1680],"parameters":{"jsCode":"const devData = $('Check if valid member (evening)').first().json;\nconst redisInputs = $input.all();\n\nlet redisResult = '';\nfor (const item of redisInputs) {\n  if (item.json.redis_session !== undefined) {\n    redisResult = item.json.redis_session;\n    break;\n  }\n}\n\nlet sessionExists = false;\nif (redisResult && redisResult !== '') {\n  try {\n    const session = typeof redisResult === 'string' ? JSON.parse(redisResult) : redisResult;\n    const sessionDate = session.date || '';\n    const today = new Date().toISOString().split('T')[0];\n    \n    if (sessionDate === today) {\n      sessionExists = true;\n    }\n  } catch (error) {\n    console.log('Redis parse error:', error.message);\n  }\n}\n\nconst now = new Date();\n\nif (sessionExists) {\n  return {\n    skip: true,\n    skip_reason: 'SESSION_EXISTS',\n    slack_user_id: devData.slack_user_id,\n    developer_id: devData.developer_id,\n    full_name: devData.full_name,\n    timestamp: now.toISOString()\n  };\n}\n\nreturn {\n  skip: false,\n  slack_user_id: devData.slack_user_id,\n  developer_id: devData.developer_id,\n  full_name: devData.full_name,\n  client_name: devData.client_name || '',\n  team_role: devData.team_role || ''\n};"},"typeVersion":2},{"id":"30d95079-1c26-4295-a02f-1cefd6609724","name":"Should proceed with evening session","type":"n8n-nodes-base.if","position":[-4384,1680],"parameters":{"options":{},"conditions":{"options":{"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"should-proceed","operator":{"type":"boolean","operation":"equals"},"leftValue":"={{ $json.skip }}","rightValue":false}]}},"typeVersion":2.2},{"id":"1041c488-c78c-4217-9c02-ff6e77f31f2c","name":"Create evening Notion session","type":"n8n-nodes-base.notion","position":[-4048,1616],"parameters":{"options":{},"resource":"databasePage","databaseId":{"__rl":true,"mode":"list","value":"2d4da36d-2b3d-806a-a528-f463dae04e54","cachedResultUrl":"https://www.notion.so/2d4da36d2b3d806aa528f463dae04e54","cachedResultName":"Conversation_State_Afternoon"},"propertiesUi":{"propertyValues":[{"key":"User_ID|title","title":"={{ $json.slack_user_id }}"},{"key":"Current_Question|number","numberValue":1},{"key":"Date|date","date":"={{ $now.setZone('Asia/Kolkata').toFormat('M/d/yyyy') }}"},{"key":"Status|status","statusValue":"In Progress"}]}},"typeVersion":2.2},{"id":"75246922-3404-42fb-8a46-423b972d6f3a","name":"Build evening session data","type":"n8n-nodes-base.code","position":[-3760,1600],"parameters":{"jsCode":"const devData = $('Should proceed with evening session').first().json;\nconst airtableInputs = $input.all();\n\nlet airtableResult = null;\nfor (const item of airtableInputs) {\n  if (item.json.id) {\n    airtableResult = item.json;\n    break;\n  }\n}\n\nif (!airtableResult || !airtableResult.id) {\n  return {\n    skip: true,\n    skip_reason: 'AIRTABLE_FAILED',\n    error: 'Failed to create Airtable record',\n    slack_user_id: devData.slack_user_id,\n    developer_id: devData.developer_id,\n    full_name: devData.full_name\n  };\n}\n\nconst now = new Date();\nconst today = now.toISOString().split('T')[0];\n\nconst sessionData = {\n  user_id: devData.slack_user_id,\n  developer_id: devData.developer_id,\n  full_name: devData.full_name,\n  client_name: devData.client_name || '',\n  team_role: devData.team_role || '',\n  current_question: 1,\n  status: 'Active',\n  date: today,\n  started_at: now.toISOString(),\n  airtable_record_id: airtableResult.id,\n  answers: {\n    answer_1: null,\n    answer_2: null,\n    answer_3: null,\n    answer_4: null\n  }\n};\n\nreturn {\n  skip: false,\n  redis_key: `standup:evening:${devData.slack_user_id}`,\n  redis_value: JSON.stringify(sessionData),\n  session_data: sessionData,\n  slack_user_id: devData.slack_user_id,\n  full_name: devData.full_name,\n  developer_id: devData.developer_id,\n  airtable_id: airtableResult.id\n};"},"typeVersion":2},{"id":"177f9493-44cf-4e03-927e-3b23211fa843","name":"Evening session ready","type":"n8n-nodes-base.if","position":[-3440,1600],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"session-ready","operator":{"type":"boolean","operation":"equals"},"leftValue":"={{ $json.skip }}","rightValue":false}]}},"typeVersion":2.2},{"id":"00406a2d-922a-440f-b29f-d05686392b6c","name":"Store evening session in Redis","type":"n8n-nodes-base.redis","position":[-3088,1488],"parameters":{"key":"={{ $json.redis_key }}","ttl":86400,"value":"={{ $json.redis_value }}","expire":true,"operation":"set"},"typeVersion":1,"continueOnFail":true},{"id":"828b422e-c5fe-42e4-a888-79a865e1835e","name":"Send evening standup message","type":"n8n-nodes-base.slack","position":[-2816,1472],"webhookId":"1e19cc1b-987d-4863-ac9e-32a0e11e6f8a","parameters":{"text":"=Good Evening {{ $json.full_name }} ☀️\n\n📋 *Daily Standup – Question 1 of 3*\n\n*What have you completed today?*\n\nPlease share your accomplishments from today.","user":{"__rl":true,"mode":"id","value":"={{ $json.session_data.user_id }}"},"select":"user","otherOptions":{"includeLinkToWorkflow":false}},"typeVersion":2.2,"continueOnFail":true},{"id":"3b67d075-85b1-4f3d-bd8a-2bf8c808d2e8","name":"Log final result","type":"n8n-nodes-base.code","position":[-2576,1472],"parameters":{"jsCode":"const sessionData = $('Store evening session in Redis').first().json;\nconst slackInputs = $input.all();\n\nlet slackResult = null;\nfor (const item of slackInputs) {\n  if (item.json.ok !== undefined || item.json.error !== undefined) {\n    slackResult = item.json;\n    break;\n  }\n}\n\nlet slackSuccess = true;\nif (slackResult !== null) {\n  if (slackResult.ok === false || String(JSON.stringify(slackResult)).toLowerCase().includes('error')) {\n    slackSuccess = false;\n  }\n}\n\nconst now = new Date();\n\nreturn {\n  status: slackSuccess ? 'SUCCESS' : 'SLACK_FAILED',\n  slack_success: slackSuccess,\n  redis_success: true,\n  slack_user_id: sessionData.slack_user_id,\n  developer_id: sessionData.developer_id,\n  full_name: sessionData.full_name,\n  airtable_id: sessionData.airtable_id,\n  timestamp: now.toISOString()\n};"},"typeVersion":2},{"id":"f3bf25e0-83c1-4c72-b24b-c5402a1954f5","name":"Continue to next (evening)","type":"n8n-nodes-base.noOp","position":[-2176,2064],"parameters":{},"typeVersion":1}],"pinData":{},"connections":{"Merge Data":{"main":[[{"node":"Build evening summary message","type":"main","index":0}]]},"Developer loop":{"main":[[],[{"node":"Extract and validate member data","type":"main","index":0}]]},"Is valid member":{"main":[[{"node":"Check existing Redis session","type":"main","index":0}],[{"node":"Continue to next (morning)","type":"main","index":0}]]},"Log final result":{"main":[[{"node":"Continue to next (evening)","type":"main","index":0}]]},"Needs new session":{"main":[[{"node":"Create Notion session","type":"main","index":0}],[{"node":"Continue to next (morning)","type":"main","index":0}]]},"Merge morning data":{"main":[[{"node":"Build morning summary message","type":"main","index":0}]]},"Session data ready":{"main":[[{"node":"Save session to Redis","type":"main","index":0}],[{"node":"Continue to next (morning)","type":"main","index":0}]]},"Parse session state":{"main":[[{"node":"Needs new session","type":"main","index":0}]]},"Fetch Active Members":{"main":[[{"node":"Merge Data","type":"main","index":1}]]},"Prepare session data":{"main":[[{"node":"Session data ready","type":"main","index":0}]]},"Send standup message":{"main":[[{"node":"Continue to next (morning)","type":"main","index":0},{"node":"Update Slack channel ID in Notion","type":"main","index":0}]]},"Create Notion session":{"main":[[{"node":"Prepare session data","type":"main","index":0}]]},"Evening session ready":{"main":[[{"node":"Store evening session in Redis","type":"main","index":0}],[{"node":"Continue to next (evening)","type":"main","index":0}]]},"Save session to Redis":{"main":[[{"node":"Send standup message","type":"main","index":0}]]},"Check developers found":{"main":[[{"node":"No developers found","type":"main","index":0}],[{"node":"Process each developer","type":"main","index":0}]]},"Check if members found":{"main":[[{"node":"Developer loop","type":"main","index":0}]]},"Fetch Evening Standups":{"main":[[{"node":"Merge Data","type":"main","index":0}]]},"Process each developer":{"main":[[],[{"node":"Validate and prepare member data","type":"main","index":0}]]},"Get active team members":{"main":[[{"node":"Check if members found","type":"main","index":0}]]},"Evening schedule trigger":{"main":[[{"node":"Fetch Active Members","type":"main","index":0},{"node":"Fetch Evening Standups","type":"main","index":0}]]},"Morning schedule trigger":{"main":[[{"node":"Fetch team members (morning)","type":"main","index":0},{"node":"Fetch today's morning standups","type":"main","index":0}]]},"Build evening session data":{"main":[[{"node":"Evening session ready","type":"main","index":0}]]},"Continue to next (evening)":{"main":[[{"node":"Process each developer","type":"main","index":0}]]},"Continue to next (morning)":{"main":[[{"node":"Developer loop","type":"main","index":0}]]},"Check evening Redis session":{"main":[[{"node":"Check evening session status","type":"main","index":0}]]},"Check evening session status":{"main":[[{"node":"Should proceed with evening session","type":"main","index":0}]]},"Check existing Redis session":{"main":[[{"node":"Parse session state","type":"main","index":0}]]},"Fetch team members (morning)":{"main":[[{"node":"Merge morning data","type":"main","index":0}]]},"Send evening standup message":{"main":[[{"node":"Log final result","type":"main","index":0}]]},"Build evening summary message":{"main":[[{"node":"Send to Admin Channel Evening","type":"main","index":0}]]},"Build morning summary message":{"main":[[{"node":"Send to Admin Channel","type":"main","index":0}]]},"Create evening Notion session":{"main":[[{"node":"Build evening session data","type":"main","index":0}]]},"Fetch today's morning standups":{"main":[[{"node":"Merge morning data","type":"main","index":1}]]},"Store evening session in Redis":{"main":[[{"node":"Send evening standup message","type":"main","index":0}]]},"Check if valid member (evening)":{"main":[[{"node":"Check evening Redis session","type":"main","index":0}],[{"node":"Continue to next (evening)","type":"main","index":0}]]},"Extract and validate member data":{"main":[[{"node":"Is valid member","type":"main","index":0}]]},"Validate and prepare member data":{"main":[[{"node":"Check if valid member (evening)","type":"main","index":0}]]},"Evening standup initiator trigger":{"main":[[{"node":"Get active team members (evening)","type":"main","index":0}]]},"Get active team members (evening)":{"main":[[{"node":"Check developers found","type":"main","index":0}]]},"Morning standup initiator trigger":{"main":[[{"node":"Get active team members","type":"main","index":0}]]},"Should proceed with evening session":{"main":[[{"node":"Create evening Notion session","type":"main","index":0}],[{"node":"Continue to next (evening)","type":"main","index":0}]]}}},"lastUpdatedBy":29,"workflowInfo":{"nodeCount":70,"nodeTypes":{"n8n-nodes-base.if":{"count":8},"n8n-nodes-base.code":{"count":10},"n8n-nodes-base.noOp":{"count":2},"n8n-nodes-base.merge":{"count":2},"n8n-nodes-base.redis":{"count":4},"n8n-nodes-base.slack":{"count":4},"n8n-nodes-base.notion":{"count":9},"n8n-nodes-base.stickyNote":{"count":25},"n8n-nodes-base.splitInBatches":{"count":2},"n8n-nodes-base.scheduleTrigger":{"count":4}}},"status":"published","readyToDemo":null,"user":{"name":"BytezTech","username":"chintan","bio":"Technology partner for startups and growing businesses. We build scalable Mobile Apps (Flutter, Native), Web Platforms (Laravel, MERN, Next.js), and AI/ML solutions using Python. Focused on clean architecture, security-first development, and long-term product scalability. Let’s build systems that grow with your business.","verified":true,"links":["https://byteztech.com/"],"avatar":"https://gravatar.com/avatar/78d67bdade378e9982a64f629cf9268fb40bb058b3c3316e7334fffd80ea1b83?r=pg&d=retro&size=200"},"nodes":[{"id":20,"icon":"fa:map-signs","name":"n8n-nodes-base.if","codex":{"data":{"alias":["Router","Filter","Condition","Logic","Boolean","Branch"],"details":"The IF node can be used to implement binary conditional logic in your workflow. You can set up one-to-many conditions to evaluate each item of data being inputted into the node. That data will either evaluate to TRUE or FALSE and route out of the node accordingly.\n\nThis node has multiple types of conditions: Bool, String, Number, and Date & Time.","resources":{"generic":[{"url":"https://n8n.io/blog/learn-to-automate-your-factorys-incident-reporting-a-step-by-step-guide/","icon":"🏭","label":"Learn to Automate Your Factory's Incident Reporting: A Step by Step Guide"},{"url":"https://n8n.io/blog/2021-the-year-to-automate-the-new-you-with-n8n/","icon":"☀️","label":"2021: The Year to Automate the New You with n8n"},{"url":"https://n8n.io/blog/why-business-process-automation-with-n8n-can-change-your-daily-life/","icon":"🧬","label":"Why business process automation with n8n can change your daily life"},{"url":"https://n8n.io/blog/create-a-toxic-language-detector-for-telegram/","icon":"🤬","label":"Create a toxic language detector for Telegram in 4 step"},{"url":"https://n8n.io/blog/no-code-ecommerce-workflow-automations/","icon":"store","label":"6 e-commerce workflows to power up your Shopify s"},{"url":"https://n8n.io/blog/how-to-build-a-low-code-self-hosted-url-shortener/","icon":"🔗","label":"How to build a low-code, self-hosted URL shortener in 3 steps"},{"url":"https://n8n.io/blog/automate-your-data-processing-pipeline-in-9-steps-with-n8n/","icon":"⚙️","label":"Automate your data processing pipeline in 9 steps"},{"url":"https://n8n.io/blog/how-to-get-started-with-crm-automation-and-no-code-workflow-ideas/","icon":"👥","label":"How to get started with CRM automation (with 3 no-code workflow ideas"},{"url":"https://n8n.io/blog/5-tasks-you-can-automate-with-notion-api/","icon":"⚡️","label":"5 tasks you can automate with the new Notion API "},{"url":"https://n8n.io/blog/automate-google-apps-for-productivity/","icon":"💡","label":"15 Google apps you can combine and automate to increase productivity"},{"url":"https://n8n.io/blog/automation-for-maintainers-of-open-source-projects/","icon":"🏷️","label":"How to automatically manage contributions to open-source projects"},{"url":"https://n8n.io/blog/how-uproc-scraped-a-multi-page-website-with-a-low-code-workflow/","icon":" 🕸️","label":"How uProc scraped a multi-page website with a low-code workflow"},{"url":"https://n8n.io/blog/5-workflow-automations-for-mattermost-that-we-love-at-n8n/","icon":"🤖","label":"5 workflow automations for Mattermost that we love at n8n"},{"url":"https://n8n.io/blog/why-this-product-manager-loves-workflow-automation-with-n8n/","icon":"🧠","label":"Why this Product Manager loves workflow automation with n8n"},{"url":"https://n8n.io/blog/sending-automated-congratulations-with-google-sheets-twilio-and-n8n/","icon":"🙌","label":"Sending Automated Congratulations with Google Sheets, Twilio, and n8n "},{"url":"https://n8n.io/blog/how-to-set-up-a-ci-cd-pipeline-with-no-code/","icon":"🎡","label":"How to set up a no-code CI/CD pipeline with GitHub and TravisCI"},{"url":"https://n8n.io/blog/benefits-of-automation-and-n8n-an-interview-with-hubspots-hugh-durkin/","icon":"🎖","label":"Benefits of automation and n8n: An interview with HubSpot's Hugh Durkin"},{"url":"https://n8n.io/blog/aws-workflow-automation/","label":"7 no-code workflow automations for Amazon Web Services"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.if/"}]},"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Flow"]}}},"group":"[\"transform\"]","defaults":{"name":"If","color":"#408000"},"iconData":{"icon":"map-signs","type":"icon"},"displayName":"If","typeVersion":2,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":24,"icon":"file:merge.svg","name":"n8n-nodes-base.merge","codex":{"data":{"alias":["Join","Concatenate","Wait"],"resources":{"generic":[{"url":"https://n8n.io/blog/how-to-sync-data-between-two-systems/","icon":"🏬","label":"How to synchronize data between two systems (one-way vs. two-way sync"},{"url":"https://n8n.io/blog/supercharging-your-conference-registration-process-with-n8n/","icon":"🎫","label":"Supercharging your conference registration process with n8n"},{"url":"https://n8n.io/blog/migrating-community-metrics-to-orbit-using-n8n/","icon":"📈","label":"Migrating Community Metrics to Orbit using n8n"},{"url":"https://n8n.io/blog/build-your-own-virtual-assistant-with-n8n-a-step-by-step-guide/","icon":"👦","label":"Build your own virtual assistant with n8n: A step by step guide"},{"url":"https://n8n.io/blog/sending-automated-congratulations-with-google-sheets-twilio-and-n8n/","icon":"🙌","label":"Sending Automated Congratulations with Google Sheets, Twilio, and n8n "},{"url":"https://n8n.io/blog/aws-workflow-automation/","label":"7 no-code workflow automations for Amazon Web Services"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.merge/"}]},"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Flow","Data Transformation"]}}},"group":"[\"transform\"]","defaults":{"name":"Merge"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF8xMTc3XzUxOCkiPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTAgNDhDMCAyMS40OTAzIDIxLjQ5MDMgMCA0OCAwSDExMkMxMzguNTEgMCAxNjAgMjEuNDkwMyAxNjAgNDhWNTZIMTk2LjI1MkMyNDAuNDM1IDU2IDI3Ni4yNTIgOTEuODE3MiAyNzYuMjUyIDEzNlYxOTJDMjc2LjI1MiAyMTQuMDkxIDI5NC4xNjEgMjMyIDMxNi4yNTIgMjMySDM1MlYyMjRDMzUyIDE5Ny40OSAzNzMuNDkgMTc2IDQwMCAxNzZINDY0QzQ5MC41MSAxNzYgNTEyIDE5Ny40OSA1MTIgMjI0VjI4OEM1MTIgMzE0LjUxIDQ5MC41MSAzMzYgNDY0IDMzNkg0MDBDMzczLjQ5IDMzNiAzNTIgMzE0LjUxIDM1MiAyODhWMjgwSDMxNi4yNTJDMjk0LjE2MSAyODAgMjc2LjI1MiAyOTcuOTA5IDI3Ni4yNTIgMzIwVjM3NkMyNzYuMjUyIDQyMC4xODMgMjQwLjQzNSA0NTYgMTk2LjI1MiA0NTZIMTYwVjQ2NEMxNjAgNDkwLjUxIDEzOC41MSA1MTIgMTEyIDUxMkg0OEMyMS40OTAzIDUxMiAwIDQ5MC41MSAwIDQ2NFY0MDBDMCAzNzMuNDkgMjEuNDkwMyAzNTIgNDggMzUySDExMkMxMzguNTEgMzUyIDE2MCAzNzMuNDkgMTYwIDQwMFY0MDhIMTk2LjI1MkMyMTMuOTI1IDQwOCAyMjguMjUyIDM5My42NzMgMjI4LjI1MiAzNzZWMzIwQzIyOC4yNTIgMjk0Ljc4NCAyMzguODU5IDI3Mi4wNDQgMjU1Ljg1MyAyNTZDMjM4Ljg1OSAyMzkuOTU2IDIyOC4yNTIgMjE3LjIxNiAyMjguMjUyIDE5MlYxMzZDMjI4LjI1MiAxMTguMzI3IDIxMy45MjUgMTA0IDE5Ni4yNTIgMTA0SDE2MFYxMTJDMTYwIDEzOC41MSAxMzguNTEgMTYwIDExMiAxNjBINDhDMjEuNDkwMyAxNjAgMCAxMzguNTEgMCAxMTJWNDhaTTEwNCA0OEMxMDguNDE4IDQ4IDExMiA1MS41ODE3IDExMiA1NlYxMDRDMTEyIDEwOC40MTggMTA4LjQxOCAxMTIgMTA0IDExMkg1NkM1MS41ODE3IDExMiA0OCAxMDguNDE4IDQ4IDEwNFY1NkM0OCA1MS41ODE3IDUxLjU4MTcgNDggNTYgNDhIMTA0Wk00NTYgMjI0QzQ2MC40MTggMjI0IDQ2NCAyMjcuNTgyIDQ2NCAyMzJWMjgwQzQ2NCAyODQuNDE4IDQ2MC40MTggMjg4IDQ1NiAyODhINDA4QzQwMy41ODIgMjg4IDQwMCAyODQuNDE4IDQwMCAyODBWMjMyQzQwMCAyMjcuNTgyIDQwMy41ODIgMjI0IDQwOCAyMjRINDU2Wk0xMTIgNDA4QzExMiA0MDMuNTgyIDEwOC40MTggNDAwIDEwNCA0MDBINTZDNTEuNTgxNyA0MDAgNDggNDAzLjU4MiA0OCA0MDhWNDU2QzQ4IDQ2MC40MTggNTEuNTgxNyA0NjQgNTYgNDY0SDEwNEMxMDguNDE4IDQ2NCAxMTIgNDYwLjQxOCAxMTIgNDU2VjQwOFoiIGZpbGw9IiM1NEI4QzkiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8xMTc3XzUxOCI+CjxyZWN0IHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo="},"displayName":"Merge","typeVersion":3,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":26,"icon":"fa:arrow-right","name":"n8n-nodes-base.noOp","codex":{"data":{"alias":["nothing"],"resources":{"generic":[{"url":"https://n8n.io/blog/learn-to-automate-your-factorys-incident-reporting-a-step-by-step-guide/","icon":"🏭","label":"Learn to Automate Your Factory's Incident Reporting: A Step by Step Guide"},{"url":"https://n8n.io/blog/2021-the-year-to-automate-the-new-you-with-n8n/","icon":"☀️","label":"2021: The Year to Automate the New You with n8n"},{"url":"https://n8n.io/blog/create-a-toxic-language-detector-for-telegram/","icon":"🤬","label":"Create a toxic language detector for Telegram in 4 step"},{"url":"https://n8n.io/blog/no-code-ecommerce-workflow-automations/","icon":"store","label":"6 e-commerce workflows to power up your Shopify s"},{"url":"https://n8n.io/blog/automate-your-data-processing-pipeline-in-9-steps-with-n8n/","icon":"⚙️","label":"Automate your data processing pipeline in 9 steps"},{"url":"https://n8n.io/blog/how-to-get-started-with-crm-automation-and-no-code-workflow-ideas/","icon":"👥","label":"How to get started with CRM automation (with 3 no-code workflow ideas"},{"url":"https://n8n.io/blog/5-tasks-you-can-automate-with-notion-api/","icon":"⚡️","label":"5 tasks you can automate with the new Notion API "},{"url":"https://n8n.io/blog/5-workflow-automations-for-mattermost-that-we-love-at-n8n/","icon":"🤖","label":"5 workflow automations for Mattermost that we love at n8n"},{"url":"https://n8n.io/blog/sending-automated-congratulations-with-google-sheets-twilio-and-n8n/","icon":"🙌","label":"Sending Automated Congratulations with Google Sheets, Twilio, and n8n "},{"url":"https://n8n.io/blog/how-to-set-up-a-ci-cd-pipeline-with-no-code/","icon":"🎡","label":"How to set up a no-code CI/CD pipeline with GitHub and TravisCI"},{"url":"https://n8n.io/blog/benefits-of-automation-and-n8n-an-interview-with-hubspots-hugh-durkin/","icon":"🎖","label":"Benefits of automation and n8n: An interview with HubSpot's Hugh Durkin"},{"url":"https://n8n.io/blog/aws-workflow-automation/","label":"7 no-code workflow automations for Amazon Web Services"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.noop/"}]},"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Helpers"]}}},"group":"[\"organization\"]","defaults":{"name":"No Operation, do nothing","color":"#b0b0b0"},"iconData":{"icon":"arrow-right","type":"icon"},"displayName":"No Operation, do nothing","typeVersion":1,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":33,"icon":"file:redis.svg","name":"n8n-nodes-base.redis","codex":{"data":{"resources":{"generic":[{"url":"https://n8n.io/blog/why-this-product-manager-loves-workflow-automation-with-n8n/","icon":"🧠","label":"Why this Product Manager loves workflow automation with n8n"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.redis/"}],"credentialDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/credentials/redis/"}]},"categories":["Development","Data & Storage"],"nodeVersion":"1.0","codexVersion":"1.0"}},"group":"[\"input\"]","defaults":{"name":"Redis"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MCIgaGVpZ2h0PSI2MCI+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGZpbGw9IiNBNDFFMTEiIGQ9Ik01Ny42NTYgNDMuOTljLTMuMjAxIDEuNjgzLTE5Ljc4NyA4LjU2MS0yMy4zMTggMTAuNDE3cy01LjQ5NCAxLjgzOC04LjI4My40OTRjLTIuNzktMS4zNDMtMjAuNDQ5LTguNTM1LTIzLjYyOS0xMC4wNjdDLjgzNCA0NC4wNjYuMDAyIDQzLjQyMi4wMDIgNDIuODExdi02LjExN3MyMi45OC01LjA0NSAyNi42OS02LjM4OCA0Ljk5NS0xLjM5IDguMTU0LS4yMjVjMy4xNiAxLjE2NSAyMi4wMzUgNC42MDMgMjUuMTU0IDUuNzU2djYuMDMyYzAgLjYwNS0uNzIgMS4yODMtMi4zNSAyLjEyNHoiLz48cGF0aCBmaWxsPSIjRDgyQzIwIiBkPSJNNTcuNjU2IDM3Ljg3MmMtMy4yMDEgMS42ODUtMTkuNzg3IDguNTYtMjMuMzE4IDEwLjQxN3MtNS40OTQgMS44MzgtOC4yODMuNDk0Yy0yLjc5LTEuMzQzLTIwLjQ0OS04LjUzNC0yMy42My0xMC4wNjhzLTMuMjQzLTIuNTg4LS4xMjItMy44MmwyNC4zODgtOS41MmMzLjcxLTEuMzQgNC45OTQtMS4zOSA4LjE1My0uMjI1czE5LjY0MyA3Ljc4IDIyLjc0NyA4Ljk1MWMzLjEwMyAxLjE3IDMuMjQgMi4wODYuMDM3IDMuNzg2eiIvPjxwYXRoIGZpbGw9IiNBNDFFMTEiIGQ9Ik01Ny42NTYgMzQuMDE1Yy0zLjIwMSAxLjY4My0xOS43ODcgOC41NjEtMjMuMzE4IDEwLjQxN3MtNS40OTQgMS44MzgtOC4yODMuNDk1Yy0yLjc5LTEuMzQ0LTIwLjQ0OS04LjUzNi0yMy42MjktMTAuMDY3Qy44MzQgMzQuMDkyLjAwMiAzMy40NDcuMDAyIDMyLjgzNlYyNi43MnMyMi45OC01LjA0NSAyNi42OS02LjM4N2MzLjcxMS0xLjM0MyA0Ljk5NS0xLjM5IDguMTU0LS4yMjUgMy4xNiAxLjE2NSAyMi4wMzUgNC42MDIgMjUuMTU0IDUuNzU2djYuMDMyYzAgLjYwNS0uNzIgMS4yODMtMi4zNSAyLjEyM3oiLz48cGF0aCBmaWxsPSIjRDgyQzIwIiBkPSJNNTcuNjU2IDI3Ljg5OGMtMy4yMDEgMS42ODUtMTkuNzg3IDguNTYxLTIzLjMxOCAxMC40MTdzLTUuNDk0IDEuODM4LTguMjgzLjQ5NWMtMi43OS0xLjM0NC0yMC40NDktOC41MzQtMjMuNjMtMTAuMDY3LTMuMTgtMS41MzQtMy4yNDMtMi41ODgtLjEyMi0zLjgybDI0LjM4OC05LjUyYzMuNzEtMS4zNDMgNC45OTQtMS4zOSA4LjE1My0uMjI1IDMuMTYgMS4xNjYgMTkuNjQ0IDcuNzg1IDIyLjc2NSA4LjkzNXMzLjI0IDIuMDg1LjAzOCAzLjc4NXoiLz48cGF0aCBmaWxsPSIjQTQxRTExIiBkPSJNNTcuNjU2IDIzLjY3MWMtMy4yMDEgMS42ODMtMTkuNzg3IDguNTYxLTIzLjMxOCAxMC40MTlzLTUuNDk0IDEuODM4LTguMjgzLjQ5NWMtMi43OS0xLjM0NC0yMC40NDktOC41MzUtMjMuNjI5LTEwLjA2OS0xLjU5Mi0uNzY1LTIuNDI0LTEuNDExLTIuNDI0LTIuMDJ2LTYuMTFzMjIuOTgtNS4wNDUgMjYuNjktNi4zODggNC45OTUtMS4zOSA4LjE1NC0uMjI1YzMuMTYgMS4xNjUgMjIuMDM1IDQuNTkxIDI1LjE1NCA1Ljc0NXY2LjAzMmMwIC42MDUtLjcyIDEuMjgzLTIuMzUgMi4xMjN6Ii8+PHBhdGggZmlsbD0iI0Q4MkMyMCIgZD0iTTU3LjY1NiAxNy41NTNjLTMuMjAxIDEuNjg1LTE5Ljc4NyA4LjU2MS0yMy4zMTggMTAuNDE3cy01LjQ5NCAxLjgzOC04LjI4My40OTVjLTIuNzktMS4zNDQtMjAuNDQ5LTguNTM0LTIzLjYzLTEwLjA2OHMtMy4yNDMtMi41ODctLjEyMi0zLjgybDI0LjM4OC05LjUyYzMuNzEtMS4zNDMgNC45OTQtMS4zOSA4LjE1My0uMjI2IDMuMTYgMS4xNjUgMTkuNjQzIDcuNzg1IDIyLjc2NSA4LjkzNnMzLjI0IDIuMDg1LjAzOCAzLjc4NXoiLz48cGF0aCBmaWxsPSIjRkZGIiBkPSJtMzEuNDk3IDE1LjAzMi0xLjg4LTMuMTUzLTYuMDAyLS41NDUgNC40OC0xLjYzTDI2Ljc1IDcuMmw0LjE5MiAxLjY1MyAzLjk1NS0xLjMwNS0xLjA3IDIuNTg2IDQuMDMyIDEuNTI0LTUuMTk4LjU0NnptLTEwLjAxNCA2LjI3NSAxMy45MDMtMi4xNTMtNC4yIDYuMjExem0tMTEuMTctNS4xNjdjMC0xLjYxIDMuMzE0LTIuOTA2IDcuNDMxLTIuOTA2IDQuMTE4IDAgNy40MzIgMS4yOTYgNy40MzIgMi45MDZzLTMuMzE0IDIuOTA1LTcuNDMyIDIuOTA1Yy00LjExNyAwLTcuNDMxLTEuMjk1LTcuNDMxLTIuOTA1Ii8+PHBhdGggZmlsbD0iIzdBMEMwMCIgZD0ibTUyLjIzMyAxNS43MTQtOC4yMjQgMy4yNzYtLjAwNy02LjU1NnoiLz48cGF0aCBmaWxsPSIjQUQyMTE1IiBkPSJtNDQuMDEgMTguOTkxLS44OS4zNTMtOC4yMTctMy4yNzYgOS4wOTQtMy42M3oiLz48L2c+PC9zdmc+"},"displayName":"Redis","typeVersion":1,"nodeCategories":[{"id":3,"name":"Data & Storage"},{"id":5,"name":"Development"}]},{"id":39,"icon":"fa:sync","name":"n8n-nodes-base.splitInBatches","codex":{"data":{"alias":["Loop","Concatenate","Batch","Split","Split In Batches"],"resources":{"generic":[{"url":"https://n8n.io/blog/how-uproc-scraped-a-multi-page-website-with-a-low-code-workflow/","icon":" 🕸️","label":"How uProc scraped a multi-page website with a low-code workflow"},{"url":"https://n8n.io/blog/benefits-of-automation-and-n8n-an-interview-with-hubspots-hugh-durkin/","icon":"🎖","label":"Benefits of automation and n8n: An interview with HubSpot's Hugh Durkin"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.splitinbatches/"}]},"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Flow"]}}},"group":"[\"organization\"]","defaults":{"name":"Loop Over Items","color":"#007755"},"iconData":{"icon":"sync","type":"icon"},"displayName":"Loop Over Items (Split in Batches)","typeVersion":3,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":40,"icon":"file:slack.svg","name":"n8n-nodes-base.slack","codex":{"data":{"alias":["human","form","wait","hitl","approval"],"resources":{"generic":[{"url":"https://n8n.io/blog/no-code-ecommerce-workflow-automations/","icon":"store","label":"6 e-commerce workflows to power up your Shopify s"},{"url":"https://n8n.io/blog/automate-your-data-processing-pipeline-in-9-steps-with-n8n/","icon":"⚙️","label":"Automate your data processing pipeline in 9 steps"},{"url":"https://n8n.io/blog/how-to-get-started-with-crm-automation-and-no-code-workflow-ideas/","icon":"👥","label":"How to get started with CRM automation (with 3 no-code workflow ideas"},{"url":"https://n8n.io/blog/5-tasks-you-can-automate-with-notion-api/","icon":"⚡️","label":"5 tasks you can automate with the new Notion API "},{"url":"https://n8n.io/blog/build-your-own-virtual-assistant-with-n8n-a-step-by-step-guide/","icon":"👦","label":"Build your own virtual assistant with n8n: A step by step guide"},{"url":"https://n8n.io/blog/how-to-automatically-give-kudos-to-contributors-with-github-slack-and-n8n/","icon":"👏","label":"How to automatically give kudos to contributors with GitHub, Slack, and n8n"},{"url":"https://n8n.io/blog/automations-for-activists/","icon":"✨","label":"How Common Knowledge use workflow automation for activism"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.slack/"}],"credentialDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/credentials/slack/"}]},"categories":["Communication","HITL"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"HITL":["Human in the Loop"]}}},"group":"[\"output\"]","defaults":{"name":"Slack"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiB2aWV3Qm94PSIwIDAgMTUwLjg1MiAxNTAuODUyIj48dXNlIHhsaW5rOmhyZWY9IiNhIiB4PSIuOTI2IiB5PSIuOTI2Ii8+PHN5bWJvbCBpZD0iYSIgb3ZlcmZsb3c9InZpc2libGUiPjxnIHN0cm9rZS13aWR0aD0iMS44NTIiPjxwYXRoIGZpbGw9IiNlMDFlNWEiIHN0cm9rZT0iI2UwMWU1YSIgZD0iTTQwLjc0MSA5My41NWMwLTguNzM1IDYuNjA3LTE1Ljc3MiAxNC44MTUtMTUuNzcyczE0LjgxNSA3LjAzNyAxNC44MTUgMTUuNzcydjM4LjgyNGMwIDguNzM3LTYuNjA3IDE1Ljc3NC0xNC44MTUgMTUuNzc0cy0xNC44MTUtNy4wMzctMTQuODE1LTE1Ljc3MnoiLz48cGF0aCBmaWxsPSIjZWNiMjJkIiBzdHJva2U9IiNlY2IyMmQiIGQ9Ik05My41NSAxMDcuNDA4Yy04LjczNSAwLTE1Ljc3Mi02LjYwNy0xNS43NzItMTQuODE1czcuMDM3LTE0LjgxNSAxNS43NzItMTQuODE1aDM4LjgyNmM4LjczNSAwIDE1Ljc3MiA2LjYwNyAxNS43NzIgMTQuODE1cy03LjAzNyAxNC44MTUtMTUuNzcyIDE0LjgxNXoiLz48cGF0aCBmaWxsPSIjMmZiNjdjIiBzdHJva2U9IiMyZmI2N2MiIGQ9Ik03Ny43NzggMTUuNzcyQzc3Ljc3OCA3LjAzNyA4NC4zODUgMCA5Mi41OTMgMHMxNC44MTUgNy4wMzcgMTQuODE1IDE1Ljc3MnYzOC44MjZjMCA4LjczNS02LjYwNyAxNS43NzItMTQuODE1IDE1Ljc3MnMtMTQuODE1LTcuMDM3LTE0LjgxNS0xNS43NzJ6Ii8+PHBhdGggZmlsbD0iIzM2YzVmMSIgc3Ryb2tlPSIjMzZjNWYxIiBkPSJNMTUuNzcyIDcwLjM3MUM3LjAzNyA3MC4zNzEgMCA2My43NjMgMCA1NS41NTZzNy4wMzctMTQuODE1IDE1Ljc3Mi0xNC44MTVoMzguODI2YzguNzM1IDAgMTUuNzcyIDYuNjA3IDE1Ljc3MiAxNC44MTVzLTcuMDM3IDE0LjgxNS0xNS43NzIgMTQuODE1eiIvPjxnIHN0cm9rZS1saW5lam9pbj0ibWl0ZXIiPjxwYXRoIGZpbGw9IiNlY2IyMmQiIHN0cm9rZT0iI2VjYjIyZCIgZD0iTTc3Ljc3OCAxMzMuMzMzYzAgOC4yMDggNi42MDcgMTQuODE1IDE0LjgxNSAxNC44MTVzMTQuODE1LTYuNjA3IDE0LjgxNS0xNC44MTUtNi42MDctMTQuODE1LTE0LjgxNS0xNC44MTVINzcuNzc4eiIvPjxwYXRoIGZpbGw9IiMyZmI2N2MiIHN0cm9rZT0iIzJmYjY3YyIgZD0iTTEzMy4zMzQgNzAuMzcxaC0xNC44MTVWNTUuNTU2YzAtOC4yMDcgNi42MDctMTQuODE1IDE0LjgxNS0xNC44MTVzMTQuODE1IDYuNjA3IDE0LjgxNSAxNC44MTUtNi42MDcgMTQuODE1LTE0LjgxNSAxNC44MTV6Ii8+PHBhdGggZmlsbD0iI2UwMWU1YSIgc3Ryb2tlPSIjZTAxZTVhIiBkPSJNMTQuODE1IDc3Ljc3OEgyOS42M3YxNC44MTVjMCA4LjIwNy02LjYwNyAxNC44MTUtMTQuODE1IDE0LjgxNVMwIDEwMC44IDAgOTIuNTkzczYuNjA3LTE0LjgxNSAxNC44MTUtMTQuODE1eiIvPjxwYXRoIGZpbGw9IiMzNmM1ZjEiIHN0cm9rZT0iIzM2YzVmMSIgZD0iTTcwLjM3MSAxNC44MTVWMjkuNjNINTUuNTU2Yy04LjIwNyAwLTE0LjgxNS02LjYwNy0xNC44MTUtMTQuODE1UzQ3LjM0OCAwIDU1LjU1NiAwczE0LjgxNSA2LjYwNyAxNC44MTUgMTQuODE1eiIvPjwvZz48L2c+PC9zeW1ib2w+PC9zdmc+"},"displayName":"Slack","typeVersion":2,"nodeCategories":[{"id":6,"name":"Communication"},{"id":28,"name":"HITL"}]},{"id":487,"icon":"file:notion.svg","name":"n8n-nodes-base.notion","codex":{"data":{"resources":{"generic":[{"url":"https://n8n.io/blog/5-tasks-you-can-automate-with-notion-api/","icon":"⚡️","label":"5 tasks you can automate with the new Notion API "}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.notion/"}],"credentialDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/credentials/notion/"}]},"categories":["Productivity"],"nodeVersion":"1.0","codexVersion":"1.0"}},"group":"[\"output\"]","defaults":{"name":"Notion"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03LjU4Mjc2IDYuOTc2NzlDOC44MjA0NyA3Ljk4MjM4IDkuMjg0NzkgNy45MDU2NiAxMS42MDkxIDcuNzUwNTdMMzMuNTIwNiA2LjQzNDg4QzMzLjk4NTMgNi40MzQ4OCAzMy41OTg5IDUuOTcxMjcgMzMuNDQzOSA1Ljg5NDIzTDI5LjgwNDkgMy4yNjM0OEMyOS4xMDc2IDIuNzIyMTMgMjguMTc4NiAyLjEwMjE3IDI2LjM5ODIgMi4yNTcyNkw1LjE4MTE1IDMuODA0NzZDNC40MDczNiAzLjg4MTQ4IDQuMjUyODIgNC4yNjgzNyA0LjU2MDk2IDQuNTc4NDdMNy41ODI3NiA2Ljk3Njc5Wk04Ljg5ODI5IDEyLjA4MzNWMzUuMTM4MUM4Ljg5ODI5IDM2LjM3NzEgOS41MTc0NiAzNi44NDA3IDEwLjkxMSAzNi43NjRMMzQuOTkxOSAzNS4zNzA2QzM2LjM4NjIgMzUuMjkzOSAzNi41NDE1IDM0LjQ0MTcgMzYuNTQxNSAzMy40MzUyVjEwLjUzNTFDMzYuNTQxNSA5LjUzMDE5IDM2LjE1NDkgOC45ODgyOSAzNS4zMDE0IDkuMDY1NjRMMTAuMTM2NyAxMC41MzUxQzkuMjA3OTkgMTAuNjEzMSA4Ljg5ODIxIDExLjA3NzcgOC44OTgyMSAxMi4wODMzSDguODk4MjlaTTMyLjY3MDggMTMuMzJDMzIuODI1MiAxNC4wMTcgMzIuNjcwOCAxNC43MTMzIDMxLjk3MjUgMTQuNzkxN0wzMC44MTIzIDE1LjAyMjlWMzIuMDQzNEMyOS44MDQ5IDMyLjU4NDggMjguODc1OSAzMi44OTQ0IDI4LjEwMTggMzIuODk0NEMyNi44NjI1IDMyLjg5NDQgMjYuNTUyMSAzMi41MDcyIDI1LjYyMzcgMzEuMzQ3NEwxOC4wMzQzIDE5LjQzMjlWMzAuOTYwNUwyMC40MzU5IDMxLjUwMjRDMjAuNDM1OSAzMS41MDI0IDIwLjQzNTkgMzIuODk0NCAxOC40OTgzIDMyLjg5NDRMMTMuMTU2OCAzMy4yMDQyQzEzLjAwMTYgMzIuODk0NCAxMy4xNTY4IDMyLjEyMTQgMTMuNjk4NiAzMS45NjY1TDE1LjA5MjUgMzEuNTgwMlYxNi4zMzg1TDEzLjE1NzIgMTYuMTgzNEMxMy4wMDE5IDE1LjQ4NjQgMTMuMzg4NSAxNC40ODE0IDE0LjQ3MzMgMTQuNDAzNUwyMC4yMDM1IDE0LjAxNzJMMjguMTAxOCAyNi4wODY4VjE1LjQwOTdMMjYuMDg4MSAxNS4xNzg2QzI1LjkzMzUgMTQuMzI2NSAyNi41NTIxIDEzLjcwNzggMjcuMzI2NSAxMy42MzExTDMyLjY3MDggMTMuMzJaTTMuMzk5NzMgMS43MTU5OEwyNS40Njg4IDAuMDkwNzQ1N0MyOC4xNzkgLTAuMTQxNjg4IDI4Ljg3NjMgMC4wMTQwMjQ1IDMwLjU3OTYgMS4yNTEzNUwzNy42MjQzIDYuMjAyNzZDMzguNzg2NyA3LjA1NDIxIDM5LjE3NDIgNy4yODYwMiAzOS4xNzQyIDguMjE0MTlWMzUuMzcwNkMzOS4xNzQyIDM3LjA3MjYgMzguNTU0MiAzOC4wNzkxIDM2LjM4NjUgMzguMjMzMUwxMC43NTc3IDM5Ljc4MDdDOS4xMzA0OSAzOS44NTgzIDguMzU2MDcgMzkuNjI2NCA3LjUwMzkyIDM4LjU0MjZMMi4zMTYwOCAzMS44MTE3QzEuMzg2NTggMzAuNTcyNiAxIDI5LjY0NTcgMSAyOC41NjEzVjQuNDIyODNDMSAzLjAzMTA1IDEuNjIwMTkgMS44NzAwNSAzLjM5OTczIDEuNzE1OThWMS43MTU5OFoiIGZpbGw9ImJsYWNrIi8+Cjwvc3ZnPgo="},"displayName":"Notion","typeVersion":2,"nodeCategories":[{"id":4,"name":"Productivity"}]},{"id":565,"icon":"fa:sticky-note","name":"n8n-nodes-base.stickyNote","codex":{"data":{"alias":["Comments","Notes","Sticky"],"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Helpers"]}}},"group":"[\"input\"]","defaults":{"name":"Sticky Note","color":"#FFD233"},"iconData":{"icon":"sticky-note","type":"icon"},"displayName":"Sticky Note","typeVersion":1,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":834,"icon":"file:code.svg","name":"n8n-nodes-base.code","codex":{"data":{"alias":["cpde","Javascript","JS","Python","Script","Custom Code","Function"],"details":"The Code node allows you to execute JavaScript in your workflow.","resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code/"}]},"categories":["Development","Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Helpers","Data Transformation"]}}},"group":"[\"transform\"]","defaults":{"name":"Code"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF8xMTcxXzQ0MSkiPgo8cGF0aCBkPSJNMTcwLjI4MyA0OEgxOTYuNUMyMDMuMTI3IDQ4IDIwOC41IDQyLjYyNzQgMjA4LjUgMzZWMTJDMjA4LjUgNS4zNzI1OCAyMDMuMTI3IDAgMTk2LjUgMEgxNzAuMjgzQzEyNi4xIDAgOTAuMjgzIDM1LjgxNzIgOTAuMjgzIDgwVjE3NkM5MC4yODMgMjA2LjkyOCA2NS4yMTA5IDIzMiAzNC4yODMgMjMySDIzQzE2LjM3MjYgMjMyIDExIDIzNy4zNzIgMTEgMjQ0VjI2OEMxMSAyNzQuNjI3IDE2LjM3MjQgMjgwIDIyLjk5OTYgMjgwTDM0LjI4MyAyODBDNjUuMjEwOSAyODAgOTAuMjgzIDMwNS4wNzIgOTAuMjgzIDMzNlY0NDBDOTAuMjgzIDQ3OS43NjQgMTIyLjUxOCA1MTIgMTYyLjI4MyA1MTJIMTk2LjVDMjAzLjEyNyA1MTIgMjA4LjUgNTA2LjYyNyAyMDguNSA1MDBWNDc2QzIwOC41IDQ2OS4zNzMgMjAzLjEyNyA0NjQgMTk2LjUgNDY0SDE2Mi4yODNDMTQ5LjAyOCA0NjQgMTM4LjI4MyA0NTMuMjU1IDEzOC4yODMgNDQwVjMzNkMxMzguMjgzIDMwOS4wMjIgMTI4LjAxMSAyODQuNDQzIDExMS4xNjQgMjY1Ljk2MUMxMDYuMTA5IDI2MC40MTYgMTA2LjEwOSAyNTEuNTg0IDExMS4xNjQgMjQ2LjAzOUMxMjguMDExIDIyNy41NTcgMTM4LjI4MyAyMDIuOTc4IDEzOC4yODMgMTc2VjgwQzEzOC4yODMgNjIuMzI2OSAxNTIuNjEgNDggMTcwLjI4MyA0OFoiIGZpbGw9IiNGRjk5MjIiLz4KPHBhdGggZD0iTTMwNSAzNkMzMDUgNDIuNjI3NCAzMTAuMzczIDQ4IDMxNyA0OEgzNDIuOTc5QzM2MC42NTIgNDggMzc0Ljk3OCA2Mi4zMjY5IDM3NC45NzggODBWMTc2QzM3NC45NzggMjAyLjk3OCAzODUuMjUxIDIyNy41NTcgNDAyLjA5OCAyNDYuMDM5QzQwNy4xNTMgMjUxLjU4NCA0MDcuMTUzIDI2MC40MTYgNDAyLjA5OCAyNjUuOTYxQzM4NS4yNTEgMjg0LjQ0MyAzNzQuOTc4IDMwOS4wMjIgMzc0Ljk3OCAzMzZWNDMyQzM3NC45NzggNDQ5LjY3MyAzNjAuNjUyIDQ2NCAzNDIuOTc5IDQ2NEgzMTdDMzEwLjM3MyA0NjQgMzA1IDQ2OS4zNzMgMzA1IDQ3NlY1MDBDMzA1IDUwNi42MjcgMzEwLjM3MyA1MTIgMzE3IDUxMkgzNDIuOTc5QzM4Ny4xNjEgNTEyIDQyMi45NzggNDc2LjE4MyA0MjIuOTc4IDQzMlYzMzZDNDIyLjk3OCAzMDUuMDcyIDQ0OC4wNTEgMjgwIDQ3OC45NzkgMjgwSDQ5MEM0OTYuNjI3IDI4MCA1MDIgMjc0LjYyOCA1MDIgMjY4VjI0NEM1MDIgMjM3LjM3MyA0OTYuNjI4IDIzMiA0OTAgMjMyTDQ3OC45NzkgMjMyQzQ0OC4wNTEgMjMyIDQyMi45NzggMjA2LjkyOCA0MjIuOTc4IDE3NlY4MEM0MjIuOTc4IDM1LjgxNzIgMzg3LjE2MSAwIDM0Mi45NzkgMEgzMTdDMzEwLjM3MyAwIDMwNSA1LjM3MjU4IDMwNSAxMlYzNloiIGZpbGw9IiNGRjk5MjIiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8xMTcxXzQ0MSI+CjxyZWN0IHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo="},"displayName":"Code","typeVersion":2,"nodeCategories":[{"id":5,"name":"Development"},{"id":9,"name":"Core Nodes"}]},{"id":839,"icon":"fa:clock","name":"n8n-nodes-base.scheduleTrigger","codex":{"data":{"alias":["Time","Scheduler","Polling","Cron","Interval"],"resources":{"generic":[],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.scheduletrigger/"}]},"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0"}},"group":"[\"trigger\",\"schedule\"]","defaults":{"name":"Schedule Trigger","color":"#31C49F"},"iconData":{"icon":"clock","type":"icon"},"displayName":"Schedule Trigger","typeVersion":1,"nodeCategories":[{"id":9,"name":"Core Nodes"}]}],"categories":[{"id":46,"name":"Project Management"},{"id":47,"name":"AI Chatbot"}],"image":[]}}