{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "422d9d8c-60a6-4b05-b608-7180436c5085",
      "name": "Create a database page",
      "type": "n8n-nodes-base.notion",
      "position": [
        576,
        224
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "7e30dccc-90f1-4d1f-beaf-53d80bff07b0",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1792,
        128
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "3816aa60-8b5f-4bfb-8bf1-c6b409cc3cc5",
      "name": "Config1",
      "type": "n8n-nodes-base.set",
      "position": [
        -1568,
        128
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "={\n  \"search_query\": \"extension:json n8n in:file\",\n  \"max_results\": 50,\n  \"ai_analysis_top\": 10,\n  \"SPREADSHEET_ID\": \"YOUR_SHEET_ID\",\n  \"SHEET_NAME\": \"Sheet1\"\n}"
      },
      "typeVersion": 3.4
    },
    {
      "id": "4a1a3eb6-1152-47c2-89ea-b803a5f8f4a0",
      "name": "GitHub Search1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1344,
        128
      ],
      "parameters": {
        "url": "https://api.github.com/search/code",
        "options": {
          "timeout": 15000
        },
        "sendQuery": true,
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "q",
              "value": "={{ $('Config1').item.json.search_query }}"
            },
            {
              "name": "per_page",
              "value": "={{ $('Config1').item.json.max_results }}"
            },
            {
              "name": "sort",
              "value": "indexed"
            },
            {
              "name": "order",
              "value": "desc"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/vnd.github.v3+json"
            },
            {
              "name": "User-Agent",
              "value": "n8n-workflow-finder"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "427ec2cf-36fe-4ec7-b29b-1a3714b1b2f3",
      "name": "Split Results1",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        -1120,
        128
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "items"
      },
      "typeVersion": 1
    },
    {
      "id": "2f4c107f-bdbe-4dfd-8749-b03cf29cfca2",
      "name": "Fetch Workflow JSON1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -896,
        128
      ],
      "parameters": {
        "url": "={{ $json.url }}",
        "options": {
          "timeout": 15000,
          "response": {
            "response": {
              "responseFormat": "text"
            }
          }
        },
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/vnd.github.v3.raw"
            },
            {
              "name": "User-Agent",
              "value": "n8n-workflow-finder"
            }
          ]
        }
      },
      "typeVersion": 4.2,
      "continueOnFail": true
    },
    {
      "id": "9df2b0ad-e26c-4658-8241-94993149b904",
      "name": "Process Workflows1",
      "type": "n8n-nodes-base.code",
      "position": [
        -672,
        128
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst splitItems = $('Split Results1').all();\nconst results = [];\nfor (let i = 0; i < items.length; i++) {\n  const item = items[i];\n  const splitItem = splitItems[i];\n  const repo = splitItem?.json?.repository;\n  if (!repo) continue;\n  try {\n    let txt = item.json.data || item.json;\n    let wf = null;\n    if (typeof txt === 'string') {\n      try { wf = JSON.parse(txt); } catch { continue; }\n    } else if (typeof txt === 'object' && txt.nodes) {\n      wf = txt;\n    } else { continue; }\n    const nodes = wf?.nodes || [];\n    if (!nodes.length) continue;\n    const filePath = splitItem.json.path || '';\n    const workflowName = wf.name || filePath.split('/').pop().replace(/\\.json$/,'') || 'Untitled Workflow';\n    const nodeTypes = [...new Set(nodes.map(n => n.type).filter(Boolean))];\n    const nodeTypeNames = nodeTypes.map(t => String(t).toLowerCase());\n    const hasAI = nodeTypeNames.some(t => t.includes('openai') || t.includes('langchain') || t.includes('agent') || t.includes('anthropic') || t.includes('gemini') || t.includes('groq') || t.includes('claude'));\n    const keyNodes = nodes.slice(0,3).map(n => n.name).filter(Boolean).join(', ');\n    results.push({ json: {\n      workflow_name: workflowName,\n      repository: repo.full_name || '',\n      stars: repo.stargazers_count || 0,\n      nodes: nodes.length,\n      node_types: nodeTypes.length,\n      has_ai: hasAI ? 'Yes' : 'No',\n      key_nodes: keyNodes || 'N/A',\n      description: (repo.description || '').substring(0,200),\n      repo_url: repo.html_url || '',\n      file_url: splitItem.json.html_url || '',\n      _sort_stars: repo.stargazers_count || 0\n    }});\n  } catch {}\n}\nresults.sort((a,b)=>b.json._sort_stars-a.json._sort_stars);\nreturn results.length ? results : [{json:{error:'No workflows found',message:'Adjust the search query'}}];"
      },
      "typeVersion": 2
    },
    {
      "id": "ac6d2def-02c9-47e9-b5fb-a3a2cc7e597a",
      "name": "Aggregate All1",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -448,
        128
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "341aae78-be07-49e1-915c-f00aab142c06",
      "name": "Prepare AI Analysis1",
      "type": "n8n-nodes-base.code",
      "position": [
        -224,
        128
      ],
      "parameters": {
        "jsCode": "let workflows = $json.data || [];\nlet topCount = ($nodes['Config'].data?.json?.ai_analysis_top) || 10;\nconst toS = v => (v==null?'':String(v));\nconst clean = (s,max=240)=>toS(s).replace(/[^\\x00-\\x7F]/g,'').replace(/\\s+/g,' ').trim().slice(0,max);\nconst n = v => Number.isFinite(Number(v))?Number(v):0;\nconst top = workflows.slice(0, topCount);\nconst items = top.map((w,i)=>`${i+1}. ${clean(w.workflow_name,120)}\\n   Repository: ${clean(w.repository,120)}\\n   Nodes: ${n(w.nodes)}, Stars: ${n(w.stars)}\\n   Key Nodes: ${clean(w.key_nodes,160)}\\n   Description: ${clean(w.description,220)}`);\nconst prompt = `Analyze the following n8n workflows and provide brief insights.\\nAlways respond in ENGLISH (en-US) only. If any input text is not English, translate it to concise English first.\\n\\n${items.join('\\n\\n')}\\n\\nFor each workflow, provide:\\n- description: one sentence (<= 25 words)\\n- use_case: one sentence (<= 20 words)\\n- difficulty: one of [\"Beginner\",\"Intermediate\",\"Advanced\"]\\n\\nSTRICT OUTPUT REQUIREMENTS:\\n- Return ONLY a valid JSON array (no markdown)\\n- ASCII characters only\\n- Schema example: [{\"index\":1,\"description\":\"...\",\"use_case\":\"...\",\"difficulty\":\"Beginner\"}]`;\nreturn [{json:{prompt, all_workflows:workflows, analyzed_count: top.length, total_count: workflows.length}}];"
      },
      "typeVersion": 2
    },
    {
      "id": "9782df9b-1a17-4630-aa12-74cedb62fb1f",
      "name": "AI Analysis1",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        0,
        128
      ],
      "parameters": {
        "text": "={{ $json.prompt }}",
        "options": {
          "systemMessage": "You are a workflow analyst. Return ONLY a valid JSON array where each item has exactly: index (int), description (string), use_case (string), difficulty (\"Beginner\"|\"Intermediate\"|\"Advanced\"). No extra fields or prose."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.6
    },
    {
      "id": "24386018-3b8b-4ac6-a80c-f3cee3c68356",
      "name": "OpenAI Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        16,
        352
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "24ba95a3-73f5-44a1-82d4-7a4965b16a1d",
      "name": "Structured Output Parser1",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        144,
        352
      ],
      "parameters": {
        "jsonSchemaExample": "[{\"index\":1,\"description\":\"string\",\"use_case\":\"string\",\"difficulty\":\"Beginner|Intermediate|Advanced\"}]"
      },
      "typeVersion": 1.2
    },
    {
      "id": "a8305a37-6dd2-4c74-9a0a-9a2a812cb237",
      "name": "Merge AI Results1",
      "type": "n8n-nodes-base.code",
      "position": [
        352,
        128
      ],
      "parameters": {
        "jsCode": "const aiOutput = $input.first().json; const prep = $('Prepare AI Analysis1').first().json; const all = prep.all_workflows||[]; const topN = Number(prep.analyzed_count||0);\nlet arr=[]; try{const raw=aiOutput.output??aiOutput; arr=Array.isArray(raw)?raw:JSON.parse(raw);}catch{arr=[]}\nconst map=new Map(); for(const it of arr){ if(it&&Number.isFinite(Number(it.index))) map.set(Number(it.index)-1,it); }\nconst S=v=>v==null?'':String(v); const clean=s=>S(s).replace(/[^\\x00-\\x7F]/g,'').replace(/\\s+/g,' ').trim();\nreturn all.map((wf,i)=>{ const a=i<topN?map.get(i):undefined; const aiDesc=clean(a?.description||''); const finalDesc=clean(wf.description||'')||aiDesc; const use=i<topN?clean(a?.use_case||''):''; const diff=i<topN?clean(a?.difficulty||''):'';\n  return {json:{workflow_name:wf.workflow_name,repository:wf.repository,stars:wf.stars,nodes:wf.nodes,node_types:wf.node_types,has_ai:wf.has_ai,key_nodes:wf.key_nodes,description:finalDesc,repo_url:wf.repo_url,file_url:wf.file_url,ai_description:aiDesc,ai_use_case:use,ai_difficulty:diff}}; });"
      },
      "typeVersion": 2
    },
    {
      "id": "90b1957e-816a-451a-a0ea-4b15de25dae9",
      "name": "Save to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        576,
        32
      ],
      "parameters": {
        "columns": {
          "value": {
            "Nodes": "={{ $json.nodes }}",
            "Stars": "={{ $json.stars }}",
            "File URL": "={{ $json.file_url }}",
            "Repo URL": "={{ $json.repo_url }}",
            "Use Case": "={{ $json.ai_use_case }}",
            "Workflow": "={{ $json.workflow_name }}",
            "Key Nodes": "={{ $json.key_nodes }}",
            "AI Powered": "={{ $json.has_ai }}",
            "AI Summary": "={{ $json.description }}",
            "Difficulty": "={{ $json.ai_difficulty }}",
            "Node Types": "={{ $json.node_types }}",
            "Repository": "={{ $json.repository }}"
          },
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Workflow"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": "={{ $('Config1').item.json.SHEET_NAME }}",
        "documentId": "={{ $('Config1').item.json.SPREADSHEET_ID }}"
      },
      "typeVersion": 4.5
    },
    {
      "id": "797c78a7-d273-430b-9a36-9b3305a783b4",
      "name": "Sticky: Overview (yellow)",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2480,
        -496
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 456,
        "content": "## Overview \u2013 GitHub n8n Workflow Analyzer\n\n**What this workflow does**  \n- Finds public n8n workflows on GitHub  \n- Analyzes them with AI to add a short description, use case, and difficulty  \n- Saves everything into Google Sheets (+ optional Notion DB) for later review\n\n**Why this is useful**  \n- Saves hours of manually browsing repos and opening JSON files one by one  \n- Gives you a curated \u201cinspiration database\u201d of real n8n workflows  \n- Helps creators spot patterns, AI usage, and ideas worth turning into templates\n\n**High-level flow**  \n1. Schedule trigger starts the run (or execute manually while testing)  \n2. GitHub search finds n8n JSON files  \n3. Code nodes parse workflows and detect AI-related nodes  \n4. LLM summarizes the most interesting ones  \n5. Results are logged to Google Sheets and optionally mirrored into Notion"
      },
      "typeVersion": 1
    },
    {
      "id": "68335719-9bc1-4a17-8704-e8f43747d310",
      "name": "Sticky: Step 1 \u2014 Fetch & Parse",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1696,
        -304
      ],
      "parameters": {
        "width": 672,
        "height": 304,
        "content": "## STEP 1 \u2013 Fetch & Parse Workflows\n\n**What happens here**  \n- `Schedule Trigger` runs this on a cadence (or via manual execute).  \n- `Config1` holds the search query, result limit, and spreadsheet settings.  \n- `GitHub Search1` searches for public n8n JSON files.  \n- `Split Results1` + `Fetch Workflow JSON1` download each file.  \n- `Process Workflows1` parses JSON, counts nodes, and flags AI-powered flows.\n\n**Why this section matters**  \n- Keeps all search settings in one place so you can tweak scope without editing nodes.  \n- Ensures only valid n8n workflows move forward to AI analysis."
      },
      "typeVersion": 1
    },
    {
      "id": "867f6b02-8731-4d0f-a1e9-abb12a38be41",
      "name": "Sticky: Step 2 \u2014 AI Analysis",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -752,
        -304
      ],
      "parameters": {
        "width": 592,
        "height": 352,
        "content": "## STEP 2 \u2013 AI Analysis\n\n**What happens here**  \n- `Aggregate All1` collects all parsed workflows.  \n- `Prepare AI Analysis1` builds a compact prompt from the top N workflows.  \n- `AI Analysis1` (LLM + structured parser) returns JSON with:  \n  - `description` \u2013 one-sentence summary  \n  - `use_case` \u2013 what the workflow is good for  \n  - `difficulty` \u2013 Beginner / Intermediate / Advanced  \n- `Merge AI Results1` combines AI insights back into each workflow record.\n\n**Why this section matters**  \n- Converts raw technical JSON into human-readable insights.  \n- The structured output parser keeps the data clean so Sheets/Notion stay reliable."
      },
      "typeVersion": 1
    },
    {
      "id": "c5a9bf2a-ba46-4c6d-8878-869572c7cb7e",
      "name": "Sticky: Step 3 \u2014 Save & Share",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        144,
        -288
      ],
      "parameters": {
        "width": 752,
        "height": 272,
        "content": "## STEP 3 \u2013 Save & Share\n\n**What happens here**  \n- `Save to Google Sheets` appends or updates rows with the latest analysis.  \n- Each row includes stars, node count, AI flag, difficulty, and links.  \n- `Create a database page` (Notion) can mirror selected workflows into a Notion DB.\n\n**Why this section matters**  \n- Google Sheets acts as your living catalog of interesting n8n workflows.  \n- Optional Notion sync lets you review, tag, and curate workflows for content, docs, or team sharing."
      },
      "typeVersion": 1
    },
    {
      "id": "4dce4b29-cbec-44b4-a18a-0e70f4a9dedc",
      "name": "Sticky: Setup Checklist",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2480,
        16
      ],
      "parameters": {
        "color": 4,
        "width": 592,
        "height": 476,
        "content": "## Setup checklist (3\u20135 minutes)\n\n1\ufe0f\u20e3 **GitHub credentials**  \n- Add `Authorization: Bearer <token>` in both `GitHub Search1` and `Fetch Workflow JSON1`.  \n- Use a personal access token with `repo` and `code` read permissions.\n\n2\ufe0f\u20e3 **OpenAI / LLM**  \n- Connect credentials in `OpenAI Chat Model1` (or swap in another supported model).  \n- Keep `ai_analysis_top` modest (e.g. 10) to control token usage.\n\n3\ufe0f\u20e3 **Google Sheets**  \n- In `Config1`, set `SPREADSHEET_ID` and `SHEET_NAME`.  \n- Make sure the sheet has matching column names (Workflow, Stars, Nodes, etc.).\n\n4\ufe0f\u20e3 **Notion (optional)**  \n- Connect your Notion credential.  \n- Select the database in `Create a database page` to store curated entries.\n\n5\ufe0f\u20e3 **First run**  \n- Start with a small `max_results` (10\u201320) and execute manually to verify everything works before scheduling."
      },
      "typeVersion": 1
    },
    {
      "id": "4112f328-b6f6-4b75-a327-c8a83d1e3a1f",
      "name": "Sticky: Troubleshooting1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2512,
        576
      ],
      "parameters": {
        "color": 5,
        "width": 668,
        "height": 372,
        "content": "## Troubleshooting\n\n- **401 / 403 from GitHub**  \n  \u2192 Check your token, scopes, and `Authorization` header in both GitHub nodes.\n\n- **Empty or \u201cNo workflows found\u201d**  \n  \u2192 Relax the search query in `Config1` or increase `max_results`.\n\n- **LLM / JSON errors**  \n  \u2192 Lower `ai_analysis_top` or shorten the prompt in `Prepare AI Analysis1`.\n\n- **Rows not updating in Sheets**  \n  \u2192 Confirm column names match exactly and that `Workflow` is used as the key.\n\n\ud83d\udcd8 Security tip: keep all tokens in n8n Credentials \u2014 never hardcode keys inside Code nodes or Set nodes."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Config1": {
      "main": [
        [
          {
            "node": "GitHub Search1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Analysis1": {
      "main": [
        [
          {
            "node": "Merge AI Results1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate All1": {
      "main": [
        [
          {
            "node": "Prepare AI Analysis1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GitHub Search1": {
      "main": [
        [
          {
            "node": "Split Results1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Results1": {
      "main": [
        [
          {
            "node": "Fetch Workflow JSON1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Config1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge AI Results1": {
      "main": [
        [
          {
            "node": "Save to Google Sheets",
            "type": "main",
            "index": 0
          },
          {
            "node": "Create a database page",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "AI Analysis1",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Process Workflows1": {
      "main": [
        [
          {
            "node": "Aggregate All1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Workflow JSON1": {
      "main": [
        [
          {
            "node": "Process Workflows1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare AI Analysis1": {
      "main": [
        [
          {
            "node": "AI Analysis1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser1": {
      "ai_outputParser": [
        [
          {
            "node": "AI Analysis1",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    }
  }
}