MinAI - Về trang chủ
Lý thuyết
4/1345 phút
Đang tải...

Personal Dashboards

Tạo daily briefings và personal dashboards với n8n - aggregate data từ nhiều nguồn thành một view

📊 Personal Dashboards

Dashboard

0

🎯 Mục tiêu bài học

TB5 min

Sau bài học này, bạn sẽ:

✅ Tạo morning briefing email tự động

✅ Xây dựng weekly dashboard với multiple data sources

✅ Implement Slack dashboard commands

✅ Thiết kế Notion dashboard page với real-time data

Start mỗi ngày với tất cả thông tin cần thiết ở một nơi. Bài này hướng dẫn tạo automated personal dashboards và morning briefings.

1

🔍 Dashboard Automation Overview

TB5 min

What to Include:

📊Personal Dashboard Components
📅Time & Calendar
Today's date & weather
Upcoming meetings
Deadlines this week
Important anniversaries
Tasks & Goals
Priority tasks
Overdue items
Weekly/monthly goals
Habit tracking
📧Communications
Unread email count
VIP messages
Slack notifications
Pending responses
📈Metrics
Personal KPIs
Project progress
Financial overview
Health data
📰Information
News highlights
Saved articles
Social updates
Learning progress

Checkpoint

Personal dashboard nên bao gồm những components nào?

2

⚡ Workflow 1: Morning Briefing

TB5 min

Daily Briefing Email:

Morning Briefing

Schedule: 6 AM Daily
Parallel: Weather, Calendar, Tasks, Email Stats, News, Quote
🔀Merge All Data
📝Generate HTML Briefing
📧Send Email / Slack

Get Weather Data:

JSON
1{
2 "name": "Get Weather",
3 "type": "n8n-nodes-base.httpRequest",
4 "parameters": {
5 "url": "https://api.openweathermap.org/data/2.5/weather",
6 "qs": {
7 "q": "Ho Chi Minh City",
8 "appid": "={{ $credentials.openWeatherApiKey }}",
9 "units": "metric"
10 }
11 }
12}

Generate Briefing HTML:

