{
  "name": "PF \u2013 WF-03 Canva Grafik Generator",
  "nodes": [
    {
      "parameters": {
        "content": "## PF \u2013 WF-03 Canva Grafik Generator\n\n**Ablauf:**\nSharePoint (Status=Freigegeben) \u2192 Claude + Canva MCP\n\u2192 Seite 3 Vorlage exportieren \u2192 SharePoint speichern\n\n**Vorlage:** DAG_tS-3P0k (Seite 3)\n**Platzhalter:** THEMA \u2192 wird ersetzt durch field_1\n\n**\u26a0\ufe0f Voraussetzung:**\nCanva OAuth Token in n8n Environment Variable:\n`CANVA_OAUTH_TOKEN` setzen\n(Settings \u2192 Environment Variables)",
        "height": 220,
        "width": 900,
        "color": 5
      },
      "id": "wf03-sticky-main",
      "name": "Sticky Note WF-03",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "content": "**Feldmapping SharePoint:**\n\nLesen:\nfield_1  = Thema (f\u00fcr THEMA-Ersatz)\nfield_6  = Status (Filter: Freigegeben)\nfield_8  = Bild_Dateiname (0 = noch kein Bild)\nAUSWEIS  = Item-ID\n\nSchreiben:\nfield_8  = Canva Export-URL",
        "width": 260,
        "color": 3
      },
      "id": "wf03-sticky-fields",
      "name": "Feldmapping",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        240,
        240
      ]
    },
    {
      "parameters": {
        "content": "**v1 \u2013 2026-05-10**\n\nCanva Vorlage: DAG_tS-3P0k\nSeite 3: Platzhalter THEMA\n\nAblauf:\n1. SP: Items Status=Freigegeben\n2. Filter: field_8 = 0 (kein Bild)\n3. Claude API + Canva MCP:\n   - THEMA ersetzen\n   - Seite 3 exportieren\n4. Export-URL \u2192 SharePoint\n\nTODO v2:\n- Template-Kopie pro Post\n- Bild in SP hochladen\n- Status \u2192 Geplant setzen",
        "width": 260,
        "color": 6
      },
      "id": "wf03-changelog",
      "name": "Changelog v1",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        2200,
        240
      ]
    },
    {
      "parameters": {},
      "id": "wf03-manual-trigger",
      "name": "Manueller Test-Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        272,
        448
      ]
    },
    {
      "parameters": {
        "resource": "item",
        "site": {
          "__rl": true,
          "value": "physiofuchs889.sharepoint.com,c74040a2-0d6b-4385-b514-fbd9830a56ac,7a7842d6-ea6c-440d-aeed-580bdd2a091c",
          "mode": "list",
          "cachedResultName": "Physio Fuchs Administration"
        },
        "list": {
          "__rl": true,
          "value": "d17a6a6f-e6ef-457d-a2a9-4c30ea56120f",
          "mode": "list",
          "cachedResultName": "PF-Content-Kalender-2026"
        },
        "filter": "=",
        "options": {
          "fields": [
            "fields"
          ]
        },
        "simplify": false,
        "requestOptions": {}
      },
      "type": "n8n-nodes-base.microsoftSharePoint",
      "typeVersion": 1,
      "position": [
        512,
        448
      ],
      "id": "wf03-sp-get",
      "name": "Get many items",
      "credentials": {
        "microsoftSharePointOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "filter-freigegeben",
              "leftValue": "={{ $json.fields.field_6 }}",
              "rightValue": "Freigegeben",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            },
            {
              "id": "filter-kein-bild",
              "leftValue": "={{ $json.fields.field_8 }}",
              "rightValue": "0",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        800,
        448
      ],
      "id": "wf03-filter",
      "name": "Filter: Freigegeben + kein Bild"
    },
    {
      "parameters": {
        "jsCode": "const json = $input.item.json;\nconst f = json.Felder || json.fields || {};\n\n// SharePoint Daten extrahieren\nconst thema   = f.Field_1 || f.field_1 || '(kein Thema)';\nconst itemId  = parseInt(String(json.AUSWEIS || json.id || 0).trim(), 10);\n\n// System-Prompt f\u00fcr Claude mit Canva MCP\nconst systemPrompt = `Du bist ein Automatisierungsassistent f\u00fcr Physio Fuchs Social Media Grafiken.\n\nF\u00fchre diese Schritte VOLLST\u00c4NDIG und NACHEINANDER aus:\n1. Starte eine Editing-Session f\u00fcr Canva Design ID: DAG_tS-3P0k\n2. Ersetze auf Seite 3 (page_index 3) den Text \"THEMA\" durch den Thema-Text aus der Benutzernachricht (element_id: PB3DLldpqyKKJNBj-LBRqHYLk6GzfMW2G)\n3. Committe die \u00c4nderung\n4. Exportiere das Design als PNG (nur Seite 3)\n5. Warte bis der Export-Link verf\u00fcgbar ist\n6. Antworte AUSSCHLIESSLICH mit diesem JSON (kein Markdown, keine Erkl\u00e4rung):\n{\"export_url\":\"URL_ZUM_EXPORT\",\"design_id\":\"DAG_tS-3P0k\",\"thema\":\"THEMA_TEXT\",\"status\":\"success\"}`;\n\n// User-Nachricht\nconst userMessage = `Thema: ${thema}\\nSharePoint-Item-ID: ${itemId}\\n\\nBitte ersetze THEMA mit \"${thema}\" und exportiere Seite 3 als PNG.`;\n\nreturn {\n  json: {\n    // Claude API Payload mit Canva MCP\n    model: 'claude-sonnet-4-20250514',\n    max_tokens: 4000,\n    system: systemPrompt,\n    messages: [{ role: 'user', content: userMessage }],\n    mcp_servers: [\n      {\n        type: 'url',\n        url: 'https://mcp.canva.com/mcp',\n        name: 'canva'\n      }\n    ],\n    // Metadaten f\u00fcr sp\u00e4tere Nodes\n    _meta: {\n      sharepoint_item_id: itemId,\n      thema: thema\n    }\n  }\n};"
      },
      "id": "wf03-build-payload",
      "name": "Build Canva Payload",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1088,
        432
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.anthropic.com/v1/messages",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "x-api-key",
              "value": "={{ $env.ANTHROPIC_API_KEY }}"
            },
            {
              "name": "anthropic-version",
              "value": "2023-06-01"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify($json) }}",
        "options": {
          "timeout": 120000
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        1360,
        432
      ],
      "id": "wf03-claude-canva",
      "name": "Claude API + Canva MCP"
    },
    {
      "parameters": {
        "jsCode": "const response = $input.item.json;\nconst prev = $('Build Canva Payload').item.json._meta;\n\n// Claude Antwort auswerten\nconst content = response.content || [];\nlet exportUrl = '';\nlet status = 'failed';\nlet thema = prev?.thema || '';\n\nfor (const block of content) {\n  if (block.type === 'text' && block.text) {\n    const text = block.text.trim();\n    // JSON extrahieren\n    try {\n      const cleaned = text.replace(/```json\\n?/gi,'').replace(/```\\n?/g,'').trim();\n      const parsed = JSON.parse(cleaned);\n      exportUrl = parsed.export_url || '';\n      status = parsed.status || 'failed';\n      thema = parsed.thema || thema;\n      break;\n    } catch(e) {\n      // URL direkt aus Text extrahieren\n      const urlMatch = text.match(/https?:\\/\\/[^\\s\"']+/g);\n      if (urlMatch) {\n        // Canva Export URLs bevorzugen\n        const canvaUrl = urlMatch.find(u => u.includes('canva') || u.includes('export'));\n        exportUrl = canvaUrl || urlMatch[0];\n        status = 'success';\n      }\n    }\n  }\n}\n\nif (!exportUrl) {\n  throw new Error('Kein Export-URL in Claude Antwort gefunden. Response: ' + JSON.stringify(response).substring(0, 500));\n}\n\nreturn {\n  json: {\n    export_url: exportUrl,\n    design_id: 'DAG_tS-3P0k',\n    thema: thema,\n    status: status,\n    sharepoint_item_id: prev?.sharepoint_item_id || 0,\n    generated_at: new Date().toISOString()\n  }\n};"
      },
      "id": "wf03-parse-response",
      "name": "Parse Canva Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1632,
        432
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://physiofuchs889.sharepoint.com/sites/PhysioFuchsTW/_api/web/lists(guid'd17a6a6f-e6ef-457d-a2a9-4c30ea56120f')/items({{ $json.sharepoint_item_id }})",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "microsoftSharePointOAuth2Api",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Accept",
              "value": "application/json"
            },
            {
              "name": "X-HTTP-Method",
              "value": "MERGE"
            },
            {
              "name": "IF-MATCH",
              "value": "*"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "field_8",
              "value": "={{ $json.export_url }}"
            },
            {
              "name": "field_6",
              "value": "Geplant"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        1904,
        432
      ],
      "id": "wf03-sp-update",
      "name": "SharePoint: Bild-URL speichern",
      "credentials": {
        "microsoftSharePointOAuth2Api": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Manueller Test-Trigger": {
      "main": [
        [
          {
            "node": "Get many items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get many items": {
      "main": [
        [
          {
            "node": "Filter: Freigegeben + kein Bild",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter: Freigegeben + kein Bild": {
      "main": [
        [
          {
            "node": "Build Canva Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Canva Payload": {
      "main": [
        [
          {
            "node": "Claude API + Canva MCP",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Claude API + Canva MCP": {
      "main": [
        [
          {
            "node": "Parse Canva Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Canva Response": {
      "main": [
        [
          {
            "node": "SharePoint: Bild-URL speichern",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SharePoint: Bild-URL speichern": {
      "main": [
        []
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "wf03-v1-2026-05-10",
  "id": "PF-WF03-Canva",
  "tags": []
}