{
  "name": "GitPost - Auto-post GitHub code to LinkedIn",
  "tags": [],
  "nodes": [
    {
      "id": "487d92ae-724a-4828-8645-2537aa3f13e9",
      "name": "Overview Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -550,
        -150
      ],
      "parameters": {
        "width": 450,
        "height": 560,
        "content": "## GitPost: Automate LinkedIn Code Posts\n\n### How it works\n\n1. A GitHub webhook triggers the workflow whenever code is pushed to the repository.\n2. The workflow lists the repository files and retrieves the content of each one.\n3. Each file is decoded from Base64 into plain text and merged into a single block.\n4. An AI agent analyses the code and explains the web development concept behind it.\n5. A second AI agent drafts a LinkedIn post under 2500 characters from that explanation.\n6. The finished post is published directly to your LinkedIn account.\n\n### Setup steps\n\n- [ ] Add your GitHub credential and connect it to the two file nodes.\n- [ ] Add your Google Gemini (PaLM) API credential to both model nodes.\n- [ ] Add your LinkedIn OAuth2 credential and select your own profile in the publish node.\n- [ ] Copy the production webhook URL into a GitHub repository webhook set to the \"push\" event.\n\n### Customization\n\nAdjust the system prompts in the two AI agents to match your tone or target a different length, or swap Gemini for another chat model."
      },
      "typeVersion": 1
    },
    {
      "id": "9ac386ce-59ae-46e4-b68b-8d5d0661b77f",
      "name": "Group Sticky Note 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -50,
        -150
      ],
      "parameters": {
        "color": 7,
        "width": 650,
        "height": 450,
        "content": "## Fetch GitHub repository data\n\nReceives the push event, lists the repository files and downloads their content via the GitHub API."
      },
      "typeVersion": 1
    },
    {
      "id": "b66700f6-6735-4e21-93a2-5cde172ecc17",
      "name": "Group Sticky Note 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        650,
        -150
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 450,
        "content": "## Process and merge code\n\nDecodes each file from Base64 and merges everything into one text block for the AI."
      },
      "typeVersion": 1
    },
    {
      "id": "ef54e9ee-68ae-47b4-b99b-a7e18c94e551",
      "name": "Group Sticky Note 3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1100,
        -150
      ],
      "parameters": {
        "color": 7,
        "width": 650,
        "height": 450,
        "content": "## AI code analysis and drafting\n\nOne agent explains the web concept behind the code; a second turns it into a LinkedIn-ready post."
      },
      "typeVersion": 1
    },
    {
      "id": "115cbed1-cebf-4c47-940c-5d29dd9dcc40",
      "name": "Group Sticky Note 4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1800,
        -150
      ],
      "parameters": {
        "color": 7,
        "width": 300,
        "height": 450,
        "content": "## Publish LinkedIn post\n\nPublishes the generated post to your LinkedIn profile."
      },
      "typeVersion": 1
    },
    {
      "id": "c18a58d1-f9eb-491f-85f4-3862d4a8e4e9",
      "name": "When Push Event Occurs",
      "type": "n8n-nodes-base.webhook",
      "position": [
        0,
        0
      ],
      "parameters": {
        "path": "627523b7-99fe-4999-88cd-7605c47db00b",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "a5fd0d6c-305e-49c1-a5b6-fa4887712ea3",
      "name": "List Repository Files",
      "type": "n8n-nodes-base.github",
      "position": [
        200,
        0
      ],
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $json.body.repository.owner.login }}"
        },
        "resource": "file",
        "operation": "list",
        "repository": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $json.body.repository.name }}"
        }
      },
      "credentials": {
        "githubApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "0e06e956-6454-4193-ad65-577c1f5329ff",
      "name": "Fetch File Content",
      "type": "n8n-nodes-base.github",
      "position": [
        400,
        0
      ],
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('When Push Event Occurs').item.json.body.repository.owner.login }}"
        },
        "filePath": "={{ $('List Repository Files').item.json.path }}",
        "resource": "file",
        "operation": "get",
        "repository": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('When Push Event Occurs').item.json.body.repository.name }}"
        },
        "asBinaryProperty": false,
        "additionalParameters": {}
      },
      "credentials": {
        "githubApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "a8c17cdf-2145-48fd-b83c-a08e854f2992",
      "name": "Decode Base64 Content",
      "type": "n8n-nodes-base.code",
      "position": [
        700,
        0
      ],
      "parameters": {
        "jsCode": "return $input.all().map(item => {\n  if (item.json.content) {\n    item.json.text = global.Buffer.from(item.json.content, 'base64').toString('utf8');\n  } else {\n    item.json.text = 'No content found';\n  }\n  return item;\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "184a55ec-39f9-4c41-99db-63ae5bc61fe5",
      "name": "Merge Code Snippets",
      "type": "n8n-nodes-base.code",
      "position": [
        850,
        0
      ],
      "parameters": {
        "jsCode": "// Access all input items (each with json.text)\nconst allTexts = $input.all().map(item => item.json.text);\n\n// Combine them into one string, separated by line breaks\nconst combinedText = allTexts.join('\\n\\n');\n\n// Return a single item with combined text suitable for AI prompt\nreturn [\n  {\n    json: {\n      combinedText: combinedText,\n    },\n  },\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "266cc158-bc66-45a6-b8d3-3c24fbf5f2e9",
      "name": "Analyze Code Context",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1150,
        0
      ],
      "parameters": {
        "text": "={{$json.combinedText}}",
        "options": {
          "systemMessage": "=You are an expert AI assistant specialized in web technologies. When the user provides a code snippet or script:\n\nAnalyze the code to understand what functionality or feature it implements and what problem it addresses.\n\nIdentify the broader web development topic or concept the code relates to (e.g., responsive design, user authentication, API integration, frontend frameworks).\n\nWrite a clear, insightful, and engaging post about that web topic, its importance, use cases, and best practices.\n\nFocus on explaining the real-world application or concept behind the code rather than detailing the code itself.\n\nAvoid step-by-step code explanations unless specifically requested.\n\nFormat the post for easy reading with headings, bullet points, and examples where relevant.\n\nAlways aim to educate and inform readers about the web development context and why the code matters in practice."
        },
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "d160120e-7a4c-4b76-9f2e-a10a04885490",
      "name": "Gemini Analysis Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1150,
        200
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "23ea917b-1a97-497d-b88c-72879d1b148c",
      "name": "Draft LinkedIn Post",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1450,
        0
      ],
      "parameters": {
        "text": "={{ $json.output }}",
        "options": {
          "systemMessage": "=You are an expert AI assistant tasked with converting code descriptions into LinkedIn posts. Generate a post that is no longer than 2500 characters, including spaces and punctuation.\n\nInstructions:\n\nWrite an engaging, clear, and professional LinkedIn post that summarizes the code\u2019s purpose and value.\n\nUse LinkedIn\u2019s tone: impactful, concise, and reader-friendly.\n\nUse paragraphs and line breaks to enhance readability within the character limit.\n\nThe output must never exceed 2500 characters.\n\nIf the content is shorter than 2500 characters, that is acceptable.\n\nIf the content exceeds 2500 characters, immediately shorten and revise the post until it fits within the limit without losing crucial meaning.\n\nDo NOT mention character count or generate any text outside the LinkedIn post content.\n\nVerify and ensure the final output is at or below 2500 characters before returning it.\n\nOutput only the LinkedIn post text\u2014no explanations, disclaimers, or extra notes."
        },
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "44c0bd31-5fb3-49cc-9f4c-3e998eeb79b8",
      "name": "Gemini Drafting Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1450,
        200
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8b6d3433-bb8d-4aa2-8331-808875354e65",
      "name": "Publish to LinkedIn",
      "type": "n8n-nodes-base.linkedIn",
      "position": [
        1850,
        0
      ],
      "parameters": {
        "text": "={{ $json.output }}",
        "person": "",
        "additionalFields": {}
      },
      "credentials": {
        "linkedInOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "Fetch File Content": {
      "main": [
        [
          {
            "node": "Decode Base64 Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Draft LinkedIn Post": {
      "main": [
        [
          {
            "node": "Publish to LinkedIn",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Code Snippets": {
      "main": [
        [
          {
            "node": "Analyze Code Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze Code Context": {
      "main": [
        [
          {
            "node": "Draft LinkedIn Post",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Decode Base64 Content": {
      "main": [
        [
          {
            "node": "Merge Code Snippets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Analysis Model": {
      "ai_languageModel": [
        [
          {
            "node": "Analyze Code Context",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Drafting Model": {
      "ai_languageModel": [
        [
          {
            "node": "Draft LinkedIn Post",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "List Repository Files": {
      "main": [
        [
          {
            "node": "Fetch File Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Push Event Occurs": {
      "main": [
        [
          {
            "node": "List Repository Files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}