{"updatedAt":"2025-11-08T19:49:55.000Z","createdAt":"2025-11-06T20:41:31.235Z","id":"OaQn4ooJ8MD5gtG6","name":"Capture – Create Entry","active":true,"isArchived":false,"nodes":[{"parameters":{"httpMethod":"POST","path":"create-entry","responseMode":"responseNode","options":{"rawBody":true}},"type":"n8n-nodes-base.webhook","typeVersion":2.1,"position":[0,0],"id":"d233aa8b-890e-4982-aeb0-5522e65b8152","name":"Create Entry Webhook","webhookId":"99a987b6-0780-4ae1-a0cf-a4e1c1e3cbb3"},{"parameters":{"jsCode":"// Robustly extract the request body and selectedFiles from the webhook.\n\n// 1. Get the raw JSON from the previous node (Webhook)\nlet raw = (items[0] && items[0].json) ? items[0].json : {};\n\n// 2. Some setups put the real payload under `body`, or even as a string.\n//    Normalize that here.\nlet body = raw;\n\nif (raw.body && typeof raw.body === \"object\") {\n  body = raw.body;\n} else if (raw.body && typeof raw.body === \"string\") {\n  try {\n    body = JSON.parse(raw.body);\n  } catch (e) {\n    // leave body as raw if parsing fails\n  }\n}\n\n// 3. selectedFiles itself might arrive as a JSON string.\n//    Normalize that into an array if needed.\nif (typeof body.selectedFiles === \"string\") {\n  try {\n    body.selectedFiles = JSON.parse(body.selectedFiles);\n  } catch (e) {\n    // ignore & let it fall through to []\n  }\n}\n\nconst entryType    = body.entryType    || \"thoughts\";\nconst title        = body.title        || \"(no title)\";\nconst description  = body.description  || \"\";\nconst timeRange    = body.timeRange    || {};\nconst selectedFiles = Array.isArray(body.selectedFiles) ? body.selectedFiles : [];\n\n// Build a text summary (optional, but harmless)\nlet filesText;\nif (selectedFiles.length === 0) {\n  filesText = \"No files attached.\";\n} else {\n  const lines = selectedFiles.map((f, idx) => {\n    const name = f.name || f.id || `File ${idx + 1}`;\n    const url  = f.url || \"\";\n    if (url) {\n      return `${idx + 1}. ${name} (${url})`;\n    } else {\n      return `${idx + 1}. ${name}`;\n    }\n  });\n  filesText = \"Files:\\n\" + lines.join(\"\\n\");\n}\n\nreturn [\n  {\n    json: {\n      entryType,\n      title,\n      description,\n      timeRange,\n      selectedFiles,\n      filesText,\n    },\n  },\n];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[208,0],"id":"e1f3da90-7e1b-4b27-8cc2-02e90a35d480","name":"Prepare Entry Data"},{"parameters":{"rules":{"values":[{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"strict","version":2},"conditions":[{"leftValue":"={{ $json[\"entryType\"] }}","rightValue":"thoughts","operator":{"type":"string","operation":"equals"},"id":"5bcf0664-1860-4d22-9f20-0e925e57e2b1"}],"combinator":"and"}},{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"strict","version":2},"conditions":[{"id":"d4357a3a-312b-4f2c-9f73-1fc76482215a","leftValue":"={{ $json[\"entryType\"] }}","rightValue":"journal","operator":{"type":"string","operation":"equals","name":"filter.operator.equals"}}],"combinator":"and"}},{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"strict","version":2},"conditions":[{"id":"1e6e6167-0c45-4e82-b10a-10fcc404dcaa","leftValue":"={{ $json[\"entryType\"] }}","rightValue":"plans","operator":{"type":"string","operation":"equals","name":"filter.operator.equals"}}],"combinator":"and"}}]},"options":{}},"type":"n8n-nodes-base.switch","typeVersion":3.3,"position":[416,-16],"id":"e759f5b3-1ffe-49e8-a25a-78aa7b5b6645","name":"Route by Type"},{"parameters":{"jsCode":"// Build Notion external-URL blocks using fserver URLs\n\nconst page = items[0].json || {};\nconst pageId = page.id;\n\n// Get selectedFiles from Prepare Entry Data\nconst selectedFiles =\n  ($node[\"Prepare Entry Data\"].json &&\n   Array.isArray($node[\"Prepare Entry Data\"].json.selectedFiles))\n    ? $node[\"Prepare Entry Data\"].json.selectedFiles\n    : [];\n\n// Decide block type based on file extension\nfunction guessBlockType(url) {\n  if (!url) return { type: \"file\", key: \"file\" };\n  const lower = url.toLowerCase();\n\n  if (lower.match(/\\.(mp4|mov|webm|mkv)$/)) {\n    return { type: \"video\", key: \"video\" };\n  }\n  if (lower.match(/\\.(mp3|m4a|wav|ogg)$/)) {\n    return { type: \"audio\", key: \"audio\" };\n  }\n  if (lower.match(/\\.(png|jpg|jpeg|gif|webp|bmp|svg)$/)) {\n    return { type: \"image\", key: \"image\" };\n  }\n  return { type: \"file\", key: \"file\" };\n}\n\nconst children = selectedFiles.map((f) => {\n  // IMPORTANT: make sure `url` here is the fserver URL (min.velvetcld...)\n  const url = f.url || f.thumbnailUrl || \"\";\n  const name = f.name || \"Unnamed file\";\n  const block = guessBlockType(url);\n\n  return {\n    object: \"block\",\n    type: block.type,\n    [block.key]: {\n      type: \"external\",\n      external: { url },\n      caption: [{ type: \"text\", text: { content: name } }],\n    },\n  };\n});\n\nreturn [\n  {\n    json: {\n      pageId,\n      children,\n    },\n  },\n];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[832,-128],"id":"5f32df8e-1fee-4693-b3de-1d9915af1f2d","name":"Build File Blocks (Thoughts)"},{"parameters":{"method":"PATCH","url":"={{ 'https://api.notion.com/v1/blocks/' + $json[\"pageId\"] + '/children' }}\n","sendHeaders":true,"headerParameters":{"parameters":[{"name":"Authorization","value":"Bearer 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"},{"name":"Notion-Version","value":"2022-06-28"},{"name":"Content-Type","value":"application/json"}]},"sendBody":true,"specifyBody":"json","jsonBody":"={{ JSON.stringify({ children: $json[\"children\"] }) }}\n\n","options":{}},"type":"n8n-nodes-base.httpRequest","typeVersion":4.3,"position":[1040,-128],"id":"0cfcdffc-b2da-4e37-9929-c0e3b525c01a","name":"Append Files (Thoughts)"},{"parameters":{"resource":"databasePage","databaseId":{"__rl":true,"value":"234dcbfd-8835-805f-8ba9-de38ea537985","mode":"list","cachedResultName":"Thoughts","cachedResultUrl":"https://www.notion.so/234dcbfd8835805f8ba9de38ea537985"},"title":"={{ $json[\"title\"] }}","simple":false,"propertiesUi":{"propertyValues":[{"key":"Thought|title","title":"={{ $json[\"title\"] }}"},{"key":"content|rich_text","richText":true,"text":{"text":[{"text":"={{ $json[\"description\"] }}","annotationUi":{}}]}}]},"options":{}},"type":"n8n-nodes-base.notion","typeVersion":2.2,"position":[624,-128],"id":"1b580043-73e6-46aa-b389-d156dd01e08d","name":"Create Thoughts Page","credentials":{"notionApi":{"id":"j9X7YFSp6m90N06v","name":"Notion account"}}},{"parameters":{"resource":"databasePage","databaseId":{"__rl":true,"value":"228dcbfd-8835-80ab-9727-ee036d84f48e","mode":"list","cachedResultName":"Journal Entries","cachedResultUrl":"https://www.notion.so/228dcbfd883580ab9727ee036d84f48e"},"title":"={{ $json[\"title\"] }}","simple":false,"propertiesUi":{"propertyValues":[{"key":"Title|title","title":"={{ $json[\"title\"] }}"},{"key":"Content|rich_text","richText":true,"text":{"text":[{"text":"={{ $json[\"description\"] }}","annotationUi":{}}]}}]},"options":{}},"type":"n8n-nodes-base.notion","typeVersion":2.2,"position":[624,16],"id":"3d4701e4-4574-4aab-83e0-02df775508d1","name":"Create Journal Page","credentials":{"notionApi":{"id":"j9X7YFSp6m90N06v","name":"Notion account"}}},{"parameters":{"jsCode":"// Build Notion external-URL blocks using fserver URLs\n\nconst page = items[0].json || {};\nconst pageId = page.id;\n\n// Get selectedFiles from Prepare Entry Data\nconst selectedFiles =\n  ($node[\"Prepare Entry Data\"].json &&\n   Array.isArray($node[\"Prepare Entry Data\"].json.selectedFiles))\n    ? $node[\"Prepare Entry Data\"].json.selectedFiles\n    : [];\n\n// Decide block type based on file extension\nfunction guessBlockType(url) {\n  if (!url) return { type: \"file\", key: \"file\" };\n  const lower = url.toLowerCase();\n\n  if (lower.match(/\\.(mp4|mov|webm|mkv)$/)) {\n    return { type: \"video\", key: \"video\" };\n  }\n  if (lower.match(/\\.(mp3|m4a|wav|ogg)$/)) {\n    return { type: \"audio\", key: \"audio\" };\n  }\n  if (lower.match(/\\.(png|jpg|jpeg|gif|webp|bmp|svg)$/)) {\n    return { type: \"image\", key: \"image\" };\n  }\n  return { type: \"file\", key: \"file\" };\n}\n\nconst children = selectedFiles.map((f) => {\n  // IMPORTANT: make sure `url` here is the fserver URL (min.velvetcld...)\n  const url = f.url || f.thumbnailUrl || \"\";\n  const name = f.name || \"Unnamed file\";\n  const block = guessBlockType(url);\n\n  return {\n    object: \"block\",\n    type: block.type,\n    [block.key]: {\n      type: \"external\",\n      external: { url },\n      caption: [{ type: \"text\", text: { content: name } }],\n    },\n  };\n});\n\nreturn [\n  {\n    json: {\n      pageId,\n      children,\n    },\n  },\n];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[832,16],"id":"bce63d51-ea7e-44cb-bce8-fd012c4f5363","name":"Build File Blocks (Journal)"},{"parameters":{"resource":"databasePage","databaseId":{"__rl":true,"value":"2a4dcbfd-8835-80ec-a760-eec0e8839846","mode":"list","cachedResultName":"Plans","cachedResultUrl":"https://www.notion.so/2a4dcbfd883580eca760eec0e8839846"},"title":"={{ $json[\"title\"] }}","simple":false,"propertiesUi":{"propertyValues":[{"key":"Title|title","title":"={{ $json[\"title\"] }}"},{"key":"Content|rich_text","richText":true,"text":{"text":[{"text":"={{ $json[\"description\"] }}","annotationUi":{}}]}}]},"options":{}},"type":"n8n-nodes-base.notion","typeVersion":2.2,"position":[624,208],"id":"cd8decc7-22ee-4a83-9e6c-4a4b38cda849","name":"Create Plan Page","credentials":{"notionApi":{"id":"j9X7YFSp6m90N06v","name":"Notion account"}}},{"parameters":{"jsCode":"// Build Notion external-URL blocks using fserver URLs\n\nconst page = items[0].json || {};\nconst pageId = page.id;\n\n// Get selectedFiles from Prepare Entry Data\nconst selectedFiles =\n  ($node[\"Prepare Entry Data\"].json &&\n   Array.isArray($node[\"Prepare Entry Data\"].json.selectedFiles))\n    ? $node[\"Prepare Entry Data\"].json.selectedFiles\n    : [];\n\n// Decide block type based on file extension\nfunction guessBlockType(url) {\n  if (!url) return { type: \"file\", key: \"file\" };\n  const lower = url.toLowerCase();\n\n  if (lower.match(/\\.(mp4|mov|webm|mkv)$/)) {\n    return { type: \"video\", key: \"video\" };\n  }\n  if (lower.match(/\\.(mp3|m4a|wav|ogg)$/)) {\n    return { type: \"audio\", key: \"audio\" };\n  }\n  if (lower.match(/\\.(png|jpg|jpeg|gif|webp|bmp|svg)$/)) {\n    return { type: \"image\", key: \"image\" };\n  }\n  return { type: \"file\", key: \"file\" };\n}\n\nconst children = selectedFiles.map((f) => {\n  // IMPORTANT: make sure `url` here is the fserver URL (min.velvetcld...)\n  const url = f.url || f.thumbnailUrl || \"\";\n  const name = f.name || \"Unnamed file\";\n  const block = guessBlockType(url);\n\n  return {\n    object: \"block\",\n    type: block.type,\n    [block.key]: {\n      type: \"external\",\n      external: { url },\n      caption: [{ type: \"text\", text: { content: name } }],\n    },\n  };\n});\n\nreturn [\n  {\n    json: {\n      pageId,\n      children,\n    },\n  },\n];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[832,208],"id":"9299adcb-b2af-416a-a045-1065129bbb02","name":"Build File Blocks (Plan)"},{"parameters":{"jsCode":"// Build simple response for the caller, based on which branch ran.\n\nconst dataFromPrepare = $node[\"Prepare Entry Data\"].json || {};\nconst entryType = (dataFromPrepare.entryType || \"thoughts\").toLowerCase();\n\nconst mapping = {\n  thoughts: \"Create Thoughts Page\",\n  journal: \"Create Journal Page\",\n  plans: \"Create Plan Page\", // <-- make sure this matches your exact node name\n};\n\nconst nodeName = mapping[entryType] || mapping.thoughts;\n\n// Only read from the node that actually ran\nconst page = ($node[nodeName] && $node[nodeName].json) ? $node[nodeName].json : {};\n\nreturn [\n  {\n    json: {\n      success: true,\n      id: page.id || null,\n      url: page.url || null,\n      entryType,\n    },\n  },\n];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[1248,16],"id":"ff75add9-83b7-4dba-9749-fa0558e2a330","name":"Build Response"},{"parameters":{"respondWith":"text","responseBody":"={{ JSON.stringify({\n  success: true,\n  pageUrl: \"https://www.notion.so/\" + $json.id,\n  entryType: $json.entryType\n}) }}\n","options":{"responseCode":200,"responseHeaders":{"entries":[{"name":"Content-Type","value":"application/json"}]}}},"type":"n8n-nodes-base.respondToWebhook","typeVersion":1.4,"position":[1456,16],"id":"a2a6244d-0ff2-47a5-ae53-75f21a09098d","name":"Respond to Webhook"},{"parameters":{"method":"PATCH","url":"={{ 'https://api.notion.com/v1/blocks/' + $json[\"pageId\"] + '/children' }}\n","sendHeaders":true,"headerParameters":{"parameters":[{"name":"Authorization","value":"Bearer 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"},{"name":"Notion-Version","value":"2022-06-28"},{"name":"Content-Type","value":"application/json"}]},"sendBody":true,"specifyBody":"json","jsonBody":"={{ JSON.stringify({ children: $json[\"children\"] }) }}\n\n","options":{}},"type":"n8n-nodes-base.httpRequest","typeVersion":4.3,"position":[1040,16],"id":"b292f1be-01ff-4204-bf9d-653ddf697a0a","name":"Append Files (Journal)"},{"parameters":{"method":"PATCH","url":"={{ 'https://api.notion.com/v1/blocks/' + $json[\"pageId\"] + '/children' }}\n","sendHeaders":true,"headerParameters":{"parameters":[{"name":"Authorization","value":"Bearer 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"},{"name":"Notion-Version","value":"2022-06-28"},{"name":"Content-Type","value":"application/json"}]},"sendBody":true,"specifyBody":"json","jsonBody":"={{ JSON.stringify({ children: $json[\"children\"] }) }}\n\n","options":{}},"type":"n8n-nodes-base.httpRequest","typeVersion":4.3,"position":[1040,208],"id":"39830698-b07b-4163-b4a8-820fd33e319e","name":"Append Files (Plan)"}],"connections":{"Create Entry Webhook":{"main":[[{"node":"Prepare Entry Data","type":"main","index":0}]]},"Prepare Entry Data":{"main":[[{"node":"Route by Type","type":"main","index":0}]]},"Route by Type":{"main":[[{"node":"Create Thoughts Page","type":"main","index":0}],[{"node":"Create Journal Page","type":"main","index":0}],[{"node":"Create Plan Page","type":"main","index":0}]]},"Build File Blocks (Thoughts)":{"main":[[{"node":"Append Files (Thoughts)","type":"main","index":0}]]},"Create Thoughts Page":{"main":[[{"node":"Build File Blocks (Thoughts)","type":"main","index":0}]]},"Create Journal Page":{"main":[[{"node":"Build File Blocks (Journal)","type":"main","index":0}]]},"Build File Blocks (Journal)":{"main":[[{"node":"Append Files (Journal)","type":"main","index":0}]]},"Create Plan Page":{"main":[[{"node":"Build File Blocks (Plan)","type":"main","index":0}]]},"Build File Blocks (Plan)":{"main":[[{"node":"Append Files (Plan)","type":"main","index":0}]]},"Append Files (Thoughts)":{"main":[[{"node":"Build Response","type":"main","index":0}]]},"Build Response":{"main":[[{"node":"Respond to Webhook","type":"main","index":0}]]},"Append Files (Journal)":{"main":[[{"node":"Build Response","type":"main","index":0}]]},"Append Files (Plan)":{"main":[[{"node":"Build Response","type":"main","index":0}]]}},"settings":{"executionOrder":"v1"},"staticData":null,"meta":{"templateCredsSetupCompleted":true},"pinData":{},"versionId":"c9a3111a-fadc-4563-9c7b-f3a9c71c0bc5","activeVersionId":"c9a3111a-fadc-4563-9c7b-f3a9c71c0bc5","triggerCount":1,"shared":[{"updatedAt":"2025-11-06T20:41:31.238Z","createdAt":"2025-11-06T20:41:31.238Z","role":"workflow:owner","workflowId":"OaQn4ooJ8MD5gtG6","projectId":"lh2csO3ZG7MzpN8o"}],"activeVersion":{"updatedAt":"2025-11-27T21:37:34.259Z","createdAt":"2025-11-27T21:37:34.259Z","versionId":"c9a3111a-fadc-4563-9c7b-f3a9c71c0bc5","workflowId":"OaQn4ooJ8MD5gtG6","nodes":[{"parameters":{"httpMethod":"POST","path":"create-entry","responseMode":"responseNode","options":{"rawBody":true}},"type":"n8n-nodes-base.webhook","typeVersion":2.1,"position":[0,0],"id":"d233aa8b-890e-4982-aeb0-5522e65b8152","name":"Create Entry Webhook","webhookId":"99a987b6-0780-4ae1-a0cf-a4e1c1e3cbb3"},{"parameters":{"jsCode":"// Robustly extract the request body and selectedFiles from the webhook.\n\n// 1. Get the raw JSON from the previous node (Webhook)\nlet raw = (items[0] && items[0].json) ? items[0].json : {};\n\n// 2. Some setups put the real payload under `body`, or even as a string.\n//    Normalize that here.\nlet body = raw;\n\nif (raw.body && typeof raw.body === \"object\") {\n  body = raw.body;\n} else if (raw.body && typeof raw.body === \"string\") {\n  try {\n    body = JSON.parse(raw.body);\n  } catch (e) {\n    // leave body as raw if parsing fails\n  }\n}\n\n// 3. selectedFiles itself might arrive as a JSON string.\n//    Normalize that into an array if needed.\nif (typeof body.selectedFiles === \"string\") {\n  try {\n    body.selectedFiles = JSON.parse(body.selectedFiles);\n  } catch (e) {\n    // ignore & let it fall through to []\n  }\n}\n\nconst entryType    = body.entryType    || \"thoughts\";\nconst title        = body.title        || \"(no title)\";\nconst description  = body.description  || \"\";\nconst timeRange    = body.timeRange    || {};\nconst selectedFiles = Array.isArray(body.selectedFiles) ? body.selectedFiles : [];\n\n// Build a text summary (optional, but harmless)\nlet filesText;\nif (selectedFiles.length === 0) {\n  filesText = \"No files attached.\";\n} else {\n  const lines = selectedFiles.map((f, idx) => {\n    const name = f.name || f.id || `File ${idx + 1}`;\n    const url  = f.url || \"\";\n    if (url) {\n      return `${idx + 1}. ${name} (${url})`;\n    } else {\n      return `${idx + 1}. ${name}`;\n    }\n  });\n  filesText = \"Files:\\n\" + lines.join(\"\\n\");\n}\n\nreturn [\n  {\n    json: {\n      entryType,\n      title,\n      description,\n      timeRange,\n      selectedFiles,\n      filesText,\n    },\n  },\n];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[208,0],"id":"e1f3da90-7e1b-4b27-8cc2-02e90a35d480","name":"Prepare Entry Data"},{"parameters":{"rules":{"values":[{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"strict","version":2},"conditions":[{"leftValue":"={{ $json[\"entryType\"] }}","rightValue":"thoughts","operator":{"type":"string","operation":"equals"},"id":"5bcf0664-1860-4d22-9f20-0e925e57e2b1"}],"combinator":"and"}},{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"strict","version":2},"conditions":[{"id":"d4357a3a-312b-4f2c-9f73-1fc76482215a","leftValue":"={{ $json[\"entryType\"] }}","rightValue":"journal","operator":{"type":"string","operation":"equals","name":"filter.operator.equals"}}],"combinator":"and"}},{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"strict","version":2},"conditions":[{"id":"1e6e6167-0c45-4e82-b10a-10fcc404dcaa","leftValue":"={{ $json[\"entryType\"] }}","rightValue":"plans","operator":{"type":"string","operation":"equals","name":"filter.operator.equals"}}],"combinator":"and"}}]},"options":{}},"type":"n8n-nodes-base.switch","typeVersion":3.3,"position":[416,-16],"id":"e759f5b3-1ffe-49e8-a25a-78aa7b5b6645","name":"Route by Type"},{"parameters":{"jsCode":"// Build Notion external-URL blocks using fserver URLs\n\nconst page = items[0].json || {};\nconst pageId = page.id;\n\n// Get selectedFiles from Prepare Entry Data\nconst selectedFiles =\n  ($node[\"Prepare Entry Data\"].json &&\n   Array.isArray($node[\"Prepare Entry Data\"].json.selectedFiles))\n    ? $node[\"Prepare Entry Data\"].json.selectedFiles\n    : [];\n\n// Decide block type based on file extension\nfunction guessBlockType(url) {\n  if (!url) return { type: \"file\", key: \"file\" };\n  const lower = url.toLowerCase();\n\n  if (lower.match(/\\.(mp4|mov|webm|mkv)$/)) {\n    return { type: \"video\", key: \"video\" };\n  }\n  if (lower.match(/\\.(mp3|m4a|wav|ogg)$/)) {\n    return { type: \"audio\", key: \"audio\" };\n  }\n  if (lower.match(/\\.(png|jpg|jpeg|gif|webp|bmp|svg)$/)) {\n    return { type: \"image\", key: \"image\" };\n  }\n  return { type: \"file\", key: \"file\" };\n}\n\nconst children = selectedFiles.map((f) => {\n  // IMPORTANT: make sure `url` here is the fserver URL (min.velvetcld...)\n  const url = f.url || f.thumbnailUrl || \"\";\n  const name = f.name || \"Unnamed file\";\n  const block = guessBlockType(url);\n\n  return {\n    object: \"block\",\n    type: block.type,\n    [block.key]: {\n      type: \"external\",\n      external: { url },\n      caption: [{ type: \"text\", text: { content: name } }],\n    },\n  };\n});\n\nreturn [\n  {\n    json: {\n      pageId,\n      children,\n    },\n  },\n];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[832,-128],"id":"5f32df8e-1fee-4693-b3de-1d9915af1f2d","name":"Build File Blocks (Thoughts)"},{"parameters":{"method":"PATCH","url":"={{ 'https://api.notion.com/v1/blocks/' + $json[\"pageId\"] + '/children' }}\n","sendHeaders":true,"headerParameters":{"parameters":[{"name":"Authorization","value":"Bearer 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"},{"name":"Notion-Version","value":"2022-06-28"},{"name":"Content-Type","value":"application/json"}]},"sendBody":true,"specifyBody":"json","jsonBody":"={{ JSON.stringify({ children: $json[\"children\"] }) }}\n\n","options":{}},"type":"n8n-nodes-base.httpRequest","typeVersion":4.3,"position":[1040,-128],"id":"0cfcdffc-b2da-4e37-9929-c0e3b525c01a","name":"Append Files (Thoughts)"},{"parameters":{"resource":"databasePage","databaseId":{"__rl":true,"value":"234dcbfd-8835-805f-8ba9-de38ea537985","mode":"list","cachedResultName":"Thoughts","cachedResultUrl":"https://www.notion.so/234dcbfd8835805f8ba9de38ea537985"},"title":"={{ $json[\"title\"] }}","simple":false,"propertiesUi":{"propertyValues":[{"key":"Thought|title","title":"={{ $json[\"title\"] }}"},{"key":"content|rich_text","richText":true,"text":{"text":[{"text":"={{ $json[\"description\"] }}","annotationUi":{}}]}}]},"options":{}},"type":"n8n-nodes-base.notion","typeVersion":2.2,"position":[624,-128],"id":"1b580043-73e6-46aa-b389-d156dd01e08d","name":"Create Thoughts Page","credentials":{"notionApi":{"id":"j9X7YFSp6m90N06v","name":"Notion account"}}},{"parameters":{"resource":"databasePage","databaseId":{"__rl":true,"value":"228dcbfd-8835-80ab-9727-ee036d84f48e","mode":"list","cachedResultName":"Journal Entries","cachedResultUrl":"https://www.notion.so/228dcbfd883580ab9727ee036d84f48e"},"title":"={{ $json[\"title\"] }}","simple":false,"propertiesUi":{"propertyValues":[{"key":"Title|title","title":"={{ $json[\"title\"] }}"},{"key":"Content|rich_text","richText":true,"text":{"text":[{"text":"={{ $json[\"description\"] }}","annotationUi":{}}]}}]},"options":{}},"type":"n8n-nodes-base.notion","typeVersion":2.2,"position":[624,16],"id":"3d4701e4-4574-4aab-83e0-02df775508d1","name":"Create Journal Page","credentials":{"notionApi":{"id":"j9X7YFSp6m90N06v","name":"Notion account"}}},{"parameters":{"jsCode":"// Build Notion external-URL blocks using fserver URLs\n\nconst page = items[0].json || {};\nconst pageId = page.id;\n\n// Get selectedFiles from Prepare Entry Data\nconst selectedFiles =\n  ($node[\"Prepare Entry Data\"].json &&\n   Array.isArray($node[\"Prepare Entry Data\"].json.selectedFiles))\n    ? $node[\"Prepare Entry Data\"].json.selectedFiles\n    : [];\n\n// Decide block type based on file extension\nfunction guessBlockType(url) {\n  if (!url) return { type: \"file\", key: \"file\" };\n  const lower = url.toLowerCase();\n\n  if (lower.match(/\\.(mp4|mov|webm|mkv)$/)) {\n    return { type: \"video\", key: \"video\" };\n  }\n  if (lower.match(/\\.(mp3|m4a|wav|ogg)$/)) {\n    return { type: \"audio\", key: \"audio\" };\n  }\n  if (lower.match(/\\.(png|jpg|jpeg|gif|webp|bmp|svg)$/)) {\n    return { type: \"image\", key: \"image\" };\n  }\n  return { type: \"file\", key: \"file\" };\n}\n\nconst children = selectedFiles.map((f) => {\n  // IMPORTANT: make sure `url` here is the fserver URL (min.velvetcld...)\n  const url = f.url || f.thumbnailUrl || \"\";\n  const name = f.name || \"Unnamed file\";\n  const block = guessBlockType(url);\n\n  return {\n    object: \"block\",\n    type: block.type,\n    [block.key]: {\n      type: \"external\",\n      external: { url },\n      caption: [{ type: \"text\", text: { content: name } }],\n    },\n  };\n});\n\nreturn [\n  {\n    json: {\n      pageId,\n      children,\n    },\n  },\n];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[832,16],"id":"bce63d51-ea7e-44cb-bce8-fd012c4f5363","name":"Build File Blocks (Journal)"},{"parameters":{"resource":"databasePage","databaseId":{"__rl":true,"value":"2a4dcbfd-8835-80ec-a760-eec0e8839846","mode":"list","cachedResultName":"Plans","cachedResultUrl":"https://www.notion.so/2a4dcbfd883580eca760eec0e8839846"},"title":"={{ $json[\"title\"] }}","simple":false,"propertiesUi":{"propertyValues":[{"key":"Title|title","title":"={{ $json[\"title\"] }}"},{"key":"Content|rich_text","richText":true,"text":{"text":[{"text":"={{ $json[\"description\"] }}","annotationUi":{}}]}}]},"options":{}},"type":"n8n-nodes-base.notion","typeVersion":2.2,"position":[624,208],"id":"cd8decc7-22ee-4a83-9e6c-4a4b38cda849","name":"Create Plan Page","credentials":{"notionApi":{"id":"j9X7YFSp6m90N06v","name":"Notion account"}}},{"parameters":{"jsCode":"// Build Notion external-URL blocks using fserver URLs\n\nconst page = items[0].json || {};\nconst pageId = page.id;\n\n// Get selectedFiles from Prepare Entry Data\nconst selectedFiles =\n  ($node[\"Prepare Entry Data\"].json &&\n   Array.isArray($node[\"Prepare Entry Data\"].json.selectedFiles))\n    ? $node[\"Prepare Entry Data\"].json.selectedFiles\n    : [];\n\n// Decide block type based on file extension\nfunction guessBlockType(url) {\n  if (!url) return { type: \"file\", key: \"file\" };\n  const lower = url.toLowerCase();\n\n  if (lower.match(/\\.(mp4|mov|webm|mkv)$/)) {\n    return { type: \"video\", key: \"video\" };\n  }\n  if (lower.match(/\\.(mp3|m4a|wav|ogg)$/)) {\n    return { type: \"audio\", key: \"audio\" };\n  }\n  if (lower.match(/\\.(png|jpg|jpeg|gif|webp|bmp|svg)$/)) {\n    return { type: \"image\", key: \"image\" };\n  }\n  return { type: \"file\", key: \"file\" };\n}\n\nconst children = selectedFiles.map((f) => {\n  // IMPORTANT: make sure `url` here is the fserver URL (min.velvetcld...)\n  const url = f.url || f.thumbnailUrl || \"\";\n  const name = f.name || \"Unnamed file\";\n  const block = guessBlockType(url);\n\n  return {\n    object: \"block\",\n    type: block.type,\n    [block.key]: {\n      type: \"external\",\n      external: { url },\n      caption: [{ type: \"text\", text: { content: name } }],\n    },\n  };\n});\n\nreturn [\n  {\n    json: {\n      pageId,\n      children,\n    },\n  },\n];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[832,208],"id":"9299adcb-b2af-416a-a045-1065129bbb02","name":"Build File Blocks (Plan)"},{"parameters":{"jsCode":"// Build simple response for the caller, based on which branch ran.\n\nconst dataFromPrepare = $node[\"Prepare Entry Data\"].json || {};\nconst entryType = (dataFromPrepare.entryType || \"thoughts\").toLowerCase();\n\nconst mapping = {\n  thoughts: \"Create Thoughts Page\",\n  journal: \"Create Journal Page\",\n  plans: \"Create Plan Page\", // <-- make sure this matches your exact node name\n};\n\nconst nodeName = mapping[entryType] || mapping.thoughts;\n\n// Only read from the node that actually ran\nconst page = ($node[nodeName] && $node[nodeName].json) ? $node[nodeName].json : {};\n\nreturn [\n  {\n    json: {\n      success: true,\n      id: page.id || null,\n      url: page.url || null,\n      entryType,\n    },\n  },\n];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[1248,16],"id":"ff75add9-83b7-4dba-9749-fa0558e2a330","name":"Build Response"},{"parameters":{"respondWith":"text","responseBody":"={{ JSON.stringify({\n  success: true,\n  pageUrl: \"https://www.notion.so/\" + $json.id,\n  entryType: $json.entryType\n}) }}\n","options":{"responseCode":200,"responseHeaders":{"entries":[{"name":"Content-Type","value":"application/json"}]}}},"type":"n8n-nodes-base.respondToWebhook","typeVersion":1.4,"position":[1456,16],"id":"a2a6244d-0ff2-47a5-ae53-75f21a09098d","name":"Respond to Webhook"},{"parameters":{"method":"PATCH","url":"={{ 'https://api.notion.com/v1/blocks/' + $json[\"pageId\"] + '/children' }}\n","sendHeaders":true,"headerParameters":{"parameters":[{"name":"Authorization","value":"Bearer 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"},{"name":"Notion-Version","value":"2022-06-28"},{"name":"Content-Type","value":"application/json"}]},"sendBody":true,"specifyBody":"json","jsonBody":"={{ JSON.stringify({ children: $json[\"children\"] }) }}\n\n","options":{}},"type":"n8n-nodes-base.httpRequest","typeVersion":4.3,"position":[1040,16],"id":"b292f1be-01ff-4204-bf9d-653ddf697a0a","name":"Append Files (Journal)"},{"parameters":{"method":"PATCH","url":"={{ 'https://api.notion.com/v1/blocks/' + $json[\"pageId\"] + '/children' }}\n","sendHeaders":true,"headerParameters":{"parameters":[{"name":"Authorization","value":"Bearer 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"},{"name":"Notion-Version","value":"2022-06-28"},{"name":"Content-Type","value":"application/json"}]},"sendBody":true,"specifyBody":"json","jsonBody":"={{ JSON.stringify({ children: $json[\"children\"] }) }}\n\n","options":{}},"type":"n8n-nodes-base.httpRequest","typeVersion":4.3,"position":[1040,208],"id":"39830698-b07b-4163-b4a8-820fd33e319e","name":"Append Files (Plan)"}],"connections":{"Create Entry Webhook":{"main":[[{"node":"Prepare Entry Data","type":"main","index":0}]]},"Prepare Entry Data":{"main":[[{"node":"Route by Type","type":"main","index":0}]]},"Route by Type":{"main":[[{"node":"Create Thoughts Page","type":"main","index":0}],[{"node":"Create Journal Page","type":"main","index":0}],[{"node":"Create Plan Page","type":"main","index":0}]]},"Build File Blocks (Thoughts)":{"main":[[{"node":"Append Files (Thoughts)","type":"main","index":0}]]},"Create Thoughts Page":{"main":[[{"node":"Build File Blocks (Thoughts)","type":"main","index":0}]]},"Create Journal Page":{"main":[[{"node":"Build File Blocks (Journal)","type":"main","index":0}]]},"Build File Blocks (Journal)":{"main":[[{"node":"Append Files (Journal)","type":"main","index":0}]]},"Create Plan Page":{"main":[[{"node":"Build File Blocks (Plan)","type":"main","index":0}]]},"Build File Blocks (Plan)":{"main":[[{"node":"Append Files (Plan)","type":"main","index":0}]]},"Append Files (Thoughts)":{"main":[[{"node":"Build Response","type":"main","index":0}]]},"Build Response":{"main":[[{"node":"Respond to Webhook","type":"main","index":0}]]},"Append Files (Journal)":{"main":[[{"node":"Build Response","type":"main","index":0}]]},"Append Files (Plan)":{"main":[[{"node":"Build Response","type":"main","index":0}]]}},"authors":"system migration","name":null,"description":null,"autosaved":false},"tags":[]}