{
  "id": "anA1Y5vVdcZqIAFg902kQ",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Create FAQ articles from Slack threads to Notion and Zendesk",
  "tags": [],
  "nodes": [
    {
      "id": "e1291817-3be3-4298-a76c-5c7d97dddcd7",
      "name": "Slack Trigger - :book: Reaction",
      "type": "n8n-nodes-base.slackTrigger",
      "position": [
        -1616,
        96
      ],
      "parameters": {
        "options": {},
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f18e3bd3-b4fa-4e9d-9e20-bdc692b7be58",
      "name": "IF - :book: Reaction Check",
      "type": "n8n-nodes-base.if",
      "position": [
        -1168,
        96
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "e4f5a6b7-8c9d-0e1f-2a3b-4c5d6e7f8a9b",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.reaction }}",
              "rightValue": "book"
            },
            {
              "id": "f5e6d7c8-9d0e-1f2a-3b4c-5d6e7f8a9b0c",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.item.type }}",
              "rightValue": "message"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "54cc93df-d45a-4847-bf2b-f920cfed9e3c",
      "name": "Slack - Get Parent Message",
      "type": "n8n-nodes-base.slack",
      "position": [
        -944,
        96
      ],
      "parameters": {
        "operation": "get"
      },
      "typeVersion": 2.1
    },
    {
      "id": "2fe8d288-e1f7-48cf-acbf-455c3c16fccc",
      "name": "Slack - Get Thread",
      "type": "n8n-nodes-base.slack",
      "position": [
        -720,
        96
      ],
      "parameters": {
        "operation": "getAll"
      },
      "typeVersion": 2.1
    },
    {
      "id": "f54db11a-baea-4ccd-aa9c-8d7729650e98",
      "name": "Code - Format Conversation",
      "type": "n8n-nodes-base.code",
      "position": [
        -496,
        96
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Format thread messages\nconst messages = $input.all();\nconst config = $('Workflow Configuration1').item.json;\nlet conversation = '';\nlet metadata = {};\n\nif (messages && messages.length > 0) {\n  // Treat the first message as the question\n  const firstMsg = messages[0].json;\n  conversation = `Q: ${firstMsg.text || ''}\\n`;\n  \n  metadata = {\n    question_author: firstMsg.user || '',\n    channel_id: firstMsg.channel || $json.channel,\n    thread_ts: firstMsg.thread_ts || firstMsg.ts,\n    created_at: new Date(parseFloat(firstMsg.ts) * 1000).toISOString(),\n    channel_name: $json.channel_name || 'unknown',\n    slack_workspace_id: config.slackWorkspaceId // Get from Config node\n  };\n  \n  // Format replies as answers\n  for (let i = 1; i < messages.length; i++) {\n    const reply = messages[i].json;\n    conversation += `A${i}: ${reply.user || 'Unknown'} - ${reply.text || ''}\\n`;\n  }\n}\n\nreturn {\n  conversation_for_ai: conversation.trim(),\n  ...metadata\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "97100810-482d-43f6-afdd-97a7424f4faa",
      "name": "OpenAI - Generate FAQ",
      "type": "n8n-nodes-base.openAi",
      "position": [
        -272,
        96
      ],
      "parameters": {
        "operation": "message",
        "requestOptions": {}
      },
      "typeVersion": 1.1
    },
    {
      "id": "945df56b-50de-4287-bc32-a3dbcb0b9a45",
      "name": "Code - Prepare Notion Data",
      "type": "n8n-nodes-base.code",
      "position": [
        -48,
        96
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Merge OpenAI output with metadata\nconst aiResponse = JSON.parse($json.content || '{}');\nconst prevData = $input.item.json;\nconst config = $('Workflow Configuration1').item.json;\n\n// Generate Slack Thread URL (Using ID from Config node)\nconst workspaceId = config.slackWorkspaceId || 'YOUR_WORKSPACE_ID';\nconst channelId = prevData.channel_id || '';\nconst threadTsClean = (prevData.thread_ts || '').replace('.', '');\nconst threadUrl = `https://app.slack.com/client/${workspaceId}/${channelId}/thread/${channelId}-${threadTsClean}`;\n\nreturn {\n  title: aiResponse.faq_question || 'Untitled FAQ',\n  answer_markdown: aiResponse.faq_answer || '',\n  tags: aiResponse.tags || [],\n  summary: aiResponse.summary || '',\n  slack_thread_url: threadUrl,\n  channel_name: prevData.channel_name || 'unknown',\n  created_at: prevData.created_at || new Date().toISOString(),\n  notion_database_id: config.notionDatabaseId\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "bdcfb4e4-ba08-4a3d-9c48-c24f266852c2",
      "name": "Notion - Create FAQ Page",
      "type": "n8n-nodes-base.notion",
      "position": [
        176,
        96
      ],
      "parameters": {
        "blockUi": {
          "blockValues": [
            {
              "richText": "={{ $json.answer_markdown }}"
            }
          ]
        },
        "options": {},
        "resource": "databasePage",
        "databaseId": "={{ $json.notion_database_id }}",
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Name",
              "title": "={{ $json.title }}"
            },
            {
              "key": "Summary",
              "richText": "={{ $json.summary }}"
            },
            {
              "key": "Tags"
            },
            {
              "key": "Source"
            },
            {
              "key": "Channel"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "39fd6ca0-6ead-4238-b21a-2d12731d3814",
      "name": "Zendesk - Create Article (Optional)",
      "type": "n8n-nodes-base.zendesk",
      "position": [
        400,
        96
      ],
      "parameters": {
        "resource": "article"
      },
      "typeVersion": 1
    },
    {
      "id": "2d0baad4-acf8-4cb4-aefe-498dd0d3d2c4",
      "name": "Slack - Notify Completion",
      "type": "n8n-nodes-base.slack",
      "position": [
        624,
        96
      ],
      "parameters": {
        "text": "FAQ article automatically generated from this thread \ud83d\udcda\nNotion: {{ $('Notion - Create FAQ Page').item.json.url }}\nZendesk: {{ $('Zendesk - Create Article (Optional)').item.json.html_url || 'Skipped' }}",
        "otherOptions": {}
      },
      "typeVersion": 2.1
    },
    {
      "id": "4c255841-5341-4b48-a29e-8d8c9dcd4db5",
      "name": "Workflow Configuration1",
      "type": "n8n-nodes-base.set",
      "position": [
        -1392,
        96
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "id-1",
              "name": "slackWorkspaceId",
              "type": "string",
              "value": "<__PLACEHOLDER_VALUE__YOUR_SLACK_WORKSPACE_ID__>"
            },
            {
              "id": "id-2",
              "name": "notionDatabaseId",
              "type": "string",
              "value": "<__PLACEHOLDER_VALUE__YOUR_NOTION_DATABASE_ID__>"
            },
            {
              "id": "id-3",
              "name": "zendeskSectionId",
              "type": "string",
              "value": "<__PLACEHOLDER_VALUE__OPTIONAL_ZENDESK_SECTION_ID__>"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "62697e20-3024-42f9-828c-67d4e5eacb2b",
      "name": "Workflow Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2304,
        -512
      ],
      "parameters": {
        "width": 460,
        "height": 552,
        "content": "## How it works\nWhen someone reacts to a Slack thread with \ud83d\udcda, this workflow captures the entire conversation, uses AI to transform it into a well-formatted FAQ article, then saves it to your Notion knowledge base and optionally to Zendesk. A confirmation message is posted back to the original Slack thread.\n\nPerfect for building internal documentation from support conversations, technical discussions, or onboarding questions.\n\n## Setup steps\n1. Configure Slack app with reaction permissions and add the bot to your channels\n2. Create a Notion database with properties: Name (title), Summary (text), Tags (multi-select), Source (URL), Channel (text)\n3. Get your Slack Workspace ID from the URL when logged into Slack web\n4. Add your API credentials: Slack, OpenAI, Notion, and optionally Zendesk\n5. Update the Workflow Configuration node with your workspace and database IDs\n6. Test by reacting to a message with the \ud83d\udcda emoji"
      },
      "typeVersion": 1
    },
    {
      "id": "97600c4d-de5f-4cbd-a4ca-ccf945970e18",
      "name": "Group 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1680,
        -32
      ],
      "parameters": {
        "color": 7,
        "width": 664,
        "height": 296,
        "content": "## Trigger & Validation\nDetects \ud83d\udcda reaction on messages and validates it's a proper message (not a file or other item type)."
      },
      "typeVersion": 1
    },
    {
      "id": "5beb1268-63de-4bc7-8ae2-8273f7ce4671",
      "name": "Group 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1008,
        -32
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 296,
        "content": "## Conversation Retrieval\nFetches the parent message and all thread replies to capture the full Q&A context."
      },
      "typeVersion": 1
    },
    {
      "id": "8f80973d-8e2d-42ca-af80-8822021ae098",
      "name": "Group 3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -560,
        -32
      ],
      "parameters": {
        "color": 7,
        "width": 656,
        "height": 296,
        "content": "## AI Processing\nFormats the conversation into Q&A structure, sends to OpenAI for FAQ generation, then prepares structured data for storage."
      },
      "typeVersion": 1
    },
    {
      "id": "c4bbedbb-b7d4-4200-9157-1f5366c3cdfb",
      "name": "Group 4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        112,
        -32
      ],
      "parameters": {
        "color": 7,
        "width": 648,
        "height": 296,
        "content": "## Storage & Notification\nSaves the FAQ to Notion (required) and Zendesk (optional), then notifies the Slack thread with links to the created articles."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "",
  "connections": {
    "Slack - Get Thread": {
      "main": [
        [
          {
            "node": "Code - Format Conversation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI - Generate FAQ": {
      "main": [
        [
          {
            "node": "Code - Prepare Notion Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Workflow Configuration1": {
      "main": [
        [
          {
            "node": "IF - :book: Reaction Check",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notion - Create FAQ Page": {
      "main": [
        [
          {
            "node": "Zendesk - Create Article (Optional)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Format Conversation": {
      "main": [
        [
          {
            "node": "OpenAI - Generate FAQ",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Prepare Notion Data": {
      "main": [
        [
          {
            "node": "Notion - Create FAQ Page",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - :book: Reaction Check": {
      "main": [
        [
          {
            "node": "Slack - Get Parent Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack - Get Parent Message": {
      "main": [
        [
          {
            "node": "Slack - Get Thread",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack Trigger - :book: Reaction": {
      "main": [
        [
          {
            "node": "Workflow Configuration1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Zendesk - Create Article (Optional)": {
      "main": [
        [
          {
            "node": "Slack - Notify Completion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}