The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Supabase Data Analyst \u2014 Morning Briefing",
"settings": {
"executionOrder": "v1"
},
"nodes": [
{
"parameters": {
"content": "## Morning Briefing\n**Purpose:** Scheduled companion to the chat agent. Runs a fixed set of KPI queries and delivers a daily digest \u2014 Slack, email, or anywhere.\n\n**Schedule:** weekdays at 09:00 (edit the cron in the trigger node).\n\n**Flow:**\n1. **Every Weekday 9am** \u2014 Schedule Trigger.\n2. **Define KPI Queries** \u2014 Set node with an array of `{label, sql}`. Edit this to add/remove your metrics.\n3. **Split KPIs** \u2014 one execution per KPI.\n4. **Run KPI Query** \u2014 Postgres executeQuery. Uses the same credential as the main agent.\n5. **Aggregate Results** \u2014 recombines all KPI outputs.\n6. **Format Briefing** \u2014 Code node builds HTML + plain text versions of the digest.\n\n**Add your delivery node** (not included in template):\n- Gmail / SMTP / Resend for email\n- Slack / Teams for chat\n- Notion / Google Docs for logging",
"height": 420,
"width": 600,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-40,
-460
],
"id": "sticky-briefing",
"name": "README"
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 9 * * 1-5"
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
0,
0
],
"id": "sched",
"name": "Every Weekday 9am"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "kpis",
"name": "kpis",
"value": "=[{\"label\":\"New rows in NHRA list (last 7d)\",\"sql\":\"SELECT COUNT(*) AS value FROM public.\\\"NHRA_Bahrain_Temporary_Importation_Medicine_List\\\" WHERE \\\"Last_Updated\\\"::date >= CURRENT_DATE - INTERVAL '7 days';\"},{\"label\":\"Distinct medicines (total)\",\"sql\":\"SELECT COUNT(DISTINCT \\\"MEDICINE NAME\\\") AS value FROM public.\\\"NHRA_Bahrain_Temporary_Importation_Medicine_List\\\";\"}]",
"type": "array"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
220,
0
],
"id": "kpi-list",
"name": "Define KPI Queries"
},
{
"parameters": {
"fieldToSplitOut": "kpis",
"options": {}
},
"type": "n8n-nodes-base.splitOut",
"typeVersion": 1,
"position": [
440,
0
],
"id": "split",
"name": "Split KPIs"
},
{
"parameters": {
"operation": "executeQuery",
"query": "={{ $json.sql }}",
"options": {}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.6,
"position": [
660,
0
],
"id": "pg-kpi",
"name": "Run KPI Query"
},
{
"parameters": {
"aggregate": "aggregateAllItemData",
"options": {}
},
"type": "n8n-nodes-base.aggregate",
"typeVersion": 1,
"position": [
880,
0
],
"id": "agg",
"name": "Aggregate Results"
},
{
"parameters": {
"jsCode": "const items = $input.all().map(i => i.json);\nconst lines = items.map((row, idx) => `- ${row.label || 'KPI ' + (idx+1)}: ${row.value ?? JSON.stringify(row)}`);\nconst html = `<h2>Daily Data Briefing \u2014 ${new Date().toISOString().slice(0,10)}</h2><ul>${lines.map(l => '<li>' + l.slice(2) + '</li>').join('')}</ul>`;\nreturn [{ json: { html, text: lines.join('\\n') } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1100,
0
],
"id": "fmt",
"name": "Format Briefing"
}
],
"connections": {
"Every Weekday 9am": {
"main": [
[
{
"node": "Define KPI Queries",
"type": "main",
"index": 0
}
]
]
},
"Define KPI Queries": {
"main": [
[
{
"node": "Split KPIs",
"type": "main",
"index": 0
}
]
]
},
"Split KPIs": {
"main": [
[
{
"node": "Run KPI Query",
"type": "main",
"index": 0
}
]
]
},
"Run KPI Query": {
"main": [
[
{
"node": "Aggregate Results",
"type": "main",
"index": 0
}
]
]
},
"Aggregate Results": {
"main": [
[
{
"node": "Format Briefing",
"type": "main",
"index": 0
}
]
]
}
}
}
About this workflow
Supabase Data Analyst — Morning Briefing. Uses stickyNote, scheduleTrigger, splitOut, postgres. Scheduled trigger; 7 nodes.
Source: https://github.com/MinaSaad1/n8n-data-analyst-agent/blob/main/workflows/05-briefing-morning.json — original creator credit. Request a take-down →