Github Deal Sourcing Automation for VCs.

We've built an automation for VCs that finds startups before they're famous, using Github and n8n.

Workflow JSON

{
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "months"
            }
          ]
        }
      },
      "id": "95487402-4b92-45a2-92c0-600febe702db",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "const topics = [\n  'devtools',\n  'developer-tools',\n  'ai',\n  'llm',\n  'fintech',\n  'infrastructure',\n  'cli',\n  'open-source'\n];\n\nconst today = new Date();\nconst oneMonthAgo = new Date(today);\noneMonthAgo.setMonth(today.getMonth() - 1);\nconst dateStr = oneMonthAgo.toISOString().split('T')[0];\n\nconst queries = topics.map(topic => ({\n  topic,\n  query: `topic:${topic} stars:200..5000 created:>${dateStr}`,\n  url: `https://api.github.com/search/repositories?q=topic:${encodeURIComponent(topic)}+stars:200..5000+created:>${dateStr}&sort=stars&order=desc&per_page=10`\n}));\n\nreturn queries.map(q => ({ json: q }));"
      },
      "id": "ede7e76f-af81-4e74-9956-7b3e139d6b55",
      "name": "Build GitHub Search Queries",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        224,
        0
      ]
    },
    {
      "parameters": {
        "url": "={{ $json.url }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "response": {
            "response": {}
          }
        }
      },
      "id": "f1fb1f80-dafd-4530-a70f-5c9ec02e902a",
      "name": "GitHub Search API",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        448,
        0
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": "jqHyiflYNgDGE85N",
          "name": "Github"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Flatten all repos from all topic searches\nconst items = $input.all();\nconst seen = new Set();\nconst repos = [];\n\nfor (const item of items) {\n  const results = item.json.items || [];\n  for (const repo of results) {\n    if (!seen.has(repo.id)) {\n      seen.add(repo.id);\n      repos.push({\n        json: {\n          id: repo.id,\n          name: repo.full_name,\n          description: repo.description || 'No description',\n          url: repo.html_url,\n          stars: repo.stargazers_count,\n          forks: repo.forks_count,\n          watchers: repo.watchers_count,\n          language: repo.language || 'Unknown',\n          topics: (repo.topics || []).join(', '),\n          created_at: repo.created_at,\n          updated_at: repo.updated_at,\n          open_issues: repo.open_issues_count,\n          owner: repo.owner?.login,\n          owner_type: repo.owner?.type,\n          readme_url: `https://api.github.com/repos/${repo.full_name}/readme`,\n          commits_url: `https://api.github.com/repos/${repo.full_name}/commits?per_page=1`,\n          contributors_url: `https://api.github.com/repos/${repo.full_name}/contributors?per_page=5`\n        }\n      });\n    }\n  }\n}\n\nreturn repos;"
      },
      "id": "9a75c758-de31-4624-9e0d-ebb5df73b4bd",
      "name": "Flatten & Deduplicate Repos",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        672,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "filter-stars",
              "leftValue": "={{ $json.stars }}",
              "rightValue": 200,
              "operator": {
                "type": "number",
                "operation": "gte"
              }
            },
            {
              "id": "filter-stars-max",
              "leftValue": "={{ $json.stars }}",
              "rightValue": 5000,
              "operator": {
                "type": "number",
                "operation": "lte"
              }
            },
            {
              "id": "filter-forks",
              "leftValue": "={{ $json.forks }}",
              "rightValue": 10,
              "operator": {
                "type": "number",
                "operation": "gte"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "026880ca-0faf-4cf0-ba05-39ac1dfe72bf",
      "name": "Filter: Quality Threshold",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2,
      "position": [
        880,
        0
      ]
    },
    {
      "parameters": {
        "url": "={{ $json.readme_url }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "response": {
            "response": {
              "fullResponse": true,
              "responseFormat": "json"
            }
          }
        }
      },
      "id": "ac378f4b-9a89-49c1-a5e0-762f53427e3c",
      "name": "Fetch README",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1120,
        0
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": "jqHyiflYNgDGE85N",
          "name": "Github"
        }
      },
      "continueOnFail": true
    },
    {
      "parameters": {
        "jsCode": "// Topics to track - customize these for your thesis\nconst topics = [\n  'devtools',\n  'developer-tools',\n  'ai',\n  'llm',\n  'fintech',\n  'infrastructure',\n  'cli',\n  'open-source'\n];\n\nconst today = new Date();\nconst oneYearAgo = new Date(today);\noneYearAgo.setFullYear(today.getFullYear() - 1);\nconst dateStr = oneYearAgo.toISOString().split('T')[0];\n\nconst queries = topics.map(topic => ({\n  topic,\n  query: `topic:${topic} stars:200..5000 created:>${dateStr}`,\n  url: `https://api.github.com/search/repositories?q=topic:${encodeURIComponent(topic)}+stars:200..5000+created:>${dateStr}&sort=stars&order=desc&per_page=10`\n}));\n\nreturn queries.map(q => ({ json: q }));"
      },
      "id": "108da8f5-223b-4452-8f6f-e9b5464b0376",
      "name": "Build GitHub Search Queries1",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        224,
        240
      ]
    },
    {
      "parameters": {
        "jsCode": "const readmeItems = $input.all();\nconst repoItems = $('Filter: Quality Threshold').all();\n\nconst results = [];\n\nfor (let i = 0; i < readmeItems.length; i++) {\n  const readmeResponse = readmeItems[i].json.body;  // <-- added .body here\n  const repo = repoItems[i].json;\n\n  let readmeText = 'README not available';\n  try {\n    if (readmeResponse.content) {\n      readmeText = Buffer.from(readmeResponse.content, 'base64')\n        .toString('utf-8')\n        .slice(0, 2000);\n    }\n  } catch(e) {\n    readmeText = 'README not available';\n  }\n\n  results.push({\n    json: {\n      ...repo,\n      readme_excerpt: readmeText\n    }\n  });\n}\n\nreturn results;"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1312,
        0
      ],
      "id": "cc9bdbe8-aca9-4c9b-8e36-8dfb9b41404f",
      "name": "Merge"
    },
    {
      "parameters": {
        "jsCode": "const items = $input.all();\nconst cards = [];\n\nfor (const item of items) {\n  const r = item.json;\n  \n  const createdDate = new Date(r.created_at).toDateString();\n  const updatedDate = new Date(r.updated_at).toDateString();\n  \n  const topicTags = (r.topics || '').split(', ').map(t => \n    `<span style=\"display:inline-block; background:#f3f4f6; color:#374151; font-size:11px; padding:2px 8px; border-radius:4px; margin:2px 2px 2px 0;\">${t}</span>`\n  ).join('');\n\n  const card = `\n    <tr>\n      <td style=\"padding: 24px 0; border-bottom: 1px solid #e5e7eb;\">\n        <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\">\n          <tr>\n            <td>\n\n              <!-- Repo name -->\n              <h2 style=\"margin: 0 0 6px 0; font-size: 18px; font-family: Arial, sans-serif;\">\n                <a href=\"${r.url}\" style=\"color: #111827; text-decoration: none;\">${r.name}</a>\n              </h2>\n\n              <!-- Description -->\n              <p style=\"margin: 0 0 14px 0; font-size: 14px; color: #6b7280; font-family: Arial, sans-serif; line-height: 1.6;\">\n                ${r.description || 'No description'}\n              </p>\n\n              <!-- Stats row -->\n              <table cellpadding=\"0\" cellspacing=\"0\" style=\"margin-bottom: 14px;\">\n                <tr>\n                  <td style=\"font-size: 13px; color: #374151; font-family: Arial, sans-serif; padding-right: 20px;\">★ ${r.stars?.toLocaleString()} stars</td>\n                  <td style=\"font-size: 13px; color: #374151; font-family: Arial, sans-serif; padding-right: 20px;\">⑂ ${r.forks?.toLocaleString()} forks</td>\n                  <td style=\"font-size: 13px; color: #374151; font-family: Arial, sans-serif; padding-right: 20px;\">👁 ${r.watchers?.toLocaleString()} watchers</td>\n                  <td style=\"font-size: 13px; color: #374151; font-family: Arial, sans-serif; padding-right: 20px;\">⚠ ${r.open_issues} issues</td>\n                  <td style=\"font-size: 13px; color: #374151; font-family: Arial, sans-serif;\">${r.language}</td>\n                </tr>\n              </table>\n\n              <!-- Owner + dates row -->\n              <table cellpadding=\"0\" cellspacing=\"0\" style=\"margin-bottom: 14px;\">\n                <tr>\n                  <td style=\"font-size: 13px; color: #374151; font-family: Arial, sans-serif; padding-right: 20px;\">\n                    👤 <a href=\"https://github.com/${r.owner}\" style=\"color: #374151;\">${r.owner}</a> &nbsp;·&nbsp; ${r.owner_type}\n                  </td>\n                  <td style=\"font-size: 13px; color: #6b7280; font-family: Arial, sans-serif; padding-right: 20px;\">Created: ${createdDate}</td>\n                  <td style=\"font-size: 13px; color: #6b7280; font-family: Arial, sans-serif;\">Updated: ${updatedDate}</td>\n                </tr>\n              </table>\n\n              <!-- Topics -->\n              <div style=\"margin-bottom: 16px;\">\n                ${topicTags}\n              </div>\n\n              <!-- README excerpt -->\n              <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"margin-bottom: 16px;\">\n                <tr>\n                  <td style=\"background: #f9fafb; border-left: 3px solid #111827; padding: 12px 16px; border-radius: 0 6px 6px 0;\">\n                    <p style=\"margin: 0 0 6px 0; font-size: 11px; font-weight: 600; color: #6b7280; text-transform: uppercase; letter-spacing: 0.05em; font-family: Arial, sans-serif;\">README</p>\n                    <p style=\"margin: 0; font-size: 13px; color: #374151; font-family: Arial, sans-serif; line-height: 1.7; white-space: pre-line;\">\n                      ${(r.readme_excerpt || 'Not available').slice(0, 600)}\n                    </p>\n                  </td>\n                </tr>\n              </table>\n\n              <!-- Links row -->\n              <table cellpadding=\"0\" cellspacing=\"0\" style=\"margin-bottom: 16px;\">\n                <tr>\n                  <td style=\"padding-right: 12px;\">\n                    <a href=\"${r.url}\" style=\"font-size: 12px; color: #6b7280; font-family: Arial, sans-serif;\">Repo</a>\n                  </td>\n                  <td style=\"padding-right: 12px;\">\n                    <a href=\"${r.commits_url.replace('?per_page=1', '')}\" style=\"font-size: 12px; color: #6b7280; font-family: Arial, sans-serif;\">Commits</a>\n                  </td>\n                  <td>\n                    <a href=\"${r.contributors_url.replace('?per_page=5', '')}\" style=\"font-size: 12px; color: #6b7280; font-family: Arial, sans-serif;\">Contributors</a>\n                  </td>\n                </tr>\n              </table>\n\n              <!-- CTA -->\n              <a href=\"${r.url}\" style=\"display: inline-block; background: #111827; color: #ffffff; font-size: 13px; font-weight: 600; padding: 10px 20px; border-radius: 6px; text-decoration: none; font-family: Arial, sans-serif;\">\n                View on GitHub →\n              </a>\n\n            </td>\n          </tr>\n        </table>\n      </td>\n    </tr>\n  `;\n  \n  cards.push(card);\n}\n\nconst html = `\n<!DOCTYPE html>\n<html>\n<head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\"></head>\n<body style=\"margin: 0; padding: 0; background: #f3f4f6;\">\n\n  <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"background: #f3f4f6; padding: 32px 0;\">\n    <tr>\n      <td align=\"center\">\n        <table width=\"640\" cellpadding=\"0\" cellspacing=\"0\" style=\"background: #ffffff; border-radius: 12px; overflow: hidden;\">\n          \n          <!-- Header -->\n          <tr>\n            <td style=\"background: #111827; padding: 28px 32px;\">\n              <h1 style=\"margin: 0 0 6px 0; color: #ffffff; font-size: 22px; font-family: Arial, sans-serif;\">\n                GitHub Deal Sourcing Digest\n              </h1>\n              <p style=\"margin: 0; color: #9ca3af; font-size: 14px; font-family: Arial, sans-serif;\">\n                ${new Date().toDateString()} &nbsp;·&nbsp; ${items.length} repositories\n              </p>\n            </td>\n          </tr>\n\n          <!-- Cards -->\n          <tr>\n            <td style=\"padding: 0 32px;\">\n              <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\">\n                ${cards.join('')}\n              </table>\n            </td>\n          </tr>\n\n          <!-- Footer -->\n          <tr>\n            <td style=\"padding: 24px 32px; background: #f9fafb; border-top: 1px solid #e5e7eb;\">\n              <p style=\"margin: 0; font-size: 12px; color: #9ca3af; font-family: Arial, sans-serif;\">\n                Generated automatically by your GitHub deal sourcing workflow\n              </p>\n            </td>\n          </tr>\n\n        </table>\n      </td>\n    </tr>\n  </table>\n\n</body>\n</html>\n`;\n\nreturn [{ json: { html } }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1520,
        0
      ],
      "id": "8c59dc59-2085-41fb-abef-bc2a9d67fe53",
      "name": "Code in JavaScript"
    },
    {
      "parameters": {
        "sendTo": "daksh@neurolooplab.com",
        "subject": "GitHub Upcoming Repos For This Month",
        "message": "={{ $json.html }}",
        "options": {}
      },
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.2,
      "position": [
        1728,
        0
      ],
      "id": "11c5a806-0c2f-4bc1-b1d5-5f9db6e6ce50",
      "name": "Send a message",
      "webhookId": "2622bb19-3ac6-48af-aa1e-4a5916efb0ec",
      "credentials": {
        "gmailOAuth2": {
          "id": "MbrD9BQtwtesvYq8",
          "name": "Gmail account"
        }
      }
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Build GitHub Search Queries",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build GitHub Search Queries": {
      "main": [
        [
          {
            "node": "GitHub Search API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GitHub Search API": {
      "main": [
        [
          {
            "node": "Flatten & Deduplicate Repos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Flatten & Deduplicate Repos": {
      "main": [
        [
          {
            "node": "Filter: Quality Threshold",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter: Quality Threshold": {
      "main": [
        [
          {
            "node": "Fetch README",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch README": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "meta": {
    "instanceId": "68e38a4d16f6bb0fc4dc0d12c182b0537e5cd43d16c8c06d03fb68dbc38c8ff4"
  }
}