JavaScript
1const weather = $('Get Weather').item.json;
2const events = $('Get Calendar').all();
3const tasks = $('Get Tasks').all();
4const emailStats = $('Get Email Stats').item.json;
5const news = $('Get News').all();
6
7const today = new Date();
8const dateStr = today.toLocaleDateString('en-US', {
9 weekday: 'long',
10 year: 'numeric',
11 month: 'long',
12 day: 'numeric'
13});
14
15const briefing = `
16<!DOCTYPE html>
17<html>
18<head>
19 <style>
20 body {
21 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
22 max-width: 600px;
23 margin: 0 auto;
24 padding: 20px;
25 background: #f5f5f5;
26 }
27 .card {
28 background: white;
29 border-radius: 12px;
30 padding: 20px;
31 margin: 15px 0;
32 box-shadow: 0 2px 4px rgba(0,0,0,0.1);
33 }
34 h1 { color: #333; font-size: 24px; }
35 h2 { color: #555; font-size: 18px; border-bottom: 2px solid #4CAF50; padding-bottom: 5px; }
36 .weather { display: flex; align-items: center; gap: 15px; }
37 .weather-temp { font-size: 48px; font-weight: bold; color: #4CAF50; }
38 .task { padding: 8px 0; border-bottom: 1px solid #eee; }
39 .task.priority { color: #e74c3c; font-weight: bold; }
40 .event { padding: 8px 0; display: flex; gap: 10px; }
41 .event-time { color: #888; min-width: 80px; }
42 .stat { display: inline-block; margin: 10px 20px 10px 0; }
43 .stat-value { font-size: 24px; font-weight: bold; color: #4CAF50; }
44 .stat-label { color: #888; font-size: 12px; }
45 .news-item { padding: 10px 0; border-bottom: 1px solid #eee; }
46 </style>
47</head>
48<body>
49 <h1> Good Morning!</h1>
50 <p style="color: #888;">${dateStr}</p>
51
52 <!-- Weather -->
53 <div class="card">
54 <div class="weather">
55 <div class="weather-temp">${Math.round(weather.main.temp)}°</div>
56 <div>
57 <div>${weather.weather[0].description}</div>
58 <div style="color: #888;">Feels like ${Math.round(weather.main.feels_like)}°</div>
59 <div style="color: #888;">Humidity: ${weather.main.humidity}%</div>
60 </div>
61 </div>
62 </div>
63
64 <!-- Email Stats -->
65 <div class="card">
66 <h2> Inbox Status</h2>
67 <div class="stat">
68 <div class="stat-value">${emailStats.unread}</div>
69 <div class="stat-label">Unread</div>
70 </div>
71 <div class="stat">
72 <div class="stat-value">${emailStats.vip}</div>
73 <div class="stat-label">VIP</div>
74 </div>
75 <div class="stat">
76 <div class="stat-value">${emailStats.needsResponse}</div>
77 <div class="stat-label">Need Response</div>
78 </div>
79 </div>
80
81 <!-- Calendar -->
82 <div class="card">
83 <h2> Today's Schedule</h2>
84 ${events.length === 0 ? '<p style="color: #888;">No meetings today! 🎉</p>' : ''}
85 ${events.slice(0, 5).map(e => `
86 <div class="event">
87 <div class="event-time">${new Date(e.json.start.dateTime).toLocaleTimeString('en-US', {hour: '2-digit', minute:'2-digit'})}</div>
88 <div>${e.json.summary}</div>
89 </div>
90 `).join('')}
91 ${events.length > 5 ? `<p style="color: #888;">+${events.length - 5} more</p>` : ''}
92 </div>
93
94 <!-- Tasks -->
95 <div class="card">
96 <h2> Priority Tasks</h2>
97 ${tasks.slice(0, 5).map(t => `
98 <div class="task ${t.json.priority === 'high' ? 'priority' : ''}">
99 ${t.json.title}
100 </div>
101 `).join('')}
102 ${tasks.length > 5 ? `<p style="color: #888;">+${tasks.length - 5} more tasks</p>` : ''}
103 </div>
104
105 <!-- News -->
106 <div class="card">
107 <h2> Headlines</h2>
108 ${news.slice(0, 3).map(n => `
109 <div class="news-item">
110 <a href="${n.json.url}" style="color: #1a73e8; text-decoration: none;">${n.json.title}</a>
111 <div style="color: #888; font-size: 12px;">${n.json.source}</div>
112 </div>
113 `).join('')}
114 </div>
115
116 <p style="text-align: center; color: #888; font-size: 12px; margin-top: 30px;">
117 Have a productive day! <br>
118 <em>Generated by n8n at ${new Date().toLocaleTimeString()}</em>
119 </p>
120</body>
121</html>
122`;
123
124return { briefing };

Checkpoint

Morning briefing email thu thập data từ bao nhiêu nguồn?

3

🔧 Workflow 2: Weekly Dashboard

TB5 min

Weekly Stats Summary:

Weekly Dashboard

Schedule: Monday 8 AM
Parallel: Calendar Stats, Tasks, Time Tracking, Project Progress, Financial Summary
🔢Calculate KPIs
📊Generate Dashboard
📝Send to Notion Page

Calculate Weekly KPIs:

JavaScript
1const calendar = $('Get Calendar Stats').item.json;
2const tasks = $('Get Tasks').item.json;
3const timeTracking = $('Get Time Tracking').item.json;
4
5// Calculate metrics
6const kpis = {
7 // Meeting efficiency
8 totalMeetingHours: calendar.totalMinutes / 60,
9 focusTimeHours: 40 - (calendar.totalMinutes / 60),
10 meetingEfficiency: calendar.meetingsWithOutcome / calendar.totalMeetings * 100,
11
12 // Task completion
13 tasksCompleted: tasks.completed,
14 tasksCreated: tasks.created,
15 completionRate: tasks.completed / tasks.created * 100,
16
17 // Time tracking
18 productiveHours: timeTracking.productive,
19 distractedHours: timeTracking.distracted,
20 productivityScore: timeTracking.productive / (timeTracking.productive + timeTracking.distracted) * 100,
21
22 // Trends
23 meetingsTrend: calendar.totalMeetings > calendar.lastWeekMeetings ? 'up' : 'down',
24 tasksTrend: tasks.completed > tasks.lastWeekCompleted ? 'up' : 'down'
25};
26
27// Set targets and status
28kpis.focusTimeTarget = 20; // hours
29kpis.focusTimeStatus = kpis.focusTimeHours >= kpis.focusTimeTarget ? 'on-track' : 'behind';
30
31kpis.completionTarget = 80; // percent
32kpis.completionStatus = kpis.completionRate >= kpis.completionTarget ? 'on-track' : 'behind';
33
34return kpis;

