🔔 Team Notifications
🎯 Mục tiêu bài học
Sau bài học này, bạn sẽ:
✅ Xây dựng daily standup collector bot
✅ Tạo project status updates tự động
✅ Implement smart deadline reminders với escalation
✅ Thiết kế system alerts và new hire welcome workflows
Team communication là critical nhưng thường bị neglect. Bài này hướng dẫn automate notifications để team luôn được informed mà không overwhelmed.
🔍 Team Notification Types
What to Automate:
Checkpoint
Có mấy loại team notifications chính?
⚡ Workflow 1: Daily Standup Bot
Auto-Collect Standups:
Standup Collector
Standup Prompt Message:
1{2 "blocks": [3 {4 "type": "header",5 "text": {6 "type": "plain_text",7 "text": "☀️ Good Morning! Time for Standup"8 }9 },10 {11 "type": "section",12 "text": {13 "type": "mrkdwn",14 "text": "Please share your standup by clicking the button below:"15 }16 },17 {18 "type": "actions",19 "elements": [20 {21 "type": "button",22 "text": {23 "type": "plain_text",24 "text": "📝 Submit Standup"25 },26 "style": "primary",27 "action_id": "submit_standup",28 "url": "https://n8n.yourdomain.com/webhook/standup-form"29 }30 ]31 },32 {33 "type": "context",34 "elements": [35 {36 "type": "mrkdwn",37 "text": "⏰ Please submit by 11 AM"38 }39 ]40 }41 ]42}Standup Summary Generator:
1const standups = $input.all();23const today = new Date().toLocaleDateString('en-US', {4 weekday: 'long',5 month: 'long',6 day: 'numeric'7});89// Group by team/project if needed10const summary = standups.map(s => {11 const user = s.json;12 return `13*${user.name}*14✅ Yesterday: ${user.yesterday}15�� Today: ${user.today}16${user.blockers ? `🚧 Blockers: ${user.blockers}` : ''}17 `;18}).join('\n---\n');1920// Find non-responders21const allMembers = ['Alice', 'Bob', 'Charlie', 'Diana'];22const responders = standups.map(s => s.json.name);23const missing = allMembers.filter(m => !responders.includes(m));2425return {26 title: `📋 Standup Summary - ${today}`,27 summary,28 responderCount: standups.length,29 totalMembers: allMembers.length,30 missing31};Checkpoint
Standup collector bot thu thập responses trong bao lâu?
🔧 Workflow 2: Project Status Updates
Weekly Project Report:
Weekly Project Update
Project Status Template:
1const jira = $('Get Jira').item.json;2const github = $('Get GitHub').item.json;3const time = $('Get Time').item.json;45const report = {6 blocks: [7 {8 type: "header",9 text: {10 type: "plain_text",11 text: `📊 Weekly Status: ${jira.projectName}`12 }13 },14 {15 type: "section",16 fields: [17 {18 type: "mrkdwn",19 text: `*Sprint Progress*\n${jira.completed}/${jira.total} tasks (${Math.round(jira.completed/jira.total*100)}%)`20 },21 {22 type: "mrkdwn",23 text: `*PRs Merged*\n${github.merged} this week`24 },25 {26 type: "mrkdwn",27 text: `*Hours Logged*\n${time.hours}h`28 },29 {30 type: "mrkdwn",31 text: `*Velocity*\n${jira.velocity} points`32 }33 ]34 },35 {36 type: "section",37 text: {38 type: "mrkdwn",39 text: `*🎯 Completed This Week*\n${jira.completedItems.map(i => `• ${i}`).join('\n')}`40 }41 },42 {43 type: "section",44 text: {45 type: "mrkdwn",46 text: `*📅 Next Week*\n${jira.nextWeek.map(i => `• ${i}`).join('\n')}`47 }48 },49 jira.blockers.length > 0 ? {50 type: "section",51 text: {52 type: "mrkdwn",53 text: `*🚧 Blockers*\n${jira.blockers.map(b => `• ${b}`).join('\n')}`54 }55 } : null,56 {57 type: "context",58 elements: [59 {60 type: "mrkdwn",61 text: `Generated at ${new Date().toLocaleString()} | <${jira.boardUrl}|View Board>`62 }63 ]64 }65 ].filter(Boolean)66};6768return report;Checkpoint
Weekly project report lấy data từ những sources nào?
🏗️ Workflow 3: Smart Deadline Reminders
Escalating Reminders:
Deadline Reminder
Reminder Logic:
1const deadlines = $input.all();2const now = new Date();34const reminders = [];56for (const dl of deadlines) {7 const dueDate = new Date(dl.json.dueDate);8 const hoursUntil = (dueDate - now) / (1000 * 60 * 60);9 const daysUntil = hoursUntil / 24;10 11 let reminder = null;12 13 if (daysUntil <= 0) {14 // Overdue15 reminder = {16 type: 'overdue',17 emoji: '🔴',18 message: `OVERDUE: ${dl.json.task}`,19 urgency: 'critical',20 escalate: true,21 assignee: dl.json.assignee,22 manager: dl.json.manager23 };24 } else if (daysUntil <= 1) {25 reminder = {26 type: '1day',27 emoji: '⚠️',28 message: `Due tomorrow: ${dl.json.task}`,29 urgency: 'high',30 assignee: dl.json.assignee31 };32 } else if (daysUntil <= 3) {33 reminder = {34 type: '3days',35 emoji: '📅',36 message: `Due in ${Math.ceil(daysUntil)} days: ${dl.json.task}`,37 urgency: 'medium',38 assignee: dl.json.assignee39 };40 } else if (daysUntil <= 7 && Math.round(daysUntil) === 7) {41 reminder = {42 type: '7days',43 emoji: '📋',44 message: `Coming up next week: ${dl.json.task}`,45 urgency: 'low',46 assignee: dl.json.assignee47 };48 }49 50 if (reminder) {51 reminders.push(reminder);52 }53}5455return { reminders };Checkpoint
Deadline reminders escalate qua những mức nào?
📊 Workflow 4: System Alerts
Infrastructure Monitoring:
System Alert
Alert Message Template:
1const alert = $input.item.json;23const severityConfig = {4 critical: {5 color: '#dc3545',6 emoji: '🚨',7 mention: '<!channel>',8 action: 'PAGE ON-CALL'9 },10 warning: {11 color: '#ffc107',12 emoji: '⚠️',13 mention: '@devops-team',14 action: 'INVESTIGATE'15 },16 info: {17 color: '#17a2b8',18 emoji: 'ℹ️',19 mention: '',20 action: 'MONITOR'21 }22};2324const config = severityConfig[alert.severity] || severityConfig.info;2526const message = {27 channel: '#alerts',28 attachments: [29 {30 color: config.color,31 blocks: [32 {33 type: "section",34 text: {35 type: "mrkdwn",36 text: `${config.emoji} *${alert.severity.toUpperCase()}* ${config.mention}\n\n*${alert.title}*`37 }38 },39 {40 type: "section",41 fields: [42 {43 type: "mrkdwn",44 text: `*Service:*\n${alert.service}`45 },46 {47 type: "mrkdwn",48 text: `*Region:*\n${alert.region}`49 },50 {51 type: "mrkdwn",52 text: `*Action:*\n${config.action}`53 },54 {55 type: "mrkdwn",56 text: `*Time:*\n${new Date().toLocaleString()}`57 }58 ]59 },60 {61 type: "section",62 text: {63 type: "mrkdwn",64 text: `\`\`\`${alert.details}\`\`\``65 }66 },67 {68 type: "actions",69 elements: [70 {71 type: "button",72 text: {73 type: "plain_text",74 text: "📊 Dashboard"75 },76 url: alert.dashboardUrl77 },78 {79 type: "button",80 text: {81 type: "plain_text",82 text: "📋 Runbook"83 },84 url: alert.runbookUrl85 },86 {87 type: "button",88 text: {89 type: "plain_text",90 text: "✅ Acknowledge"91 },92 action_id: "ack_alert",93 value: alert.id94 }95 ]96 }97 ]98 }99 ]100};101102return message;Checkpoint
System alerts phân loại severity thành những levels nào?
💡 Workflow 5: Meeting Reminders
Team Meeting Reminder:
Meeting Reminder
Meeting Reminder Message:
1const meeting = $input.item.json;23const formatAttendees = (attendees) => {4 const count = attendees.length;5 const names = attendees.slice(0, 3).map(a => a.name).join(', ');6 return count > 3 ? `${names} +${count - 3} others` : names;7};89const reminder = {10 blocks: [11 {12 type: "section",13 text: {14 type: "mrkdwn",15 text: `🔔 *Meeting starting in 15 minutes*`16 }17 },18 {19 type: "section",20 text: {21 type: "mrkdwn",22 text: `*${meeting.summary}*\n📍 ${meeting.location || meeting.hangoutLink || 'Location TBD'}\n👥 ${formatAttendees(meeting.attendees)}`23 }24 },25 meeting.hangoutLink ? {26 type: "actions",27 elements: [28 {29 type: "button",30 text: {31 type: "plain_text",32 text: "🎥 Join Meeting"33 },34 style: "primary",35 url: meeting.hangoutLink36 }37 ]38 } : null,39 meeting.agenda ? {40 type: "section",41 text: {42 type: "mrkdwn",43 text: `*Agenda:*\n${meeting.agenda.substring(0, 200)}...`44 }45 } : null46 ].filter(Boolean)47};4849return reminder;Checkpoint
Meeting reminder gửi trước meeting bao nhiêu phút?
🌟 Workflow 6: New Hire Welcome
Automated Onboarding Notifications:
New Hire Welcome
Welcome Message:
1const newHire = $input.item.json;23const welcomeMessage = {4 channel: '#general',5 blocks: [6 {7 type: "header",8 text: {9 type: "plain_text",10 text: `🎉 Welcome to the team, ${newHire.firstName}!`11 }12 },13 {14 type: "section",15 text: {16 type: "mrkdwn",17 text: `Please join me in welcoming *${newHire.firstName} ${newHire.lastName}* who is joining us as *${newHire.role}* on the *${newHire.team}* team!`18 },19 accessory: newHire.photoUrl ? {20 type: "image",21 image_url: newHire.photoUrl,22 alt_text: newHire.firstName23 } : null24 },25 {26 type: "section",27 text: {28 type: "mrkdwn",29 text: `📍 *Location:* ${newHire.location}\n📧 *Email:* ${newHire.email}\n👤 *Manager:* ${newHire.manager}`30 }31 },32 newHire.funFact ? {33 type: "section",34 text: {35 type: "mrkdwn",36 text: `💡 *Fun fact:* ${newHire.funFact}`37 }38 } : null,39 {40 type: "context",41 elements: [42 {43 type: "mrkdwn",44 text: `Start date: ${newHire.startDate} | Say hi 👋`45 }46 ]47 }48 ].filter(Boolean)49};5051return welcomeMessage;Checkpoint
New hire welcome workflow bao gồm những bước nào?
📋 Best Practices
DO:
- ✅ Be concise - people skim
- ✅ Include action items clearly
- ✅ Respect time zones
- ✅ Allow opt-out/mute options
- ✅ Batch non-urgent notifications
DON'T:
- ❌ Over-notify (notification fatigue)
- ❌ Use @channel for everything
- ❌ Send at odd hours
- ❌ Repeat the same info
- ❌ Make critical alerts look like regular ones
Notification Frequency Guide:
| Category | Frequency |
|---|---|
| Critical Alerts | Immediate |
| Important Updates | Within 1 hour |
| Status Updates | Daily digest |
| FYI Information | Weekly summary |
| Announcements | As needed (rare) |
Checkpoint
Tại sao notification fatigue là vấn đề cần tránh?
📝 Bài Tập Thực Hành
Build team notification system:
- Create standup collector bot
- Build weekly project status update
- Implement smart deadline reminders
- Set up meeting reminder system
- Design new hire welcome workflow
Keep your team in sync! 🔔
Checkpoint
Bạn đã hoàn thành những challenges nào trong bài tập?
🧠 Key Takeaways
- 🔔 Less is more - Quality over quantity
- 📊 Digest when possible - Batch updates
- 🎯 Target right audience - Don't spam everyone
- ⚡ Reserve urgency - For truly urgent items
- 📱 Multi-channel - Right message, right channel
Checkpoint
Tại sao nên reserve urgency for truly urgent items?
🚀 Bài tiếp theo
Document Workflows — Approvals, versioning, và document automation.
