
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> · ${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()} · ${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" } }