Checkpoint

Weekly dashboard tính toán những KPIs nào?

4

🏗️ Workflow 3: Real-Time Slack Dashboard

TB5 min

Slash Command Dashboard:

/dashboard Command

💬Webhook: Slack Slash Command
Quick Parallel Fetch
📧Email Count
📅Today's Events
🔥Urgent Tasks
🕐Current Time
📝Format Slack Message
Respond to Slack

Slack Dashboard Response:

JavaScript
1const email = $('Get Email').item.json;
2const events = $('Get Events').all();
3const tasks = $('Get Tasks').all();
4
5const now = new Date();
6
7const blocks = [
8 {
9 type: "header",
10 text: {
11 type: "plain_text",
12 text: `📊 Quick Dashboard - ${now.toLocaleTimeString()}`
13 }
14 },
15 {
16 type: "section",
17 fields: [
18 {
19 type: "mrkdwn",
20 text: `*📧 Unread Emails*\n${email.unread}`
21 },
22 {
23 type: "mrkdwn",
24 text: `*📅 Meetings Today*\n${events.length}`
25 },
26 {
27 type: "mrkdwn",
28 text: `*⚡ Urgent Tasks*\n${tasks.filter(t => t.json.priority === 'high').length}`
29 },
30 {
31 type: "mrkdwn",
32 text: `*✅ Tasks Due Today*\n${tasks.filter(t => t.json.dueToday).length}`
33 }
34 ]
35 },
36 {
37 type: "divider"
38 },
39 {
40 type: "section",
41 text: {
42 type: "mrkdwn",
43 text: events.length > 0
44 ? `*Next Meeting:* ${events[0].json.summary} at ${new Date(events[0].json.start.dateTime).toLocaleTimeString()}`
45 : "*Next Meeting:* None scheduled 🎉"
46 }
47 }
48];
49
50return { blocks };

Checkpoint

Slack slash command dashboard trả về những thông tin gì?

5

📊 Workflow 4: Notion Dashboard Page

TB5 min

Auto-Update Notion Dashboard:

Update Notion Dashboard

Schedule: Hourly
📥Get All Dashboard Data
📝Update Notion Page Blocks
🕐Update Last Refreshed Timestamp

Update Notion Database:

JSON
1{
2 "name": "Update Dashboard",
3 "type": "n8n-nodes-base.notion",
4 "parameters": {
5 "operation": "update",
6 "pageId": "dashboard-page-id",
7 "properties": {
8 "Email Count": {
9 "number": "={{ $json.emailCount }}"
10 },
11 "Tasks Due": {
12 "number": "={{ $json.tasksDue }}"
13 },
14 "Meetings Today": {
15 "number": "={{ $json.meetingsToday }}"
16 },
17 "Last Updated": {
18 "date": { "start": "={{ $now.toISOString() }}" }
19 }
20 }
21 }
22}

Checkpoint

Notion dashboard page update với frequency nào?

6

💡 Workflow 5: Financial Dashboard

TB5 min

Personal Finance Summary:

JavaScript
1// Aggregate financial data
2const transactions = $('Get Transactions').all();
3const investments = $('Get Portfolio').item.json;
4const budget = $('Get Budget').item.json;
5
6// Calculate spending by category
7const spending = {};
8for (const tx of transactions) {
9 const cat = tx.json.category || 'Other';
10 spending[cat] = (spending[cat] || 0) + tx.json.amount;
11}
12
13// Budget status
14const totalSpent = Object.values(spending).reduce((a, b) => a + b, 0);
15const budgetRemaining = budget.monthly - totalSpent;
16const budgetPercent = (totalSpent / budget.monthly * 100).toFixed(1);
17
18// Investment summary
19const portfolioChange = investments.currentValue - investments.costBasis;
20const portfolioChangePercent = (portfolioChange / investments.costBasis * 100).toFixed(2);
21
22return {
23 spending: {
24 byCategory: spending,
25 total: totalSpent,
26 budgetRemaining,
27 budgetPercent,
28 onTrack: totalSpent < budget.monthly
29 },
30 investments: {
31 value: investments.currentValue,
32 change: portfolioChange,
33 changePercent: portfolioChangePercent,
34 isPositive: portfolioChange > 0
35 },
36 topCategories: Object.entries(spending)
37 .sort((a, b) => b[1] - a[1])
38 .slice(0, 5)
39 .map(([cat, amount]) => ({ category: cat, amount }))
40};

