Skip to content

Instantly share code, notes, and snippets.

@dukex
Created August 12, 2025 19:44
Show Gist options
  • Save dukex/a4c8b28e73ce59d3bec0f39004b76cd8 to your computer and use it in GitHub Desktop.
Save dukex/a4c8b28e73ce59d3bec0f39004b76cd8 to your computer and use it in GitHub Desktop.
Calendar to Obsidian N8N Workflow
services:
n8n:
image: n8nio/n8n
container_name: n8n
ports:
- "5678:5678"
volumes:
- ".n8n:/home/node/.n8n"
- "TODO: Knowledge DIR:/knowledge"
environment:
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
- N8N_LOG_LEVEL=debug
stdin_open: true
tty: true
restart: unless-stopped
{
"name": "Calendar to Obsidian",
"nodes": [
{
"parameters": {
"operation": "toText",
"sourceProperty": "text",
"options": {
"encoding": "utf8",
"fileName": "={{ $json.filename }}"
}
},
"type": "n8n-nodes-base.convertToFile",
"typeVersion": 1.1,
"position": [
992,
80
],
"id": "db9f4451-e1fd-4120-9061-9dd43b81fa86",
"name": "Convert to Markdown"
},
{
"parameters": {
"operation": "write",
"fileName": "={{ $binary.data.directory }}/{{ $binary.data.fileName }}",
"options": {}
},
"type": "n8n-nodes-base.readWriteFile",
"typeVersion": 1,
"position": [
1168,
80
],
"id": "7aa10bca-7f18-4282-a6bb-13b52af90329",
"name": "Save to obsidian",
"executeOnce": false,
"alwaysOutputData": false,
"notesInFlow": false
},
{
"parameters": {
"operation": "getAll",
"calendar": {
"__rl": true,
"value": "TODO: ADD YOUR EMAIL HERE",
"mode": "list",
"cachedResultName": "TODO: ADD YOUR EMAIL HERE"
},
"timeMin": "={{ $now.startOf('day') }}",
"timeMax": "={{ $now.endOf('day') }}",
"options": {}
},
"type": "n8n-nodes-base.googleCalendar",
"typeVersion": 1.3,
"position": [
-176,
-176
],
"id": "196f2858-0d53-47a5-9761-66400ef640d3",
"name": "Get today events",
"credentials": {
"googleCalendarOAuth2Api": {
"id": "WI1mSTdCscQfGd0m",
"name": "Google Calendar account"
}
}
},
{
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 6
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
-352,
-320
],
"id": "1f46c3e7-8bd3-419e-b675-dbdd0916ebbd",
"name": "Every morning"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "04233253-bd10-4ccb-b06f-7c5a900d449b",
"leftValue": "={{ $json.attendees }}",
"rightValue": 1,
"operator": {
"type": "array",
"operation": "lengthGt",
"rightType": "number"
}
},
{
"id": "b3289491-51f6-4474-8fae-2d9145fa0799",
"leftValue": "={{ $json.hangoutLink }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
}
},
{
"id": "cb42bb5d-20a6-4639-a2f7-f404e5145b44",
"leftValue": "",
"rightValue": "",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.filter",
"typeVersion": 2.2,
"position": [
16,
-176
],
"id": "87ec4474-66c4-42d6-839d-564c315444ae",
"name": "Filter: valid calls"
},
{
"parameters": {
"jsCode": "const events = []\n\nfor (const item of $input.all()) {\n events.push({\n d: item.json.start.dateTime,\n \"id\": item.json.id,\n \"title\": item.json.summary,\n \"filename\": '/knowledge/03 - Resources/Zettelkasten/03 - Main Notes/' + item.json.start.dateTime.replace(\"-03:00\",\"\").replace(\"T\", \"\").replaceAll(/[-:]/gi,\"\").substring(0,12) + \" - \" + item.json.summary.replace('/', '-').replace(\" \", \" \").replace(\"[\", \"\").replace(\"]\", \"\") + \".md\",\n \"attendees\": item.json.attendees.map((a) => a.email),\n \"tags\": \"work\",\n \"body\": item.json.description || \"\",\n \"starts_at\": item.json.start.dateTime\n })\n}\n\nreturn events"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
224,
-176
],
"id": "e32543b5-219d-4f66-af53-b91ecfd5b575",
"name": "Extract data"
},
{
"parameters": {
"jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n item.json.data = `---\nkind: metting\nguests:\n${item.json.attendees.map(i => ` - ${i}`).join('\\n')}\nstarts_at: ${item.json.starts_at}\nid: ${item.json.id}\ntags: work/caju/staff\n---\n\n# ${item.json.title}\n${item.json.body || \"\"}\n\n### Notes\n\n...\n\n## Tasks\n\n- [ ] ... #work/caju/staff\n- [ ] ... #work/caju/staff\n`\n}\n\nreturn $input.all();"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
400,
-176
],
"id": "dfbdac4a-f3c5-47dc-8a81-a97df4e0b3e4",
"name": "Prepare markown"
},
{
"parameters": {
"options": {}
},
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
608,
-48
],
"id": "1adfa27c-e3ba-450f-a819-136de47c6489",
"name": "For each event"
},
{
"parameters": {
"command": "=ls \"{{ $json.filename }}\""
},
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
800,
64
],
"id": "4f38cecc-e523-4f17-b61d-6851704f7bd2",
"name": "File exists",
"onError": "continueErrorOutput"
},
{
"parameters": {
"operation": "getAll",
"calendar": {
"__rl": true,
"value": "TODO: ADD YOUR EMAIL HERE",
"mode": "list",
"cachedResultName": "TODO: ADD YOUR EMAIL HERE"
},
"timeMin": "={{ $now.minus(1, 'day').startOf('day') }}",
"timeMax": "={{ $now.minus(1, 'day').endOf('day') }}",
"options": {}
},
"type": "n8n-nodes-base.googleCalendar",
"typeVersion": 1.3,
"position": [
784,
-320
],
"id": "e8906fdc-d155-4fd3-8bb7-85b59d187f6a",
"name": "Yesterday events",
"credentials": {
"googleCalendarOAuth2Api": {
"id": "WI1mSTdCscQfGd0m",
"name": "Google Calendar account"
}
}
},
{
"parameters": {
"jsCode": "return $input.all().\n filter(e => (e.json.attachments || []).\n filter(a => a.title.indexOf('Gemini') > -1).length > 0).\n flatMap((e) => e.json.attachments.map(a => ({ ...a, event: e.json,\n \"filename\": '/knowledge/03 - Resources/Zettelkasten/03 - Main Notes/' + e.json.start.dateTime.replace(\"-03:00\",\"\").replace(\"T\", \"\").replaceAll(/[-:]/gi,\"\").substring(0,12) + \" - \" + e.json.summary.replace('/', '-').replace(\" \", \" \").replace(\"[\", \"\").replace(\"]\", \"\") + \".md\",\n })));"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
976,
-320
],
"id": "dd3c4949-02fb-4f01-8eb2-42f816d2f4f5",
"name": "Events with annotations"
},
{
"parameters": {
"operation": "download",
"fileId": {
"__rl": true,
"value": "={{ $json.fileUrl }}",
"mode": "url"
},
"options": {
"binaryPropertyName": "data",
"googleFileConversion": {
"conversion": {
"docsToFormat": "text/plain"
}
}
}
},
"type": "n8n-nodes-base.googleDrive",
"typeVersion": 3,
"position": [
1168,
-320
],
"id": "b981451f-7a05-4247-8266-4fca331b914d",
"name": "Download file",
"credentials": {
"googleDriveOAuth2Api": {
"id": "2R9pKYwMRrpKCNo5",
"name": "Google Drive account"
}
},
"onError": "continueErrorOutput"
},
{
"parameters": {
"options": {}
},
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
1488,
-432
],
"id": "e9d93e8b-6718-4d48-b60b-58713bc00a6c",
"name": "For each event1"
},
{
"parameters": {
"operation": "write",
"fileName": "={{ $('Events with annotations').item.json.filename }}",
"options": {
"append": true
}
},
"type": "n8n-nodes-base.readWriteFile",
"typeVersion": 1,
"position": [
1760,
-416
],
"id": "6d3f7ec7-e370-4d0a-a281-247ee0763fd9",
"name": "Append to obsidian file",
"executeOnce": false,
"alwaysOutputData": true,
"notesInFlow": false
}
],
"pinData": {},
"connections": {
"Convert to Markdown": {
"main": [
[
{
"node": "Save to obsidian",
"type": "main",
"index": 0
}
]
]
},
"Save to obsidian": {
"main": [
[
{
"node": "For each event",
"type": "main",
"index": 0
}
]
]
},
"Get today events": {
"main": [
[
{
"node": "Filter: valid calls",
"type": "main",
"index": 0
}
]
]
},
"Every morning": {
"main": [
[
{
"node": "Get today events",
"type": "main",
"index": 0
}
]
]
},
"Filter: valid calls": {
"main": [
[
{
"node": "Extract data",
"type": "main",
"index": 0
}
]
]
},
"Extract data": {
"main": [
[
{
"node": "Prepare markown",
"type": "main",
"index": 0
}
]
]
},
"Prepare markown": {
"main": [
[
{
"node": "For each event",
"type": "main",
"index": 0
}
]
]
},
"For each event": {
"main": [
[
{
"node": "Yesterday events",
"type": "main",
"index": 0
}
],
[
{
"node": "File exists",
"type": "main",
"index": 0
}
]
]
},
"File exists": {
"main": [
[
{
"node": "For each event",
"type": "main",
"index": 0
}
],
[
{
"node": "Convert to Markdown",
"type": "main",
"index": 0
}
]
]
},
"Yesterday events": {
"main": [
[
{
"node": "Events with annotations",
"type": "main",
"index": 0
}
]
]
},
"Events with annotations": {
"main": [
[
{
"node": "Download file",
"type": "main",
"index": 0
}
]
]
},
"Download file": {
"main": [
[
{
"node": "For each event1",
"type": "main",
"index": 0
}
]
]
},
"For each event1": {
"main": [
[],
[
{
"node": "Append to obsidian file",
"type": "main",
"index": 0
}
]
]
},
"Append to obsidian file": {
"main": [
[
{
"node": "For each event1",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "1bd546a7-b619-4f99-90ff-8e00b43accdc",
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "instanceId"
},
"id": "evoCRrEnzpUPEhYO",
"tags": []
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment