N
n8n Store
Workflow Market
Sync Android drawable assets from Figma to GitHub

Sync Android drawable assets from Figma to GitHub

by weblineindiaβ€’0 views

Description

Categories

πŸ”§ EngineeringπŸ€– AI & Machine Learning

Nodes Used

n8n-nodes-base.ifn8n-nodes-base.coden8n-nodes-base.coden8n-nodes-base.coden8n-nodes-base.coden8n-nodes-base.mergen8n-nodes-base.mergen8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.httpRequest
PriceGratis
Views0
Last Updated11/28/2025
workflow.json
{
  "id": "Wyw2TmhKVujBRhkZ",
  "meta": {
    "instanceId": "14e4c77104722ab186539dfea5182e419aecc83d85963fe13f6de862c875ebfa",
    "templateCredsSetupCompleted": true
  },
  "name": "Sync Android drawable assets from Figma to GitHub",
  "tags": [],
  "nodes": [
    {
      "id": "b9ed0516-1d34-499b-85ba-7e304129b116",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        660,
        -280
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineAll"
      },
      "typeVersion": 3.2
    },
    {
      "id": "8c08ddf1-e081-425c-bdb1-b46e28f48ebf",
      "name": "Download Each Image from the Figma Export URL",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1320,
        -355
      ],
      "parameters": {
        "url": "={{ $json[\"url\"] }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "139ce28e-570d-443d-a347-bef3089e6e1e",
      "name": "get figma Url",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        880,
        -355
      ],
      "parameters": {
        "url": "=https://api.figma.com/v1/images/FIGMA_PROJECT_ID?ids={{$json[\"id\"]}}&format=png&scale={{$json[\"scale\"]}}",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Figma-Token",
              "value": "FIGMA_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "383243fc-1bd0-4968-af5e-fb6ba09e80f9",
      "name": "Merge1",
      "type": "n8n-nodes-base.merge",
      "position": [
        1560,
        -220
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2,
      "alwaysOutputData": true
    },
    {
      "id": "087cce4c-2102-48f8-bee1-69468fceeec9",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        1840,
        -220
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4f1fd504-3119-4fe0-bb8f-6af824494d41",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{$itemIndex}}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "258614f5-1704-4972-bbd4-e0bf8f4126d3",
      "name": "Get Figma Export URL",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        220,
        -280
      ],
      "parameters": {
        "url": "https://api.figma.com/v1/files/FIGMA_PROJECT_ID?ids=2-20347",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Figma-Token",
              "value": "FIGMA_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "417bd211-81b9-4f1c-9cdf-15b01a2d39ab",
      "name": "Execute workflow",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        0,
        -280
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "03ff18dd-880b-4930-9d61-6e16d5e08078",
      "name": "Find Icons & Buttons",
      "type": "n8n-nodes-base.code",
      "position": [
        440,
        -380
      ],
      "parameters": {
        "jsCode": "function findIconsAndButtons(nodes, parentChain = []) {\n  let matches = [];\n\n  for (const node of nodes) {\n    const fullPath = [...parentChain, node.name].join('/');\n\n    // If current node is a match\n    if (typeof node.name === 'string' && /icon|button/i.test(node.name)) {\n      matches.push({\n        id: node.id,\n        name: node.name,\n        type: node.type,\n        fullPath: fullPath,\n        exportSettings: node.exportSettings || null,\n      });\n    }\n\n    // Recurse into children if they exist\n    if (node.children && Array.isArray(node.children)) {\n      matches.push(...findIconsAndButtons(node.children, [...parentChain, node.name]));\n    }\n  }\n\n  return matches;\n}\n\n// Start from the root document children\nconst rootNode = items[0].json.document;\nconst canvas = rootNode.children.find(child => child.type === 'CANVAS');\nconst frame = canvas.children.find(child => child.type === 'FRAME' && /forgot password/i.test(child.name));\n\nif (!frame || !frame.children) {\n  return [];\n}\n\n// Recursively collect icons and buttons\nconst results = findIconsAndButtons(frame.children);\n\nreturn results.map(node => ({\n  json: node\n}));"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "6ea0e89f-aeef-46b0-b26b-22dcace571de",
      "name": "Predefine drawable folders",
      "type": "n8n-nodes-base.code",
      "position": [
        440,
        -180
      ],
      "parameters": {
        "jsCode": "return [\n  { json: { folder: 'drawable-mdpi', scale: '1' } },\n  { json: { folder: 'drawable-hdpi', scale: '1.5' } },\n  { json: { folder: 'drawable-xhdpi', scale: '2' } },\n  { json: { folder: 'drawable-xxhdpi', scale: '3' } }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "1ac6faec-8395-4f4e-bea1-82344b1a4fd8",
      "name": "Filter nullable url of nodes",
      "type": "n8n-nodes-base.code",
      "position": [
        1100,
        -360
      ],
      "parameters": {
        "jsCode": "// Filter valid images and map to { nodeId, url }\nconst results = [];\n\nfor (const item of items) {\n  const images = item.json.images;\n\n  for (const nodeId in images) {\n    const url = images[nodeId];\n\n    if (url) {\n      results.push({\n        json: {\n          nodeId,\n          url\n        }\n      });\n    }\n  }\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "053297b8-705d-42b9-9531-16bf91629f93",
      "name": "Edit File names",
      "type": "n8n-nodes-base.code",
      "position": [
        1700,
        -360
      ],
      "parameters": {
        "jsCode": "return items.map(item => {\n  const name = item.json.name || \"asset\";\n  const folder = item.json.folder || \"drawable-mdpi\";\n  \n  item.json.path = `app/src/main/res/${folder}/${name.toLowerCase().replace(/[^a-z0-9]/g, \"_\")}.png`;\n  item.json.commitMessage = `Add asset: ${name}.png to ${folder}`;\n  item.json.branch = \"add-assets-from-figma\";\n  item.json.repoOwner = \"REPO_OWNER\";\n  item.json.repoName = \"REPO_NAME\";\n\n  return item;\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "1678d236-4bab-4b39-a553-cd67f9cffe1a",
      "name": "Prepare Pull Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2040,
        -220
      ],
      "parameters": {
        "url": "https://api.github.com/repos/REPO_OWNER/REPO_NAME/pulls",
        "method": "POST",
        "options": {},
        "jsonBody": "{\n  \"title\": \"Add drawable assets from Figma\",\n  \"head\": \"add-assets-from-figma\",\n  \"base\": \"main\",\n  \"body\": \"This PR contains Android drawable assets exported from Figma in all resolutions.\"\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer GITHUB_TOKEN"
            },
            {
              "name": "Accept",
              "value": "application/vnd.github+json"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "4ccbac73-ffba-45a7-a6fe-a77b8021480f",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        -460
      ],
      "parameters": {
        "width": 2280,
        "height": 440,
        "content": "\nSync Android drawable assets from Figma to GitHub via PR (multi‑density PNG)"
      },
      "typeVersion": 1
    },
    {
      "id": "09523583-b2db-40d7-97df-798608513226",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        60
      ],
      "parameters": {
        "width": 2280,
        "height": 760,
        "content": "#\nNode Name\nDescription\n\n1 πŸ” Execute Flow\nTrigger node to start the automation manually or via webhook/schedule.\n\n2 🎨 Get Figma Export URLs\nFetches Figma export URLs (PNG/SVG) for all components from a specified file or parent node.\n\n3 🧠 Find Icons & Buttons\nFilters nodes by name or type to extract only relevant UI components like β€œIcon” and β€œButton”.\n\n4 πŸ“‚ Predefine Drawable Folders\nCreates static Android drawable folder list (mdpi, hdpi, etc.) as JSON for merging later.\n\n5 πŸ”— Merge Metadata & Folders\nMerges filtered Figma nodes with predefined Android folder structure for each resolution.\n\n6 🌐 Get Figma Image URLs\nCalls Figma export API with IDs from merged metadata to retrieve actual exportable image URLs.\n\n7 🚫 Filter Empty Image URLs\nRemoves any nodes where export URL is missing/null to avoid failed downloads or commits.\n\n8 πŸ“₯ Download Figma Images\nDownloads binary image files from export URLs for all filtered nodes across densities.\n\n9 🧬 Merge Metadata & Images\nMerges previously prepared metadata (drawable folder, file name) with actual downloaded image files.\n\n10 πŸ“ Edit File Names\nRenames files based on naming conventions (e.g., lowercase, no spaces, append _icon if needed).\n\n11 πŸ”„ If: Pull Request Created?\nPrevents duplicate pull requests by checking if one already exists for the same branch or purpose.\n\n12 πŸš€ Prepare Pull Request\nCommits all images to GitHub in proper folders and creates a clean Pull Request into the main branch.\n\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "da71a6f8-28a7-467f-998e-a4fef0700dc8",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Prepare Pull Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "get figma Url",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge1",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge1": {
      "main": [
        [
          {
            "node": "Edit File names",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get figma Url": {
      "main": [
        [
          {
            "node": "Filter nullable url of nodes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit File names": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute workflow": {
      "main": [
        [
          {
            "node": "Get Figma Export URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Icons & Buttons": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Figma Export URL": {
      "main": [
        [
          {
            "node": "Find Icons & Buttons",
            "type": "main",
            "index": 0
          },
          {
            "node": "Predefine drawable folders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Predefine drawable folders": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Filter nullable url of nodes": {
      "main": [
        [
          {
            "node": "Download Each Image from the Figma Export URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Each Image from the Figma Export URL": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

η›Έε…³ε·₯作桁