Checkpoint

Financial dashboard tính toán spending by category bằng cách nào?

7

🌟 Workflow 6: Health Dashboard

TB5 min

Aggregate Health Data:

Health Dashboard

Schedule: Daily at 10 PM
Parallel: Apple Health/Fitbit, Sleep Tracker, Water Intake, Mood Logger
🔢Calculate Health Scores
📊Update Dashboard
📈Generate Weekly Trend Report

Health Score Calculator:

JavaScript
1const health = $('Get Health Data').item.json;
2
3// Calculate component scores (0-100)
4const scores = {
5 sleep: Math.min(100, (health.sleepHours / 8) * 100),
6 steps: Math.min(100, (health.steps / 10000) * 100),
7 water: Math.min(100, (health.waterOz / 64) * 100),
8 exercise: Math.min(100, (health.activeMinutes / 30) * 100),
9 mood: health.moodScore * 20 // 1-5 scale to 0-100
10};
11
12// Overall wellness score (weighted average)
13const overallScore = Math.round(
14 scores.sleep * 0.25 +
15 scores.steps * 0.20 +
16 scores.water * 0.15 +
17 scores.exercise * 0.25 +
18 scores.mood * 0.15
19);
20
21// Status indicators
22const getStatus = (score) => {
23 if (score >= 80) return { emoji: '🟢', text: 'Excellent' };
24 if (score >= 60) return { emoji: '🟡', text: 'Good' };
25 if (score >= 40) return { emoji: '🟠', text: 'Fair' };
26 return { emoji: '🔴', text: 'Needs Attention' };
27};
28
29return {
30 scores,
31 overallScore,
32 overallStatus: getStatus(overallScore),
33 breakdown: Object.entries(scores).map(([key, score]) => ({
34 metric: key,
35 score,
36 status: getStatus(score)
37 }))
38};

Checkpoint

Health score calculator sử dụng weighted average với những weights nào?

8

📋 Dashboard Templates

TB5 min

Minimalist Morning Briefing:

JavaScript
1const data = $input.item.json;
2
3const briefing = `
4 **Today at a Glance**
5
6 ${data.events.length} meetings | ${data.tasks} tasks | ${data.emails} emails
7
8**Focus:** ${data.topPriority || 'Check your tasks'}
9
10**Weather:** ${data.weather.temp}° ${data.weather.condition}
11
12*Have a great day!*
13`;
14
15return { briefing };

Executive Summary Style:

JavaScript
1const data = $input.item.json;
2
3const summary = `
4# Executive Dashboard
5
6## Key Metrics
7| Metric | Value | Status |
8|--------|-------|--------|
9| Revenue MTD | $${data.revenue.toLocaleString()} | ${data.revenueStatus} |
10| Tasks Completed | ${data.tasksCompleted}/${data.tasksTotal} | ${data.taskStatus} |
11| Team Velocity | ${data.velocity} pts | ${data.velocityStatus} |
12
13## Action Required
14${data.actionItems.map(a => `- ${a}`).join('\n')}
15
16## Upcoming Deadlines
17${data.deadlines.map(d => `- ${d.date}: ${d.item}`).join('\n')}
18
19*Updated: ${new Date().toLocaleString()}*
20`;
21
22return { summary };

Checkpoint

Minimalist morning briefing bao gồm những thông tin gì?

9

📝 Bài Tập Thực Hành

TB5 min
Dashboard Challenge

Build your command center:

  1. Create morning briefing email
  2. Build Slack quick dashboard command
  3. Set up weekly summary report
  4. Design Notion dashboard page
  5. Implement one specialized dashboard (finance/health/work)

Own your day! 📊

Checkpoint

Bạn đã hoàn thành những challenges nào trong bài tập?

10

🧠 Key Takeaways

TB5 min
Remember
  • 📊 Aggregate don't duplicate - Pull from source of truth
  • Timing matters - Send at useful times
  • 📱 Multi-channel - Email, Slack, Notion options
  • 🎯 Keep it focused - Show what matters
  • 🔄 Update frequency - Match your needs

Checkpoint

Tại sao nên Aggregate don't duplicate?

🚀 Bài tiếp theo

Team Notifications — Automate updates, alerts, và reminders cho team.