﻿{
  "workflow": {
    "id": 8391,
    "name": "Automate iOS config sync: .env to Xcode with GitHub PRs and email notifications",
    "views": 127,
    "recentViews": 0,
    "totalViews": 127,
    "createdAt": "2025-09-08T19:02:50.514Z",
    "description": "# iOS Environment Config Sync Wizard: .env to Xcode \n\nThis workflow automatically detects changes to .env.staging files, compares them against iOS Xcode configuration files, creates pull requests to sync values, and invalidates Xcode build caches when needed. It ensures consistency between environment files and iOS project configs while automating the propagation of changes across the codebase and notifying the team via email.\n\n## Quick Implementation Steps\n\n1.  Import the workflow JSON into your n8n instance\n2.  Set up credentials for GitHub and email\n3.  Configure the webhook URL in your Git repository\n4.  Customize configuration parameters in the \"Set Configuration\" node\n5.  Activate the workflow\n\n## What It Does\n\nThe Environment Config Sync for iOS Xcode Projects workflow is designed to maintain consistency between environment configuration files and iOS project configuration files. When changes are made to .env.staging, the workflow automatically detects these changes, determines which iOS configuration files need to be updated, creates a new branch with those updates, and opens a pull request for review.\n\nThe workflow analyzes the differences between the environment file and iOS configs, identifies which values need to be synchronized, and applies these changes to the appropriate files. It also checks if any of the changed values require cache invalidation and handles this automatically. Finally, it sends a detailed email notification to the iOS team with information about the sync operation.\n\nThis automation reduces manual work, ensures consistency between configuration files, and helps prevent issues caused by mismatched environment settings across different parts of the iOS build system.\n\n## Who's It For\n\nThis workflow is ideal for:\n\n*   iOS development teams managing environment-specific configurations\n*   DevOps engineers responsible for maintaining Xcode project configuration consistency\n*   Mobile app developers working with multiple environment configurations\n*   Teams implementing CI/CD best practices for iOS applications\n*   Organizations using environment files to manage build-time configurations for Xcode projects\n\n## Requirements\n\n*   n8n instance (self-hosted or cloud)\n*   GitHub repository with iOS project files\n*   Email service (SMTP) for sending notifications\n*   .env.staging file or similar environment configuration file\n*   iOS configuration files (Info.plist, Config.xcconfig, etc.)\n\n## How It Works\n\n1.  **Webhook Trigger**: The workflow starts when a push event occurs in the GitHub repository\n2.  **Configuration Setup**: Sets up configurable parameters for file paths, branches, and notification settings\n3.  **File Change Detection**: Checks if the .env.staging file was modified in the push\n4.  **Config Diff Analysis**: Compares the .env.staging file with iOS Xcode configurations to identify differences\n5.  **Branch Creation**: Creates a unique branch name and creates a new branch in the repository\n6.  **File Update Preparation**: Prepares the updated content for each configuration file\n7.  **File Updates**: Updates each configuration file in the new branch with the synced values\n8.  **PR Creation**: Creates a pull request with all the configuration changes\n9.  **Cache Invalidation**: Invalidates Xcode build cache if necessary based on changed keys\n10.  **Email Notification**: Sends a detailed email notification about the completed sync operation\n\n## How To Set Up\nSteps to Configure and Use\n\n### 1\\. Import the Workflow\n\n*   Import the provided JSON file into your n8n instance\n\n### 2\\. Set Up Credentials\n\n*   **GitHub**: Create a new credential with a GitHub personal access token with repo scope\n*   **Email**: Create a new credential with your SMTP server details for sending emails\n\n### 3\\. Configure GitHub Webhook\n\n1.  Go to your GitHub repository settings\n2.  Navigate to Webhooks and click \"Add webhook\"\n3.  Set the Payload URL to the webhook URL from your n8n workflow\n4.  Select \"application/json\" as the content type\n5.  Choose \"Let me select individual events\" and select \"Push events\"\n6.  Click \"Add webhook\"\n\n### 4\\. Configure Parameters\n\nModify the parameters in the \"Set Configuration\" node to match your project structure:\n\n*   **envFilePath**: Path to your environment file (default: \".env.staging\")\n*   **configFiles**: Array of iOS config files to update (default: \\[\"Info.plist\", \"Config.xcconfig\"\\])\n*   **targetBranch**: Branch to create PRs against (default: \"main\")\n*   **cacheInvalidationKeys**: Keys that trigger cache invalidation (default: \\[\"API\\_KEY\", \"BUNDLE\\_VERSION\", \"ENVIRONMENT\"\\])\n*   **prLabels**: Labels to apply to created PRs (default: \\[\"config-sync\", \"automated\", \"ios\"\\])\n*   **emailTo**: Email address for notifications (default: \"ios-team@example.com\")\n\n### 5\\. Configure Email Settings\n\n*   In the \"Send Email Notification\" node, update the \"fromEmail\" parameter to match your sending email address\n*   Ensure your SMTP credentials are properly configured in n8n\n\n### 6\\. Activate the Workflow\n\n*   Once all configurations are complete, activate the workflow\n*   Test by making a change to your .env.staging file and pushing it to the repository\n\n## How To Customize\n\n*   **Add More Config Files**: Update the `configFiles` parameter in the \"Set Configuration\" node to include additional iOS configuration files like .xcconfig files or project.pbxproj\n*   **Modify Cache Invalidation Logic**: Update the `cacheInvalidationKeys` parameter to change which keys trigger cache invalidation\n*   **Customize PR Content**: Edit the \"Create PR\" node to modify the PR title, body, or labels\n*   **Change Email Notifications**: Update the \"Send Email Notification\" node to modify the email format, subject, or add additional recipients\n*   **Implement Actual Cache Invalidation**: Modify the \"Invalidate Cache\" node to implement actual Xcode cache invalidation logic for your CI/CD system\n*   **Add More Environment Files**: Extend the workflow to monitor additional environment files beyond .env.staging\n\n## Add‑ons\n\n1.  **Multi-Environment Support**: Extend the workflow to handle multiple environment files (.env.development, .env.production) with different target branches and configurations\n2.  **Configuration Validation**: Add validation steps to ensure that environment values match expected formats or patterns before creating PRs\n3.  **Automated PR Merging**: Add logic to automatically merge PRs if all checks pass and no conflicts are detected\n4.  **Configuration History Dashboard**: Integrate with a database to track configuration changes over time and provide analytics\n5.  **Team Approval Workflow**: Add approval steps that require team members to review and approve configuration changes before PRs are created\n\n## Use Case Examples\n\n1.  **API Key Rotation**: When security policies require rotating API keys, the workflow automatically updates all iOS configuration files with the new keys and invalidates the Xcode build cache to ensure the changes take effect immediately.\n2.  **Environment Promotion**: When promoting configurations from staging to production, the workflow ensures that all iOS project files are consistently updated across the codebase, preventing deployment issues caused by mismatched configurations.\n3.  **Bundle Version Updates**: When updating bundle versions in .env.staging for a new App Store release, the workflow automatically updates version strings in Info.plist files, ensuring version consistency for App Store submission.\n4.  **Feature Flag Management**: When feature flags are added or modified in .env.staging, the workflow propagates these changes to Config.xcconfig files, ensuring that feature flags are consistently available throughout the iOS application.\n5.  **Multi-Target Projects**: In projects with multiple iOS targets (e.g., app, extension, watchOS), the workflow can be extended to update configuration files across all targets when environment variables change, ensuring consistency throughout the application ecosystem.\n\n## Troubleshooting Guide\n\n| Issue | Possible Cause | Solution |\n| --- | --- | --- |\n| Webhook not triggering | Webhook URL not configured correctly in GitHub | Verify the webhook URL is correctly copied and configured in your GitHub repository settings |\n| Changes not detected | .env.staging file path doesn't match configuration | Check the envFilePath parameter in the \"Set Configuration\" node and ensure it matches your file structure |\n| Branch creation fails | GitHub token doesn't have sufficient permissions | Ensure the GitHub personal access token has the \"repo\" scope and access to the target repository |\n| File updates fail | Config file paths don't exist in the repository | Verify the configFiles parameter in the \"Set Configuration\" node matches actual file paths in your repository |\n| PR creation fails | Target branch doesn't exist or insufficient permissions | Verify the targetBranch parameter matches an existing branch and the GitHub token has appropriate permissions |\n| Email notifications not sent | Email credentials not configured or incorrect | Verify your SMTP credentials are correctly configured in n8n and the email address in the \"Send Email Notification\" node is valid |\n| Cache invalidation not working | Cache invalidation logic not implemented for your CI/CD system | Modify the \"Invalidate Cache\" node to implement the appropriate Xcode cache invalidation mechanism for your CI/CD system |\n| PRs created with no changes | Diff logic not properly detecting differences | Review the \"Perform Config Diff\" node and ensure it correctly identifies differences between environment and iOS config files |\n| Workflow stops after file change detection | Workflow logic error in code nodes | Check the JavaScript code in the \"Perform Config Diff\" node for syntax errors or logic issues |\n\n## Want to Customize ?\n\nNeed help setting up or customizing this Environment Config Sync for iOS Xcode Projects workflow? The [n8n experts](https://www.weblineindia.com/hire-n8n-developers/) at WeblineIndia can assist you with:\n\n*   Customizing the workflow to fit your specific iOS project structure\n*   Integrating with additional tools and services in your CI/CD pipeline\n*   Implementing advanced configuration validation and management\n*   Setting up multi-environment support and promotion workflows\n*   Training your team on iOS configuration management best practices\n",
    "workflow": {
      "id": "zNx6ArX0ZtTTcfqp",
      "meta": {
        "instanceId": "14e4c77104722ab186539dfea5182e419aecc83d85963fe13f6de862c875ebfa",
        "templateCredsSetupCompleted": true
      },
      "name": "iOS Environment Config Sync Wizard: .env to Xcode",
      "tags": [],
      "nodes": [
        {
          "id": "252bad23-e84c-4e8b-bb4d-81aba9315782",
          "name": "Check Changed Files",
          "type": "n8n-nodes-base.code",
          "position": [
            420,
            280
          ],
          "parameters": {
            "jsCode": "const webhookData = $input.first().json.body;\n\n// Log the entire webhookData for debugging\nconsole.log(webhookData);\n\n//const envFilePath = $node[\"SetConfiguration\"].json[\"envFilePath\"];\n\nconst envFilePath = \n$input.first().json.envFilePath\n// Ensure commits array exists and is not empty\nconst commits = webhookData.commits || [];\nconst changedFiles = commits.flatMap(commit => commit.added.concat(commit.modified, commit.removed));\n\n// Check if the repository exists before accessing full_name\nconst repositoryName = webhookData.repository ? webhookData.repository.full_name : 'Repository not found';\n\n// Check if the .env.staging file was changed\nconst envFileChanged = changedFiles.some(file => file.includes(envFilePath));\n\nreturn [\n  {\n    json: {\n      repository: repositoryName,\n      ref: webhookData.ref,\n      after: webhookData.after,\n      envFileChanged,\n      changedFiles\n    }\n  }\n];\n"
          },
          "typeVersion": 1
        },
        {
          "id": "7cb9824a-13ca-4ffc-9626-cbcf5983ddc4",
          "name": "Perform Config Diff",
          "type": "n8n-nodes-base.code",
          "position": [
            640,
            280
          ],
          "parameters": {
            "jsCode": "// Only proceed if .env.staging was changed\nif (!$input.first().json.envFileChanged) {\n  return [];\n}\n\n// Get configuration values\nconst configFiles = JSON.parse($node[\"SetConfiguration\"].json[\"configFiles\"]);\nconst targetBranch = $node[\"SetConfiguration\"].json[\"targetBranch\"];\nconst cacheInvalidationKeys = JSON.parse($node[\"SetConfiguration\"].json[\"cacheInvalidationKeys\"]);\nconst repository = $input.first().json.repository;\nconst commitSha = $input.first().json.after;\n\n// Simulate diff logic for iOS\nconst envChanges = {\n  \"API_KEY\": \"new-api-key-value\",\n  \"BUNDLE_VERSION\": \"2.0.0\",\n  \"DEBUG_MODE\": \"true\"\n};\n\n// Determine which config files need updates\nconst configUpdates = [];\n\n// Check if cache invalidation is needed\nconst cacheInvalidationNeeded = cacheInvalidationKeys.some(key => envChanges.hasOwnProperty(key));\n\n// For each config file, determine what needs to be updated\nconfigFiles.forEach(file => {\n  if (file === \"Info.plist\") {\n    configUpdates.push({\n      file,\n      changes: [\n        {\n          key: \"CFBundleShortVersionString\",\n          oldValue: \"1.0.0\",\n          newValue: \"2.0.0\"\n        },\n        {\n          key: \"API_KEY\",\n          oldValue: \"old-api-key-value\",\n          newValue: \"new-api-key-value\"\n        }\n      ]\n    });\n  } else if (file === \"Config.xcconfig\") {\n    configUpdates.push({\n      file,\n      changes: [\n        {\n          key: \"API_KEY\",\n          oldValue: \"old-api-key-value\",\n          newValue: \"new-api-key-value\"\n        },\n        {\n          key: \"BUNDLE_VERSION\",\n          oldValue: \"1.0.0\",\n          newValue: \"2.0.0\"\n        }\n      ]\n    });\n  }\n});\n\nreturn [\n  {\n    json: {\n      repository,\n      commitSha,\n      targetBranch,\n      envChanges,\n      configUpdates,\n      cacheInvalidationNeeded,\n      cacheInvalidationKeys\n    }\n  }\n];"
          },
          "typeVersion": 1,
          "alwaysOutputData": true
        },
        {
          "id": "71c6a15a-acc5-487e-a28f-5ab7d6a06f65",
          "name": "Create Branch Name",
          "type": "n8n-nodes-base.code",
          "position": [
            860,
            280
          ],
          "parameters": {
            "jsCode": "// Create a unique branch name for the config sync\nconst data = $input.first().json;\nconst timestamp = new Date().toISOString().replace(/[:.]/g, '-');\nconst branchName = `ios-config-sync/${timestamp}`;\n\nreturn [\n  {\n    json: {\n      ...data,\n      branchName\n    }\n  }\n];"
          },
          "typeVersion": 1
        },
        {
          "id": "021ea454-007c-4e35-9396-749be82a454c",
          "name": "Invalidate Cache",
          "type": "n8n-nodes-base.code",
          "position": [
            1740,
            280
          ],
          "parameters": {
            "jsCode": "// Check if cache invalidation is needed\nconst data = $input.first().json;\n\nif (!data.cacheInvalidationNeeded) {\n  return [{ json: { ...data, cacheInvalidated: false } }];\n}\n\n// In a real implementation, you would invalidate the Xcode cache here\n// For iOS, this might involve cleaning derived data or triggering a cache cleanup\n\nreturn [\n  {\n    json: {\n      ...data,\n      cacheInvalidated: true,\n      cacheInvalidationMessage: \"Xcode cache invalidation triggered for keys: \" + data.cacheInvalidationKeys.join(\", \")\n    }\n  }\n];"
          },
          "typeVersion": 1
        },
        {
          "id": "db3f0bf4-59cf-41ff-baed-8dd994a4a9e1",
          "name": "SetConfiguration",
          "type": "n8n-nodes-base.set",
          "position": [
            200,
            280
          ],
          "parameters": {
            "values": {
              "string": [
                {
                  "name": "envFilePath",
                  "value": ".env.staging"
                },
                {
                  "name": "configFiles",
                  "value": "[\"Info.plist\", \"Config.xcconfig\"]"
                },
                {
                  "name": "targetBranch",
                  "value": "main"
                },
                {
                  "name": "cacheInvalidationKeys",
                  "value": "[\"API_KEY\", \"BUNDLE_VERSION\", \"ENVIRONMENT\"]"
                },
                {
                  "name": "prLabels",
                  "value": "[\"config-sync\", \"automated\", \"ios\"]"
                },
                {
                  "name": "emailTo",
                  "value": "user@example.com"
                }
              ]
            },
            "options": {}
          },
          "typeVersion": 1
        },
        {
          "id": "8b34ddf0-c670-40c1-b699-b30da3fcc6af",
          "name": "Prepare File and Merge Result",
          "type": "n8n-nodes-base.code",
          "position": [
            1300,
            280
          ],
          "parameters": {
            "jsCode": "// Prepare file updates for each iOS config file\nconst data = $input.first().json;\n\n// Extract repository name from the URL\n// Check if the URL exists\nconst url = data?.url;\nlet repoName = '';\nlet user = '';\nlet repoFullName = '';\nlet newBranch = '';\n// If the URL exists, extract the repository name and user\nif (url) {\n  const urlParts = url.split(\"/repos/\")[1]?.split(\"/\");\n  \n  if (urlParts && urlParts.length > 1) {\n    user = urlParts[0]; // Get the user (e.g., username)\n    repoName = urlParts[1]; // Get the repository name (e.g., repo_app)\n    repoFullName = `${user}/${repoName}`; // Full repository name (e.g., username/repo_app)\n  }\n}\n\nconst targetBranch = $node[\"SetConfiguration\"].json[\"targetBranch\"];\n\n// Extract the new branch name from the `ref` field\nconst ref = data?.ref;\nif (ref) {\n  // Remove \"refs/heads/\" to get just the branch name\n  newBranch = ref.replace(\"refs/heads/\", \"\");\n}\n\nreturn [\n  {\n    json: {\n      ...data,\n      user,\n      repoName,\n      repoFullName,\n      targetBranch,\n      newBranch\n    }\n  }\n];\n"
          },
          "typeVersion": 1
        },
        {
          "id": "52d9141f-0b0e-45d8-8930-3d535f99d834",
          "name": "Send Email Notification",
          "type": "n8n-nodes-base.gmail",
          "position": [
            1960,
            280
          ],
          "webhookId": "7b33ec82-a94f-428d-8be6-31100c30f97f",
          "parameters": {
            "sendTo": "={{ $node[\"SetConfiguration\"].json[\"emailTo\"] }}",
            "message": "=Environment Configuration Sync Completed \\nRepository: {{ $json.head.repo.full_name }}\\nBranch: {{ $('Prepare File and Merge Result').item.json.newBranch }}\\nPR: #{{ $json.number }}\\n\\nSummary:\\n- {{ $json.changed_files }} iOS config files updated\\n- {{ $json.cacheInvalidated ? 'Xcode cache invalidation triggered' : 'No cache invalidation needed' }}\\n\\nChanges Made:\\n{{ $json.configUpdates.map(u => `\\n${u.file}:\\n${u.changes.map(c => `  - ${c.key}: ${c.oldValue} → ${c.newValue}`).join('\\n')}`).join('\\n') }}\\n\\nView PR: https://github.com/{{ $json.head.repo.full_name }}/pull/{{ $json.number }}\\n\\n---\\nThis email was automatically generated by the Environment Config Sync for iOS workflow.",
            "options": {
              "appendAttribution": false
            },
            "subject": "=iOS Config Sync Completed - {{ $json.head.repo.full_name }}",
            "emailType": "text"
          },
          "credentials": {
            "gmailOAuth2": {
              "id": "credential-id",
              "name": "gmailOAuth2 Credential"
            }
          },
          "typeVersion": 2.1
        },
        {
          "id": "b218d17f-8fd4-437e-bf17-418fcd5edda6",
          "name": "Create PR",
          "type": "n8n-nodes-base.httpRequest",
          "onError": "continueErrorOutput",
          "position": [
            1520,
            280
          ],
          "parameters": {
            "url": "=https://api.github.com/repos/{{ $json.repoFullName }}/pulls",
            "method": "POST",
            "options": {},
            "jsonBody": "={\n  \"title\": \"Sync iOS Configurations\",\n  \"body\": \"This PR syncs iOS configuration changes.\",\n  \"head\": \"{{ $json.newBranch }}\",\n  \"base\": \"{{ $json.targetBranch }}\",\n  \"maintainer_can_modify\": true\n}\n",
            "sendBody": true,
            "sendHeaders": true,
            "specifyBody": "json",
            "authentication": "predefinedCredentialType",
            "headerParameters": {
              "parameters": [
                {
                  "name": "Authorization",
                  "value": "Bearer ${token}"
                },
                {
                  "name": "Content-Type",
                  "value": "application/json"
                }
              ]
            },
            "nodeCredentialType": "githubApi"
          },
          "credentials": {
            "githubApi": {
              "id": "credential-id",
              "name": "githubApi Credential"
            }
          },
          "typeVersion": 4.2,
          "alwaysOutputData": true
        },
        {
          "id": "a4946753-c20a-49cb-8414-ebb2786b16e1",
          "name": "Create Branch",
          "type": "n8n-nodes-base.httpRequest",
          "onError": "continueErrorOutput",
          "position": [
            1080,
            280
          ],
          "parameters": {
            "url": "=https://api.github.com/repos/{{ $json.repository }}/git/refs",
            "method": "POST",
            "options": {},
            "jsonBody": "={\n  \"ref\": \"refs/heads/{{ $json[\"branchName\"] }}\",\n  \"sha\": \"{{ $json[\"commitSha\"] }}\"\n}\n",
            "sendBody": true,
            "sendHeaders": true,
            "specifyBody": "json",
            "authentication": "predefinedCredentialType",
            "headerParameters": {
              "parameters": [
                {
                  "name": "Authorization",
                  "value": "Bearer ${token}"
                },
                {
                  "name": "Content-Type",
                  "value": "application/json"
                }
              ]
            },
            "nodeCredentialType": "githubApi"
          },
          "credentials": {
            "githubApi": {
              "id": "credential-id",
              "name": "githubApi Credential"
            }
          },
          "typeVersion": 4.2
        },
        {
          "id": "e36828b0-5520-4840-9864-633cb755511a",
          "name": "Github Push Trigger",
          "type": "n8n-nodes-base.githubTrigger",
          "position": [
            -20,
            280
          ],
          "webhookId": "18e18df2-708c-4497-966c-48181fdb800b",
          "parameters": {
            "owner": {
              "__rl": true,
              "mode": "name",
              "value": "username"
            },
            "events": [
              "push"
            ],
            "options": {
              "insecureSSL": false
            },
            "repository": {
              "__rl": true,
              "mode": "list",
              "value": "repo_app",
              "cachedResultUrl": "",
              "cachedResultName": "repo_app"
            }
          },
          "credentials": {
            "githubApi": {
              "id": "credential-id",
              "name": "githubApi Credential"
            }
          },
          "typeVersion": 1
        },
        {
          "id": "7079fb26-5b6a-448e-8815-ab39231a2f8e",
          "name": "Sticky Note1",
          "type": "n8n-nodes-base.stickyNote",
          "position": [
            -100,
            660
          ],
          "parameters": {
            "width": 2400,
            "height": 2120,
            "content": "## Description\n\n### 1. Github Push Trigger\n- Purpose: Watches for push events on the username/repo repository.\n- What it does: When a commit is pushed, it captures details such as repository name, branch (ref), commit SHA (after), and changed files.\n- Key Output: Provides raw push payload data that other nodes consume for further processing.\n\n---\n\n### 2. SetConfiguration and Customisation\n- Purpose: Defines configurable parameters for the workflow.\n- What it does:\n- Specifies the environment file to monitor (.env.staging).\n- Lists config files to update (Info.plist, Config.xcconfig).\n- Sets the target branch (main).\n- Declares cache invalidation keys (API_KEY, BUNDLE_VERSION, ENVIRONMENT).\n- Adds PR labels (config-sync, automated, ios).\n- Configures email notification recipient (eg: ios-team@example.com).\n- Key Output: Passes configuration values downstream for diffing and PR creation.\n\n---\n\n### 3. Check Changed Files\n- Purpose: Detects if .env.staging was modified in the latest push.\n- What it does:\n- Parses commit payload.\n- Flattens all added/modified/removed files.\n- Checks whether .env.staging exists in the changed files.\n- Key Output: Returns envFileChanged = true/false plus the repository and commit details.\n\n---\n\n### 4. Perform Config Diff\n- Purpose: Analyzes differences between .env.staging and iOS configuration files.\n- What it does:\n- Extracts simulated environment changes (e.g., API_KEY, BUNDLE_VERSION).\n- Prepares configUpdates array describing old → new values for each file.\n- Determines if cache invalidation is required (based on keys).\n- Key Output: Provides structured diff results and flags whether cache invalidation is needed.\n\n---\n\n### 5. Create Branch Name\n- Purpose: Generates a unique branch name for the configuration changes.\n- What it does: Appends a timestamp to ios-config-sync/ (e.g., ios-config-sync/2025-09-01T12-00-00).\n- Key Output: New branch name (branchName) to be created in GitHub.\n\n---\n\n### 6. Create Branch\n- Purpose: Creates a new branch in the repository.\n- What it does: Calls GitHub API to create a reference (refs/heads/branchName) from the latest commit SHA.\n- Key Output: Confirmation of branch creation for downstream file updates.\n\n---\n\n### 7. Prepare File and Merge Result\n- Purpose: Prepares repository details for file updates and PR creation.\n- What it does:\n- Extracts user, repoName, and repoFullName from the repository URL.\n- Determines newBranch name from ref.\n- Prepares a merged JSON object with config updates and metadata.\n- Key Output: Supplies enriched repository details for PR step.\n\n---\n\n### 8. Create PR\n- Purpose: Opens a pull request in GitHub with the config changes.\n- What it does:\n- Uses GitHub API to create PR with title “Sync iOS Configurations”.\n- Sets head = newBranch, base = main.\n- Attaches PR labels.\n- Key Output: Returns PR number (prNumber) and metadata for notifications.\n\n---\n\n### 9. Invalidate Cache\n- Purpose: Triggers Xcode build cache invalidation if required.\n- What it does:\n- Checks cacheInvalidationNeeded.\n- If true, marks cache as invalidated and logs message (e.g., “Xcode cache invalidation triggered for keys: API_KEY, BUNDLE_VERSION”).\n- Key Output: Adds cacheInvalidated status and message to workflow data.\n\n---\n\n### 10. Send Email Notification\n- Purpose: Notifies stakeholders of completed config sync.\n- What it does:\n- Sends Gmail notification to the configured recipient.\n- Includes repository name, branch, PR number, number of updated config files, cache invalidation status, and detailed change log.\n- Adds GitHub PR link for quick access.\n- Key Output: Final communication to confirm sync completion.\n\n---"
          },
          "typeVersion": 1
        },
        {
          "id": "d8620a5d-87e5-4174-978e-bbd37bce0a50",
          "name": "Sticky Note",
          "type": "n8n-nodes-base.stickyNote",
          "position": [
            -100,
            120
          ],
          "parameters": {
            "width": 2400,
            "height": 440,
            "content": "## iOS Environment Config Sync Wizard: .env to Xcode"
          },
          "typeVersion": 1
        }
      ],
      "active": false,
      "pinData": {
        "Github Push Trigger": [
          {
            "json": {
              "body": {
                "ref": "refs/heads/develop",
                "after": "e592287f68b64ddd754dd0f64aedd84f37a270ba",
                "before": "0000000000000000000000000000000000000000",
                "forced": false,
                "pusher": {
                  "name": "username",
                  "email": "151736888+username@users.noreply.github.com"
                },
                "sender": {
                  "id": 151736888,
                  "url": "https://api.github.com/users/username",
                  "type": "User",
                  "login": "username",
                  "node_id": "U_kgDOCQtSOA",
                  "html_url": "https://github.com/username",
                  "gists_url": "https://api.github.com/users/username/gists{/gist_id}",
                  "repos_url": "https://api.github.com/users/username/repos",
                  "avatar_url": "https://avatars.githubusercontent.com/u/151736888?v=4",
                  "events_url": "https://api.github.com/users/username/events{/privacy}",
                  "site_admin": false,
                  "gravatar_id": "",
                  "starred_url": "https://api.github.com/users/username/starred{/owner}{/repo}",
                  "followers_url": "https://api.github.com/users/username/followers",
                  "following_url": "https://api.github.com/users/username/following{/other_user}",
                  "user_view_type": "public",
                  "organizations_url": "https://api.github.com/users/username/orgs",
                  "subscriptions_url": "https://api.github.com/users/username/subscriptions",
                  "received_events_url": "https://api.github.com/users/username/received_events"
                },
                "commits": [
                  {
                    "id": "e592287f68b64ddd754dd0f64aedd84f37a270ba",
                    "url": "",
                    "added": [],
                    "author": {
                      "name": "username",
                      "email": "username@example.com",
                      "username": "username"
                    },
                    "message": "change3",
                    "removed": [],
                    "tree_id": "6e0f7c23e352216f6eac41c17d4f87c76d55dcd5",
                    "distinct": true,
                    "modified": [
                      "",
                      "n8n_flow_app/.env.staging"
                    ],
                    "committer": {
                      "name": "username",
                      "email": "username@example.com",
                      "username": "username"
                    },
                    "timestamp": "2025-08-30T19:58:10+05:30"
                  }
                ],
                "compare": "",
                "created": true,
                "deleted": false,
                "base_ref": null,
                "repository": {
                  "id": 1040155358,
                  "url": "https://api.github.com/repos/username/repo_app",
                  "fork": false,
                  "name": "repo_app",
                  "size": 31,
                  "forks": 0,
                  "owner": {
                    "id": 151736888,
                    "url": "https://api.github.com/users/username",
                    "name": "username",
                    "type": "User",
                    "email": "151736888+username@users.noreply.github.com",
                    "login": "username",
                    "node_id": "U_kgDOCQtSOA",
                    "html_url": "https://github.com/username",
                    "gists_url": "https://api.github.com/users/username/gists{/gist_id}",
                    "repos_url": "https://api.github.com/users/username/repos",
                    "avatar_url": "https://avatars.githubusercontent.com/u/151736888?v=4",
                    "events_url": "https://api.github.com/users/username/events{/privacy}",
                    "site_admin": false,
                    "gravatar_id": "",
                    "starred_url": "https://api.github.com/users/username/starred{/owner}{/repo}",
                    "followers_url": "https://api.github.com/users/username/followers",
                    "following_url": "https://api.github.com/users/username/following{/other_user}",
                    "user_view_type": "public",
                    "organizations_url": "https://api.github.com/users/username/orgs",
                    "subscriptions_url": "https://api.github.com/users/username/subscriptions",
                    "received_events_url": "https://api.github.com/users/username/received_events"
                  },
                  "topics": [],
                  "git_url": "git://github.com/username/repo_app.git",
                  "license": null,
                  "node_id": "R_kgDOPf-C3g",
                  "private": false,
                  "ssh_url": "git@github.com:username/repo_app.git",
                  "svn_url": "https://github.com/username/repo_app",
                  "archived": false,
                  "disabled": false,
                  "has_wiki": true,
                  "homepage": null,
                  "html_url": "https://github.com/username/repo_app",
                  "keys_url": "https://api.github.com/repos/username/repo_app/keys{/key_id}",
                  "language": "Swift",
                  "tags_url": "https://api.github.com/repos/username/repo_app/tags",
                  "watchers": 0,
                  "blobs_url": "https://api.github.com/repos/username/repo_app/git/blobs{/sha}",
                  "clone_url": "https://github.com/username/repo_app.git",
                  "forks_url": "https://api.github.com/repos/username/repo_app/forks",
                  "full_name": "username/repo_app",
                  "has_pages": false,
                  "hooks_url": "https://api.github.com/repos/username/repo_app/hooks",
                  "pulls_url": "https://api.github.com/repos/username/repo_app/pulls{/number}",
                  "pushed_at": 1756564260,
                  "teams_url": "https://api.github.com/repos/username/repo_app/teams",
                  "trees_url": "https://api.github.com/repos/username/repo_app/git/trees{/sha}",
                  "created_at": 1755527836,
                  "events_url": "https://api.github.com/repos/username/repo_app/events",
                  "has_issues": true,
                  "issues_url": "https://api.github.com/repos/username/repo_app/issues{/number}",
                  "labels_url": "https://api.github.com/repos/username/repo_app/labels{/name}",
                  "merges_url": "https://api.github.com/repos/username/repo_app/merges",
                  "mirror_url": null,
                  "stargazers": 0,
                  "updated_at": "2025-08-30T10:36:42Z",
                  "visibility": "public",
                  "archive_url": "https://api.github.com/repos/username/repo_app/{archive_format}{/ref}",
                  "commits_url": "https://api.github.com/repos/username/repo_app/commits{/sha}",
                  "compare_url": "https://api.github.com/repos/username/repo_app/compare/{base}...{head}",
                  "description": "n8n work flow ",
                  "forks_count": 0,
                  "is_template": false,
                  "open_issues": 0,
                  "branches_url": "https://api.github.com/repos/username/repo_app/branches{/branch}",
                  "comments_url": "https://api.github.com/repos/username/repo_app/comments{/number}",
                  "contents_url": "https://api.github.com/repos/username/repo_app/contents/{+path}",
                  "git_refs_url": "https://api.github.com/repos/username/repo_app/git/refs{/sha}",
                  "git_tags_url": "https://api.github.com/repos/username/repo_app/git/tags{/sha}",
                  "has_projects": true,
                  "releases_url": "https://api.github.com/repos/username/repo_app/releases{/id}",
                  "statuses_url": "https://api.github.com/repos/username/repo_app/statuses/{sha}",
                  "allow_forking": true,
                  "assignees_url": "https://api.github.com/repos/username/repo_app/assignees{/user}",
                  "downloads_url": "https://api.github.com/repos/username/repo_app/downloads",
                  "has_downloads": true,
                  "languages_url": "https://api.github.com/repos/username/repo_app/languages",
                  "master_branch": "main",
                  "default_branch": "main",
                  "milestones_url": "https://api.github.com/repos/username/repo_app/milestones{/number}",
                  "stargazers_url": "https://api.github.com/repos/username/repo_app/stargazers",
                  "watchers_count": 0,
                  "deployments_url": "https://api.github.com/repos/username/repo_app/deployments",
                  "git_commits_url": "https://api.github.com/repos/username/repo_app/git/commits{/sha}",
                  "has_discussions": false,
                  "subscribers_url": "https://api.github.com/repos/username/repo_app/subscribers",
                  "contributors_url": "https://api.github.com/repos/username/repo_app/contributors",
                  "issue_events_url": "https://api.github.com/repos/username/repo_app/issues/events{/number}",
                  "stargazers_count": 0,
                  "subscription_url": "https://api.github.com/repos/username/repo_app/subscription",
                  "collaborators_url": "https://api.github.com/repos/username/repo_app/collaborators{/collaborator}",
                  "issue_comment_url": "https://api.github.com/repos/username/repo_app/issues/comments{/number}",
                  "notifications_url": "https://api.github.com/repos/username/repo_app/notifications{?since,all,participating}",
                  "open_issues_count": 0,
                  "web_commit_signoff_required": false
                },
                "head_commit": {
                  "id": "e592287f68b64ddd754dd0f64aedd84f37a270ba",
                  "url": "",
                  "added": [],
                  "author": {
                    "name": "username",
                    "email": "username@example.com",
                    "username": "username"
                  },
                  "message": "change3",
                  "removed": [],
                  "tree_id": "6e0f7c23e352216f6eac41c17d4f87c76d55dcd5",
                  "distinct": true,
                  "modified": [
                    "",
                    "n8n_flow_app/.env.staging"
                  ],
                  "committer": {
                    "name": "username",
                    "email": "username@example.com",
                    "username": "username"
                  },
                  "timestamp": "2025-08-30T19:58:10+05:30"
                }
              },
              "query": {},
              "headers": {
                "host": "domain.app.n8n.cloud",
                "accept": "*/*",
                "cf-ray": "9774fd47659dd6f7-IAD",
                "cdn-loop": "托管平台; loops=1; subreqs=1",
                "cf-ew-via": "15",
                "cf-worker": "n8n.cloud",
                "x-real-ip": "140.82.115.102",
                "cf-visitor": "{\"scheme\":\"https\"}",
                "user-agent": "GitHub-Hookshot/bebe1c7",
                "cf-ipcountry": "US",
                "content-type": "application/json",
                "x-is-trusted": "yes",
                "content-length": "7278",
                "x-github-event": "push",
                "accept-encoding": "gzip, br",
                "x-forwarded-for": "140.82.115.102, 172.71.194.43",
                "cf-connecting-ip": "140.82.115.102",
                "x-forwarded-host": "domain.app.n8n.cloud",
                "x-forwarded-port": "443",
                "x-github-hook-id": "566851828",
                "x-forwarded-proto": "https",
                "x-github-delivery": "f3435bd4-85ad-11f0-824f-61363511cd42",
                "x-forwarded-server": "traefik-prod-users-gwc-84-57fcbd49bc-g4r2w",
                "x-github-hook-installation-target-id": "1040155358",
                "x-github-hook-installation-target-type": "repository"
              }
            }
          }
        ]
      },
      "settings": {
        "executionOrder": "v1"
      },
      "versionId": "f44fd78d-b44c-4689-adf7-f576535c6db5",
      "connections": {
        "Create PR": {
          "main": [
            [
              {
                "node": "Invalidate Cache",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Create Branch": {
          "main": [
            [
              {
                "node": "Prepare File and Merge Result",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Invalidate Cache": {
          "main": [
            [
              {
                "node": "Send Email Notification",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "SetConfiguration": {
          "main": [
            [
              {
                "node": "Check Changed Files",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Create Branch Name": {
          "main": [
            [
              {
                "node": "Create Branch",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Check Changed Files": {
          "main": [
            [
              {
                "node": "Perform Config Diff",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Github Push Trigger": {
          "main": [
            [
              {
                "node": "SetConfiguration",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Perform Config Diff": {
          "main": [
            [
              {
                "node": "Create Branch Name",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Prepare File and Merge Result": {
          "main": [
            [
              {
                "node": "Create PR",
                "type": "main",
                "index": 0
              }
            ]
          ]
        }
      }
    },
    "lastUpdatedBy": 1,
    "workflowInfo": {
      "nodeCount": 12,
      "nodeTypes": {
        "n8n-nodes-base.set": {
          "count": 1
        },
        "n8n-nodes-base.code": {
          "count": 5
        },
        "n8n-nodes-base.gmail": {
          "count": 1
        },
        "n8n-nodes-base.stickyNote": {
          "count": 2
        },
        "n8n-nodes-base.httpRequest": {
          "count": 2
        },
        "n8n-nodes-base.githubTrigger": {
          "count": 1
        }
      }
    },
    "status": "published",
    "user": {
      "name": "WeblineIndia",
      "username": "weblineindia",
      "bio": "A Leading Software Engineering, Consulting & Outsourcing Services Company in USA & India serving Clients Globally since 1999.",
      "verified": true,
      "links": [
        "https://www.weblineindia.com/"
      ],
      "avatar": "https://gravatar.com/avatar/a229d43aefca4588581583c58bb37b4773aebbdf4c1fef86a08bb1d38eae91fa?r=pg&d=retro&size=200"
    },
    "nodes": [
      {
        "id": 17,
        "icon": "file:github.svg",
        "name": "n8n-nodes-base.githubTrigger",
        "codex": {
          "data": {
            "resources": {
              "generic": [
                {
                  "url": "https://n8n.io/blog/automation-for-maintainers-of-open-source-projects/",
                  "icon": "🏷️",
                  "label": "How to automatically manage contributions to open-source projects"
                },
                {
                  "url": "https://n8n.io/blog/5-workflow-automations-for-mattermost-that-we-love-at-n8n/",
                  "icon": "🤖",
                  "label": "5 workflow automations for Mattermost that we love at n8n"
                },
                {
                  "url": "https://n8n.io/blog/how-to-set-up-a-ci-cd-pipeline-with-no-code/",
                  "icon": "🎡",
                  "label": "How to set up a no-code CI/CD pipeline with GitHub and TravisCI"
                }
              ],
              "primaryDocumentation": [
                {
                  "url": "https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.githubtrigger/"
                }
              ],
              "credentialDocumentation": [
                {
                  "url": "https://docs.n8n.io/integrations/builtin/credentials/github/"
                }
              ]
            },
            "categories": [
              "Development"
            ],
            "nodeVersion": "1.0",
            "codexVersion": "1.0"
          }
        },
        "group": "[\"trigger\"]",
        "defaults": {
          "name": "Github Trigger"
        },
        "iconData": {
          "type": "file",
          "fileBuffer": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yMC4wMTY1IDBDOC45NDc5MSAwIDAgOS4wMTM4OCAwIDIwLjE2NTNDMCAyOS4wNzkyIDUuNzMzMjQgMzYuNjI0NiAxMy42ODY4IDM5LjI5NTJDMTQuNjgxMiAzOS40OTYgMTUuMDQ1NCAzOC44NjEzIDE1LjA0NTQgMzguMzI3NEMxNS4wNDU0IDM3Ljg1OTkgMTUuMDEyNiAzNi4yNTc1IDE1LjAxMjYgMzQuNTg3OUM5LjQ0NDUgMzUuNzkgOC4yODQ5OCAzMi4xODQxIDguMjg0OTggMzIuMTg0MUM3LjM5MDE1IDI5Ljg0NyA2LjA2NDI5IDI5LjI0NjMgNi4wNjQyOSAyOS4yNDYzQzQuMjQxODUgMjguMDExIDYuMTk3MDQgMjguMDExIDYuMTk3MDQgMjguMDExQzguMjE4NjEgMjguMTQ0NiA5LjI3OTM4IDMwLjA4MSA5LjI3OTM4IDMwLjA4MUMxMS4wNjg2IDMzLjE1MjIgMTMuOTUxOCAzMi4yODQ0IDE1LjExMTggMzEuNzUwMkMxNS4yNzczIDMwLjQ0ODEgMTUuODA3OSAyOS41NDY3IDE2LjM3MTMgMjkuMDQ2QzExLjkzMDMgMjguNTc4NSA3LjI1NzgxIDI2Ljg0MjUgNy4yNTc4MSAxOS4wOTY3QzcuMjU3ODEgMTYuODkzMiA4LjA1MjY3IDE1LjA5MDUgOS4zMTIxNiAxMy42ODg0QzkuMTEzNDQgMTMuMTg3NyA4LjQxNzMyIDExLjExNzQgOS41MTEyOCA4LjM0NjQ0QzkuNTExMjggOC4zNDY0NCAxMS4yMDE0IDcuODEyMTcgMTUuMDEyMiAxMC40MTY0QzE2LjY0MzggOS45NzQ5NSAxOC4zMjYzIDkuNzUwNCAyMC4wMTY1IDkuNzQ4NTFDMjEuNzA2NyA5Ljc0ODUxIDIzLjQyOTUgOS45ODI0NiAyNS4wMjA1IDEwLjQxNjRDMjguODMxNyA3LjgxMjE3IDMwLjUyMTggOC4zNDY0NCAzMC41MjE4IDguMzQ2NDRDMzEuNjE1OCAxMS4xMTc0IDMwLjkxOTIgMTMuMTg3NyAzMC43MjA1IDEzLjY4ODRDMzIuMDEzMiAxNS4wOTA1IDMyLjc3NTMgMTYuODkzMiAzMi43NzUzIDE5LjA5NjdDMzIuNzc1MyAyNi44NDI1IDI4LjEwMjggMjguNTQ0OSAyMy42Mjg3IDI5LjA0NkMyNC4zNTggMjkuNjgwMiAyNC45ODczIDMwLjg4MiAyNC45ODczIDMyLjc4NTFDMjQuOTg3MyAzNS40ODkzIDI0Ljk1NDUgMzcuNjU5NiAyNC45NTQ1IDM4LjMyN0MyNC45NTQ1IDM4Ljg2MTMgMjUuMzE5MiAzOS40OTYgMjYuMzEzMiAzOS4yOTU2QzM0LjI2NjcgMzYuNjI0MiAzOS45OTk5IDI5LjA3OTIgMzkuOTk5OSAyMC4xNjUzQzQwLjAzMjcgOS4wMTM4OCAzMS4wNTIgMCAyMC4wMTY1IDBaIiBmaWxsPSIjMjQyOTJGIi8+Cjwvc3ZnPgo="
        },
        "displayName": "Github Trigger",
        "typeVersion": 1,
        "nodeCategories": [
          {
            "id": 5,
            "name": "Development"
          }
        ]
      },
      {
        "id": 19,
        "icon": "file:httprequest.svg",
        "name": "n8n-nodes-base.httpRequest",
        "codex": {
          "data": {
            "alias": [
              "API",
              "Request",
              "URL",
              "Build",
              "cURL"
            ],
            "resources": {
              "generic": [
                {
                  "url": "https://n8n.io/blog/2021-the-year-to-automate-the-new-you-with-n8n/",
                  "icon": "☀️",
                  "label": "2021: The Year to Automate the New You with n8n"
                },
                {
                  "url": "https://n8n.io/blog/why-business-process-automation-with-n8n-can-change-your-daily-life/",
                  "icon": "🧬",
                  "label": "Why business process automation with n8n can change your daily life"
                },
                {
                  "url": "https://n8n.io/blog/automatically-pulling-and-visualizing-data-with-n8n/",
                  "icon": "📈",
                  "label": "Automatically pulling and visualizing data with n8n"
                },
                {
                  "url": "https://n8n.io/blog/learn-how-to-automatically-cross-post-your-content-with-n8n/",
                  "icon": "✍️",
                  "label": "Learn how to automatically cross-post your content with n8n"
                },
                {
                  "url": "https://n8n.io/blog/automatically-adding-expense-receipts-to-google-sheets-with-telegram-mindee-twilio-and-n8n/",
                  "icon": "🧾",
                  "label": "Automatically Adding Expense Receipts to Google Sheets with Telegram, Mindee, Twilio, and n8n"
                },
                {
                  "url": "https://n8n.io/blog/running-n8n-on-ships-an-interview-with-maranics/",
                  "icon": "🛳",
                  "label": "Running n8n on ships: An interview with Maranics"
                },
                {
                  "url": "https://n8n.io/blog/what-are-apis-how-to-use-them-with-no-code/",
                  "icon": " 🪢",
                  "label": "What are APIs and how to use them with no code"
                },
                {
                  "url": "https://n8n.io/blog/5-tasks-you-can-automate-with-notion-api/",
                  "icon": "⚡️",
                  "label": "5 tasks you can automate with the new Notion API "
                },
                {
                  "url": "https://n8n.io/blog/world-poetry-day-workflow/",
                  "icon": "📜",
                  "label": "Celebrating World Poetry Day with a daily poem in Telegram"
                },
                {
                  "url": "https://n8n.io/blog/automate-google-apps-for-productivity/",
                  "icon": "💡",
                  "label": "15 Google apps you can combine and automate to increase productivity"
                },
                {
                  "url": "https://n8n.io/blog/automate-designs-with-bannerbear-and-n8n/",
                  "icon": "🎨",
                  "label": "Automate Designs with Bannerbear and n8n"
                },
                {
                  "url": "https://n8n.io/blog/how-uproc-scraped-a-multi-page-website-with-a-low-code-workflow/",
                  "icon": " 🕸️",
                  "label": "How uProc scraped a multi-page website with a low-code workflow"
                },
                {
                  "url": "https://n8n.io/blog/building-an-expense-tracking-app-in-10-minutes/",
                  "icon": "📱",
                  "label": "Building an expense tracking app in 10 minutes"
                },
                {
                  "url": "https://n8n.io/blog/5-workflow-automations-for-mattermost-that-we-love-at-n8n/",
                  "icon": "🤖",
                  "label": "5 workflow automations for Mattermost that we love at n8n"
                },
                {
                  "url": "https://n8n.io/blog/how-to-use-the-http-request-node-the-swiss-army-knife-for-workflow-automation/",
                  "icon": "🧰",
                  "label": "How to use the HTTP Request Node - The Swiss Army Knife for Workflow Automation"
                },
                {
                  "url": "https://n8n.io/blog/learn-how-to-use-webhooks-with-mattermost-slash-commands/",
                  "icon": "🦄",
                  "label": "Learn how to use webhooks with Mattermost slash commands"
                },
                {
                  "url": "https://n8n.io/blog/how-a-membership-development-manager-automates-his-work-and-investments/",
                  "icon": "📈",
                  "label": "How a Membership Development Manager automates his work and investments"
                },
                {
                  "url": "https://n8n.io/blog/a-low-code-bitcoin-ticker-built-with-questdb-and-n8n-io/",
                  "icon": "📈",
                  "label": "A low-code bitcoin ticker built with QuestDB and n8n.io"
                },
                {
                  "url": "https://n8n.io/blog/how-to-set-up-a-ci-cd-pipeline-with-no-code/",
                  "icon": "🎡",
                  "label": "How to set up a no-code CI/CD pipeline with GitHub and TravisCI"
                },
                {
                  "url": "https://n8n.io/blog/automations-for-activists/",
                  "icon": "✨",
                  "label": "How Common Knowledge use workflow automation for activism"
                },
                {
                  "url": "https://n8n.io/blog/creating-scheduled-text-affirmations-with-n8n/",
                  "icon": "🤟",
                  "label": "Creating scheduled text affirmations with n8n"
                },
                {
                  "url": "https://n8n.io/blog/how-goomer-automated-their-operations-with-over-200-n8n-workflows/",
                  "icon": "🛵",
                  "label": "How Goomer automated their operations with over 200 n8n workflows"
                },
                {
                  "url": "https://n8n.io/blog/aws-workflow-automation/",
                  "label": "7 no-code workflow automations for Amazon Web Services"
                }
              ],
              "primaryDocumentation": [
                {
                  "url": "https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/"
                }
              ]
            },
            "categories": [
              "Development",
              "Core Nodes"
            ],
            "nodeVersion": "1.0",
            "codexVersion": "1.0",
            "subcategories": {
              "Core Nodes": [
                "Helpers"
              ]
            }
          }
        },
        "group": "[\"output\"]",
        "defaults": {
          "name": "HTTP Request",
          "color": "#0004F5"
        },
        "iconData": {
          "type": "file",
          "fileBuffer": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00MCAyMEM0MCA4Ljk1MzE0IDMxLjA0NjkgMCAyMCAwQzguOTUzMTQgMCAwIDguOTUzMTQgMCAyMEMwIDMxLjA0NjkgOC45NTMxNCA0MCAyMCA0MEMzMS4wNDY5IDQwIDQwIDMxLjA0NjkgNDAgMjBaTTIwIDM2Ljk0NThDMTguODg1MiAzNi45NDU4IDE3LjEzNzggMzUuOTY3IDE1LjQ5OTggMzIuNjk4NUMxNC43OTY0IDMxLjI5MTggMTQuMTk2MSAyOS41NDMxIDEzLjc1MjYgMjcuNjg0N0gyNi4xODk4QzI1LjgwNDUgMjkuNTQwMyAyNS4yMDQ0IDMxLjI5MDEgMjQuNTAwMiAzMi42OTg1QzIyLjg2MjIgMzUuOTY3IDIxLjExNDggMzYuOTQ1OCAyMCAzNi45NDU4Wk0xMi45MDY0IDIwQzEyLjkwNjQgMjEuNjA5NyAxMy4wMDg3IDIzLjE2NCAxMy4yMDAzIDI0LjYzMDVIMjYuNzk5N0MyNi45OTEzIDIzLjE2NCAyNy4wOTM2IDIxLjYwOTcgMjcuMDkzNiAyMEMyNy4wOTM2IDE4LjM5MDMgMjYuOTkxMyAxNi44MzYgMjYuNzk5NyAxNS4zNjk1SDEzLjIwMDNDMTMuMDA4NyAxNi44MzYgMTIuOTA2NCAxOC4zOTAzIDEyLjkwNjQgMjBaTTIwIDMuMDU0MTlDMjEuMTE0OSAzLjA1NDE5IDIyLjg2MjIgNC4wMzA3OCAyNC41MDAxIDcuMzAwMzlDMjUuMjA2NiA4LjcxNDA4IDI1LjgwNzIgMTAuNDA2NyAyNi4xOTIgMTIuMzE1M0gxMy43NTAxQzE0LjE5MzMgMTAuNDA0NyAxNC43OTQyIDguNzEyNTQgMTUuNDk5OCA3LjMwMDY0QzE3LjEzNzcgNC4wMzA4MyAxOC44ODUxIDMuMDU0MTkgMjAgMy4wNTQxOVpNMzAuMTQ3OCAyMEMzMC4xNDc4IDE4LjQwOTkgMzAuMDU0MyAxNi44NjE3IDI5LjgyMjcgMTUuMzY5NUgzNi4zMDQyQzM2LjcyNTIgMTYuODQyIDM2Ljk0NTggMTguMzk2NCAzNi45NDU4IDIwQzM2Ljk0NTggMjEuNjAzNiAzNi43MjUyIDIzLjE1OCAzNi4zMDQyIDI0LjYzMDVIMjkuODIyN0MzMC4wNTQzIDIzLjEzODMgMzAuMTQ3OCAyMS41OTAxIDMwLjE0NzggMjBaTTI2LjI3NjcgNC4yNTUxMkMyNy42MzY1IDYuMzYwMTkgMjguNzExIDkuMTMyIDI5LjM3NzQgMTIuMzE1M0gzNS4xMDQ2QzMzLjI1MTEgOC42NjggMzAuMTA3IDUuNzgzNDYgMjYuMjc2NyA0LjI1NTEyWk0xMC42MjI2IDEyLjMxNTNINC44OTI5M0M2Ljc1MTQ3IDguNjY3ODQgOS44OTM1MSA1Ljc4MzQxIDEzLjcyMzIgNC4yNTUxM0MxMi4zNjM1IDYuMzYwMjEgMTEuMjg5IDkuMTMyMDEgMTAuNjIyNiAxMi4zMTUzWk0zLjA1NDE5IDIwQzMuMDU0MTkgMjEuNjAzIDMuMjc3NDMgMjMuMTU3NSAzLjY5NDg0IDI0LjYzMDVIMTAuMTIxN0M5Ljk0NjE5IDIzLjE0MiA5Ljg1MjIyIDIxLjU5NDMgOS44NTIyMiAyMEM5Ljg1MjIyIDE4LjQwNTcgOS45NDYxOSAxNi44NTggMTAuMTIxNyAxNS4zNjk1SDMuNjk0ODRDMy4yNzc0MyAxNi44NDI1IDMuMDU0MTkgMTguMzk3IDMuMDU0MTkgMjBaTTI2LjI3NjYgMzUuNzQyN0MyNy42MzY1IDMzLjYzOTMgMjguNzExIDMwLjg2OCAyOS4zNzc0IDI3LjY4NDdIMzUuMTA0NkMzMy4yNTEgMzEuMzMyMiAzMC4xMDY4IDM0LjIxNzkgMjYuMjc2NiAzNS43NDI3Wk0xMy43MjM0IDM1Ljc0MjdDOS44OTM2OSAzNC4yMTc5IDYuNzUxNTUgMzEuMzMyNCA0Ljg5MjkzIDI3LjY4NDdIMTAuNjIyNkMxMS4yODkgMzAuODY4IDEyLjM2MzUgMzMuNjM5MyAxMy43MjM0IDM1Ljc0MjdaIiBmaWxsPSIjM0E0MkU5Ii8+Cjwvc3ZnPgo="
        },
        "displayName": "HTTP Request",
        "typeVersion": 4,
        "nodeCategories": [
          {
            "id": 5,
            "name": "Development"
          },
          {
            "id": 9,
            "name": "Core Nodes"
          }
        ]
      },
      {
        "id": 38,
        "icon": "fa:pen",
        "name": "n8n-nodes-base.set",
        "codex": {
          "data": {
            "alias": [
              "Set",
              "JS",
              "JSON",
              "Filter",
              "Transform",
              "Map"
            ],
            "resources": {
              "generic": [
                {
                  "url": "https://n8n.io/blog/learn-to-automate-your-factorys-incident-reporting-a-step-by-step-guide/",
                  "icon": "🏭",
                  "label": "Learn to Automate Your Factory's Incident Reporting: A Step by Step Guide"
                },
                {
                  "url": "https://n8n.io/blog/2021-the-year-to-automate-the-new-you-with-n8n/",
                  "icon": "☀️",
                  "label": "2021: The Year to Automate the New You with n8n"
                },
                {
                  "url": "https://n8n.io/blog/automatically-pulling-and-visualizing-data-with-n8n/",
                  "icon": "📈",
                  "label": "Automatically pulling and visualizing data with n8n"
                },
                {
                  "url": "https://n8n.io/blog/database-monitoring-and-alerting-with-n8n/",
                  "icon": "📡",
                  "label": "Database Monitoring and Alerting with n8n"
                },
                {
                  "url": "https://n8n.io/blog/automatically-adding-expense-receipts-to-google-sheets-with-telegram-mindee-twilio-and-n8n/",
                  "icon": "🧾",
                  "label": "Automatically Adding Expense Receipts to Google Sheets with Telegram, Mindee, Twilio, and n8n"
                },
                {
                  "url": "https://n8n.io/blog/no-code-ecommerce-workflow-automations/",
                  "icon": "store",
                  "label": "6 e-commerce workflows to power up your Shopify s"
                },
                {
                  "url": "https://n8n.io/blog/how-to-build-a-low-code-self-hosted-url-shortener/",
                  "icon": "🔗",
                  "label": "How to build a low-code, self-hosted URL shortener in 3 steps"
                },
                {
                  "url": "https://n8n.io/blog/automate-your-data-processing-pipeline-in-9-steps-with-n8n/",
                  "icon": "⚙️",
                  "label": "Automate your data processing pipeline in 9 steps"
                },
                {
                  "url": "https://n8n.io/blog/how-to-get-started-with-crm-automation-and-no-code-workflow-ideas/",
                  "icon": "👥",
                  "label": "How to get started with CRM automation (with 3 no-code workflow ideas"
                },
                {
                  "url": "https://n8n.io/blog/5-tasks-you-can-automate-with-notion-api/",
                  "icon": "⚡️",
                  "label": "5 tasks you can automate with the new Notion API "
                },
                {
                  "url": "https://n8n.io/blog/automate-google-apps-for-productivity/",
                  "icon": "💡",
                  "label": "15 Google apps you can combine and automate to increase productivity"
                },
                {
                  "url": "https://n8n.io/blog/how-uproc-scraped-a-multi-page-website-with-a-low-code-workflow/",
                  "icon": " 🕸️",
                  "label": "How uProc scraped a multi-page website with a low-code workflow"
                },
                {
                  "url": "https://n8n.io/blog/building-an-expense-tracking-app-in-10-minutes/",
                  "icon": "📱",
                  "label": "Building an expense tracking app in 10 minutes"
                },
                {
                  "url": "https://n8n.io/blog/the-ultimate-guide-to-automate-your-video-collaboration-with-whereby-mattermost-and-n8n/",
                  "icon": "📹",
                  "label": "The ultimate guide to automate your video collaboration with Whereby, Mattermost, and n8n"
                },
                {
                  "url": "https://n8n.io/blog/5-workflow-automations-for-mattermost-that-we-love-at-n8n/",
                  "icon": "🤖",
                  "label": "5 workflow automations for Mattermost that we love at n8n"
                },
                {
                  "url": "https://n8n.io/blog/learn-to-build-powerful-api-endpoints-using-webhooks/",
                  "icon": "🧰",
                  "label": "Learn to Build Powerful API Endpoints Using Webhooks"
                },
                {
                  "url": "https://n8n.io/blog/how-a-membership-development-manager-automates-his-work-and-investments/",
                  "icon": "📈",
                  "label": "How a Membership Development Manager automates his work and investments"
                },
                {
                  "url": "https://n8n.io/blog/a-low-code-bitcoin-ticker-built-with-questdb-and-n8n-io/",
                  "icon": "📈",
                  "label": "A low-code bitcoin ticker built with QuestDB and n8n.io"
                },
                {
                  "url": "https://n8n.io/blog/how-to-set-up-a-ci-cd-pipeline-with-no-code/",
                  "icon": "🎡",
                  "label": "How to set up a no-code CI/CD pipeline with GitHub and TravisCI"
                },
                {
                  "url": "https://n8n.io/blog/benefits-of-automation-and-n8n-an-interview-with-hubspots-hugh-durkin/",
                  "icon": "🎖",
                  "label": "Benefits of automation and n8n: An interview with HubSpot's Hugh Durkin"
                },
                {
                  "url": "https://n8n.io/blog/how-goomer-automated-their-operations-with-over-200-n8n-workflows/",
                  "icon": "🛵",
                  "label": "How Goomer automated their operations with over 200 n8n workflows"
                },
                {
                  "url": "https://n8n.io/blog/aws-workflow-automation/",
                  "label": "7 no-code workflow automations for Amazon Web Services"
                }
              ],
              "primaryDocumentation": [
                {
                  "url": "https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.set/"
                }
              ]
            },
            "categories": [
              "Core Nodes"
            ],
            "nodeVersion": "1.0",
            "codexVersion": "1.0",
            "subcategories": {
              "Core Nodes": [
                "Data Transformation"
              ]
            }
          }
        },
        "group": "[\"input\"]",
        "defaults": {
          "name": "Edit Fields"
        },
        "iconData": {
          "icon": "pen",
          "type": "icon"
        },
        "displayName": "Edit Fields (Set)",
        "typeVersion": 3,
        "nodeCategories": [
          {
            "id": 9,
            "name": "Core Nodes"
          }
        ]
      },
      {
        "id": 356,
        "icon": "file:gmail.svg",
        "name": "n8n-nodes-base.gmail",
        "codex": {
          "data": {
            "alias": [
              "email",
              "human",
              "form",
              "wait",
              "hitl",
              "approval"
            ],
            "resources": {
              "generic": [
                {
                  "url": "https://n8n.io/blog/why-business-process-automation-with-n8n-can-change-your-daily-life/",
                  "icon": "🧬",
                  "label": "Why business process automation with n8n can change your daily life"
                },
                {
                  "url": "https://n8n.io/blog/supercharging-your-conference-registration-process-with-n8n/",
                  "icon": "🎫",
                  "label": "Supercharging your conference registration process with n8n"
                },
                {
                  "url": "https://n8n.io/blog/no-code-ecommerce-workflow-automations/",
                  "icon": "store",
                  "label": "6 e-commerce workflows to power up your Shopify s"
                },
                {
                  "url": "https://n8n.io/blog/how-to-get-started-with-crm-automation-and-no-code-workflow-ideas/",
                  "icon": "👥",
                  "label": "How to get started with CRM automation (with 3 no-code workflow ideas"
                },
                {
                  "url": "https://n8n.io/blog/automate-google-apps-for-productivity/",
                  "icon": "💡",
                  "label": "15 Google apps you can combine and automate to increase productivity"
                },
                {
                  "url": "https://n8n.io/blog/your-business-doesnt-need-you-to-operate/",
                  "icon": " 🖥️",
                  "label": "Hey founders! Your business doesn't need you to operate"
                },
                {
                  "url": "https://n8n.io/blog/using-automation-to-boost-productivity-in-the-workplace/",
                  "icon": "💪",
                  "label": "Using Automation to Boost Productivity in the Workplace"
                }
              ],
              "primaryDocumentation": [
                {
                  "url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.gmail/"
                }
              ],
              "credentialDocumentation": [
                {
                  "url": "https://docs.n8n.io/integrations/builtin/credentials/google/oauth-single-service/"
                }
              ]
            },
            "categories": [
              "Communication",
              "HITL"
            ],
            "nodeVersion": "1.0",
            "codexVersion": "1.0",
            "subcategories": {
              "HITL": [
                "Human in the Loop"
              ]
            }
          }
        },
        "group": "[\"transform\"]",
        "defaults": {
          "name": "Gmail"
        },
        "iconData": {
          "type": "file",
          "fileBuffer": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNTYiIGhlaWdodD0iMTkzIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCI+PHBhdGggZmlsbD0iIzQyODVGNCIgZD0iTTU4LjE4MiAxOTIuMDVWOTMuMTRMMjcuNTA3IDY1LjA3NyAwIDQ5LjUwNHYxMjUuMDkxYzAgOS42NTggNy44MjUgMTcuNDU1IDE3LjQ1NSAxNy40NTV6Ii8+PHBhdGggZmlsbD0iIzM0QTg1MyIgZD0iTTE5Ny44MTggMTkyLjA1aDQwLjcyN2M5LjY1OSAwIDE3LjQ1NS03LjgyNiAxNy40NTUtMTcuNDU1VjQ5LjUwNWwtMzEuMTU2IDE3LjgzNy0yNy4wMjYgMjUuNzk4eiIvPjxwYXRoIGZpbGw9IiNFQTQzMzUiIGQ9Im01OC4xODIgOTMuMTQtNC4xNzQtMzguNjQ3IDQuMTc0LTM2Ljk4OUwxMjggNjkuODY4bDY5LjgxOC01Mi4zNjQgNC42NyAzNC45OTItNC42NyA0MC42NDRMMTI4IDE0NS41MDR6Ii8+PHBhdGggZmlsbD0iI0ZCQkMwNCIgZD0iTTE5Ny44MTggMTcuNTA0VjkzLjE0TDI1NiA0OS41MDRWMjYuMjMxYzAtMjEuNTg1LTI0LjY0LTMzLjg5LTQxLjg5LTIwLjk0NXoiLz48cGF0aCBmaWxsPSIjQzUyMjFGIiBkPSJtMCA0OS41MDQgMjYuNzU5IDIwLjA3TDU4LjE4MiA5My4xNFYxNy41MDRMNDEuODkgNS4yODZDMjQuNjEtNy42NiAwIDQuNjQ2IDAgMjYuMjN6Ii8+PC9zdmc+"
        },
        "displayName": "Gmail",
        "typeVersion": 2,
        "nodeCategories": [
          {
            "id": 6,
            "name": "Communication"
          },
          {
            "id": 28,
            "name": "HITL"
          }
        ]
      },
      {
        "id": 565,
        "icon": "fa:sticky-note",
        "name": "n8n-nodes-base.stickyNote",
        "codex": {
          "data": {
            "alias": [
              "Comments",
              "Notes",
              "Sticky"
            ],
            "categories": [
              "Core Nodes"
            ],
            "nodeVersion": "1.0",
            "codexVersion": "1.0",
            "subcategories": {
              "Core Nodes": [
                "Helpers"
              ]
            }
          }
        },
        "group": "[\"input\"]",
        "defaults": {
          "name": "Sticky Note",
          "color": "#FFD233"
        },
        "iconData": {
          "icon": "sticky-note",
          "type": "icon"
        },
        "displayName": "Sticky Note",
        "typeVersion": 1,
        "nodeCategories": [
          {
            "id": 9,
            "name": "Core Nodes"
          }
        ]
      },
      {
        "id": 834,
        "icon": "file:code.svg",
        "name": "n8n-nodes-base.code",
        "codex": {
          "data": {
            "alias": [
              "cpde",
              "Javascript",
              "JS",
              "Python",
              "Script",
              "Custom Code",
              "Function"
            ],
            "details": "The Code node allows you to execute JavaScript in your workflow.",
            "resources": {
              "primaryDocumentation": [
                {
                  "url": "https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code/"
                }
              ]
            },
            "categories": [
              "Development",
              "Core Nodes"
            ],
            "nodeVersion": "1.0",
            "codexVersion": "1.0",
            "subcategories": {
              "Core Nodes": [
                "Helpers",
                "Data Transformation"
              ]
            }
          }
        },
        "group": "[\"transform\"]",
        "defaults": {
          "name": "Code"
        },
        "iconData": {
          "type": "file",
          "fileBuffer": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF8xMTcxXzQ0MSkiPgo8cGF0aCBkPSJNMTcwLjI4MyA0OEgxOTYuNUMyMDMuMTI3IDQ4IDIwOC41IDQyLjYyNzQgMjA4LjUgMzZWMTJDMjA4LjUgNS4zNzI1OCAyMDMuMTI3IDAgMTk2LjUgMEgxNzAuMjgzQzEyNi4xIDAgOTAuMjgzIDM1LjgxNzIgOTAuMjgzIDgwVjE3NkM5MC4yODMgMjA2LjkyOCA2NS4yMTA5IDIzMiAzNC4yODMgMjMySDIzQzE2LjM3MjYgMjMyIDExIDIzNy4zNzIgMTEgMjQ0VjI2OEMxMSAyNzQuNjI3IDE2LjM3MjQgMjgwIDIyLjk5OTYgMjgwTDM0LjI4MyAyODBDNjUuMjEwOSAyODAgOTAuMjgzIDMwNS4wNzIgOTAuMjgzIDMzNlY0NDBDOTAuMjgzIDQ3OS43NjQgMTIyLjUxOCA1MTIgMTYyLjI4MyA1MTJIMTk2LjVDMjAzLjEyNyA1MTIgMjA4LjUgNTA2LjYyNyAyMDguNSA1MDBWNDc2QzIwOC41IDQ2OS4zNzMgMjAzLjEyNyA0NjQgMTk2LjUgNDY0SDE2Mi4yODNDMTQ5LjAyOCA0NjQgMTM4LjI4MyA0NTMuMjU1IDEzOC4yODMgNDQwVjMzNkMxMzguMjgzIDMwOS4wMjIgMTI4LjAxMSAyODQuNDQzIDExMS4xNjQgMjY1Ljk2MUMxMDYuMTA5IDI2MC40MTYgMTA2LjEwOSAyNTEuNTg0IDExMS4xNjQgMjQ2LjAzOUMxMjguMDExIDIyNy41NTcgMTM4LjI4MyAyMDIuOTc4IDEzOC4yODMgMTc2VjgwQzEzOC4yODMgNjIuMzI2OSAxNTIuNjEgNDggMTcwLjI4MyA0OFoiIGZpbGw9IiNGRjk5MjIiLz4KPHBhdGggZD0iTTMwNSAzNkMzMDUgNDIuNjI3NCAzMTAuMzczIDQ4IDMxNyA0OEgzNDIuOTc5QzM2MC42NTIgNDggMzc0Ljk3OCA2Mi4zMjY5IDM3NC45NzggODBWMTc2QzM3NC45NzggMjAyLjk3OCAzODUuMjUxIDIyNy41NTcgNDAyLjA5OCAyNDYuMDM5QzQwNy4xNTMgMjUxLjU4NCA0MDcuMTUzIDI2MC40MTYgNDAyLjA5OCAyNjUuOTYxQzM4NS4yNTEgMjg0LjQ0MyAzNzQuOTc4IDMwOS4wMjIgMzc0Ljk3OCAzMzZWNDMyQzM3NC45NzggNDQ5LjY3MyAzNjAuNjUyIDQ2NCAzNDIuOTc5IDQ2NEgzMTdDMzEwLjM3MyA0NjQgMzA1IDQ2OS4zNzMgMzA1IDQ3NlY1MDBDMzA1IDUwNi42MjcgMzEwLjM3MyA1MTIgMzE3IDUxMkgzNDIuOTc5QzM4Ny4xNjEgNTEyIDQyMi45NzggNDc2LjE4MyA0MjIuOTc4IDQzMlYzMzZDNDIyLjk3OCAzMDUuMDcyIDQ0OC4wNTEgMjgwIDQ3OC45NzkgMjgwSDQ5MEM0OTYuNjI3IDI4MCA1MDIgMjc0LjYyOCA1MDIgMjY4VjI0NEM1MDIgMjM3LjM3MyA0OTYuNjI4IDIzMiA0OTAgMjMyTDQ3OC45NzkgMjMyQzQ0OC4wNTEgMjMyIDQyMi45NzggMjA2LjkyOCA0MjIuOTc4IDE3NlY4MEM0MjIuOTc4IDM1LjgxNzIgMzg3LjE2MSAwIDM0Mi45NzkgMEgzMTdDMzEwLjM3MyAwIDMwNSA1LjM3MjU4IDMwNSAxMlYzNloiIGZpbGw9IiNGRjk5MjIiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8xMTcxXzQ0MSI+CjxyZWN0IHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo="
        },
        "displayName": "Code",
        "typeVersion": 2,
        "nodeCategories": [
          {
            "id": 5,
            "name": "Development"
          },
          {
            "id": 9,
            "name": "Core Nodes"
          }
        ]
      }
    ],
    "categories": [
      {
        "id": 16,
        "name": "DevOps"
      }
    ],
    "image": []
  }
}