{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "18821cef-db16-4989-a24f-98547d422982",
      "name": "Workflow Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -224,
        -304
      ],
      "parameters": {
        "width": 540,
        "height": 620,
        "content": "## Meeting notes automation\n\nAutomatically process meeting recordings by transcribing, summarizing, and extracting action items with Gemini AI. Results are organized in Notion and shared via Slack.\n\n### How it works\n1. A form trigger lets you upload a meeting recording file and enter the meeting title.\n2. The recording is uploaded to Gemini Files API for processing.\n3. Gemini AI generates a structured summary with key decisions, action items, and follow-ups.\n4. A Notion page is created with the full summary and a checklist of action items.\n5. The team is notified in Slack with a link to the Notion page.\n\n### Setup steps\n1. Add a **Google Gemini API** credential for file upload and analysis.\n2. Add a **Notion API** credential and create a database with columns: Title, Date, Summary, Action Items, Status.\n3. Add a **Slack OAuth2** credential and set your meetings channel.\n4. Activate the workflow and open the form URL to start processing recordings."
      },
      "typeVersion": 1
    },
    {
      "id": "52d8297b-a617-4d51-b750-78798ccb4dad",
      "name": "Upload section note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        336,
        -304
      ],
      "parameters": {
        "color": 7,
        "width": 260,
        "height": 332,
        "content": "## Upload recording\nCollects the audio file and meeting title from a web form."
      },
      "typeVersion": 1
    },
    {
      "id": "f6c60367-f04d-4b62-9950-f74d7ce82fcc",
      "name": "AI section note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        608,
        -304
      ],
      "parameters": {
        "color": 7,
        "width": 500,
        "height": 332,
        "content": "## AI processing\nUploads the file to Gemini and generates a structured meeting summary."
      },
      "typeVersion": 1
    },
    {
      "id": "24c4f10e-8d52-4fd9-9ee0-1ed7b4e22839",
      "name": "Output section note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1120,
        -304
      ],
      "parameters": {
        "color": 7,
        "width": 628,
        "height": 332,
        "content": "## Save and notify\nCreates a Notion page with the summary and alerts the team on Slack."
      },
      "typeVersion": 1
    },
    {
      "id": "538ffd25-3969-4630-9946-8720d95d50c8",
      "name": "Upload meeting recording",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        400,
        -144
      ],
      "parameters": {
        "path": "e5b77a90-f97d-47d8-bba2-75afca30c8d7",
        "options": {},
        "formTitle": "Meeting Notes Processor",
        "formFields": {
          "values": [
            {
              "fieldType": "file",
              "fieldLabel": "Meeting Recording",
              "requiredField": true
            },
            {
              "fieldLabel": "Meeting Title",
              "placeholder": "Weekly standup - Feb 28",
              "requiredField": true
            }
          ]
        },
        "formDescription": "Upload a meeting recording to generate AI-powered notes and action items."
      },
      "typeVersion": 2
    },
    {
      "id": "ff9a4dbf-c27e-489a-88b3-32a59bab5896",
      "name": "Upload recording to Gemini",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        688,
        -144
      ],
      "parameters": {
        "url": "https://generativelanguage.googleapis.com/upload/v1beta/files",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "binaryData",
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Goog-Upload-Command",
              "value": "upload, finalize"
            },
            {
              "name": "X-Goog-Upload-Protocol",
              "value": "raw"
            }
          ]
        },
        "inputDataFieldName": "Meeting Recording",
        "nodeCredentialType": "googlePalmApi"
      },
      "typeVersion": 4.4
    },
    {
      "id": "d1068503-d9f1-4e63-8834-255a55ff4ced",
      "name": "Analyze recording with Gemini",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        896,
        -144
      ],
      "parameters": {
        "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"contents\": [{\n    \"parts\": [\n      {\"fileData\": {\"mimeType\": \"{{ $json.file.mimeType }}\", \"fileUri\": \"{{ $json.file.uri }}\"}},\n      {\"text\": \"Analyze this meeting recording. Provide:\\n1. Meeting summary (3-5 paragraphs)\\n2. Key decisions made\\n3. Action items with assignees if mentioned\\n4. Follow-up topics\\n\\nOutput as JSON with keys: summary, decisions (array), actionItems (array of {task, assignee, deadline}), followUps (array)\"}\n    ]\n  }]\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googlePalmApi"
      },
      "typeVersion": 4.4
    },
    {
      "id": "a5af1345-769f-4471-a642-b042984e4c50",
      "name": "Format meeting notes",
      "type": "n8n-nodes-base.code",
      "position": [
        1168,
        -144
      ],
      "parameters": {
        "jsCode": "// Parse Gemini response\nvar response = $input.first().json;\nvar text = '';\ntry { text = response.candidates[0].content.parts[0].text; } catch(e) { text = '{}'; }\nvar parsed;\ntry { parsed = JSON.parse(text); } catch(e) { parsed = {summary: text, decisions: [], actionItems: [], followUps: []}; }\nvar meetingTitle = $('Upload meeting recording').first().json['Meeting Title'] || 'Untitled meeting';\nvar actionList = (parsed.actionItems || []).map(function(a) { return '- [ ] ' + (a.task || a) + (a.assignee ? ' (@' + a.assignee + ')' : ''); }).join('\\n');\nreturn { json: { title: meetingTitle, summary: parsed.summary || '', decisions: (parsed.decisions || []).join('\\n- '), actionItems: actionList, followUps: (parsed.followUps || []).join('\\n- '), date: new Date().toISOString() } };"
      },
      "typeVersion": 2
    },
    {
      "id": "2dad38ed-1184-43fa-a38b-de880292b0be",
      "name": "Create notes in Notion",
      "type": "n8n-nodes-base.notion",
      "position": [
        1376,
        -144
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "4fcec11c-263f-4d58-bf78-b1df0410bdf2",
      "name": "Notify team on Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        1568,
        -144
      ],
      "parameters": {
        "text": "=:memo: *Meeting notes ready: {{ $json.title }}*\n\n*Summary:* {{ $json.summary.substring(0, 300) }}...\n\n*Action items:*\n{{ $json.actionItems }}\n\nFull notes in Notion.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": ""
        },
        "otherOptions": {}
      },
      "typeVersion": 2.3
    }
  ],
  "connections": {
    "Format meeting notes": {
      "main": [
        [
          {
            "node": "Create notes in Notion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create notes in Notion": {
      "main": [
        [
          {
            "node": "Notify team on Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload meeting recording": {
      "main": [
        [
          {
            "node": "Upload recording to Gemini",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload recording to Gemini": {
      "main": [
        [
          {
            "node": "Analyze recording with Gemini",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze recording with Gemini": {
      "main": [
        [
          {
            "node": "Format meeting notes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}