AutomationFlowsGeneral › Calendar to Obsidian

Calendar to Obsidian

Calendar to Obsidian. Uses readWriteFile, googleCalendar, executeCommand, googleDrive. Scheduled trigger; 14 nodes.

Cron / scheduled trigger★★★★☆ complexity14 nodesRead Write FileGoogle CalendarExecute CommandGoogle Drive
General Trigger: Cron / scheduled Nodes: 14 Complexity: ★★★★☆ Added:

This workflow follows the Executecommand → Readwritefile recipe pattern — see all workflows that pair these two integrations.

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 →

Download .json
{
  "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": {
          "name": "<your credential>"
        }
      }
    },
    {
      "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": {
          "name": "<your credential>"
        }
      }
    },
    {
      "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": {
          "name": "<your credential>"
        }
      },
      "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
    }
  ],
  "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
  },
  "id": "evoCRrEnzpUPEhYO",
  "tags": []
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Calendar to Obsidian. Uses readWriteFile, googleCalendar, executeCommand, googleDrive. Scheduled trigger; 14 nodes.

Source: https://gist.github.com/dukex/a4c8b28e73ce59d3bec0f39004b76cd8 — original creator credit. Request a take-down →

More General workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

General

Complete backup solution that saves both workflows and credentials to local/server disk with optional FTP upload for off-site redundancy.

Read Write File, Email Send, Execute Command +3
General

🎯 Purpose: Generate audio files from text scripts stored in Google Drive.

Execute Workflow Trigger, Google Drive, Read Write File +1
General

Workflow 2469. Uses moveBinaryData, googleDrive, itemLists, n8n. Scheduled trigger; 33 nodes.

Move Binary Data, Google Drive, Item Lists +1
General

Perfect for content publishing with organic scheduling patterns, social media automation, API systems that need to avoid rate limiting, or any automation requiring randomised timing control across mul

n8n, Read Write File, Stop And Error +1
General

creda. Uses executeCommand, googleDrive, n8n. Event-driven trigger; 27 nodes.

Execute Command, Google Drive, n8n