{
  "nodes": [
    {
      "id": "e36b580a-9314-453c-88d6-7ffb948e79a8",
      "name": "1. Sample Data",
      "type": "n8n-nodes-base.set",
      "position": [
        512,
        480
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "38ce3db6-ce1d-4091-9645-39e674ad1782",
              "name": "users",
              "type": "array",
              "value": "=[{\"firstName\":\"Alice\",\"lastName\":\"Smith\",\"birthDate\":\"1990-05-15\"},{\"firstName\":\"Bob\",\"lastName\":\"Jones\",\"birthDate\":\"1985-11-22\"},{\"firstName\":\"Charlie\",\"lastName\":\"Brown\",\"birthDate\":\"2001-02-10\"}, {\"firstName\":\"Alex\",\"lastName\":\"Garcia\",\"birthDate\":\"1995-07-30\"}]"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "d77a1d9a-376a-451c-9fc3-174a60fb787a",
      "name": "2. Split Out Users",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        720,
        480
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "users"
      },
      "typeVersion": 1
    },
    {
      "id": "39ab2c6f-11ce-4e1e-a6c7-327d758f6d0c",
      "name": "3. Process Each User",
      "type": "n8n-nodes-base.code",
      "position": [
        1040,
        480
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// This code runs for EACH user individually.\n\n// 1. Get the data for the current item\nconst user = $input.item.json;\n\n// 2. Perform operations\nconst fullName = `${user.firstName} ${user.lastName}`;\n\nconst birthDate = new Date(user.birthDate);\nconst ageDiffMs = Date.now() - birthDate.getTime();\nconst ageDate = new Date(ageDiffMs);\nconst age = Math.abs(ageDate.getUTCFullYear() - 1970);\n\nconsole.log(`Processing user: ${fullName}, Age: ${age}`);\n\n// 3. Return the new data, keeping the original fields\nreturn {\n  ...user, // This keeps the original data (firstName, lastName, etc.)\n  fullName: fullName,\n  age: age\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "9f4aa08e-f15f-4215-843c-87997e6d6cff",
      "name": "5. Calculate Average Age",
      "type": "n8n-nodes-base.code",
      "position": [
        1840,
        480
      ],
      "parameters": {
        "jsCode": "// This code runs only ONCE for ALL users.\n\n// 1. Get all items from the previous node\nconst allUsers = $items();\n\n// 2. Perform an aggregation\nconst totalAge = allUsers.reduce((sum, item) => {\n  return sum + item.json.age;\n}, 0);\n\nconst userCount = allUsers.length;\nconst averageAge = totalAge / userCount;\n\nconsole.log(`Calculated average age for ${userCount} users.`);\n\n// 3. Return a single new item with the result\nreturn [\n  {\n    json: {\n      totalUsers: userCount,\n      averageAge: parseFloat(averageAge.toFixed(2)) // Format to 2 decimal places\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "2e7f0710-0b4a-450e-8e87-591c5324f5c7",
      "name": "4. Fetch External Data (Advanced)",
      "type": "n8n-nodes-base.code",
      "position": [
        1440,
        480
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// ADVANCED: This code calls an external API for each user.\n\n// 1. Get the data for the current item\nconst user = $input.item.json;\n\n// 2. Use a helper function to make an HTTP request\n// We'll use a free API to guess the gender based on the first name.\nconst url = `https://api.genderize.io?name=${user.firstName}`;\n\nconsole.log(`Fetching external data for ${user.firstName} from ${url}`)\n\n// this.helpers.httpRequest is a powerful built-in function.\n// We use 'await' because it's an asynchronous operation.\nconst response = await this.helpers.httpRequest({ url: url, json: true });\n\n// 3. Return the original data merged with the new API data\nreturn {\n  ...user, // Keep all existing data (fullName, age, etc.)\n  gender: response.gender,\n  genderProbability: response.probability\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "809e91c4-02b6-4d12-b8f0-e9cd96d92c24",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        448,
        240
      ],
      "parameters": {
        "color": 5,
        "width": 440,
        "height": 420,
        "content": "#### \u25b6\ufe0f STARTING POINT: Sample Data\n\nThese nodes prepare our data for the tutorial.\n\n1.  **`1. Sample Data`**: Creates a list of users. Feel free to edit the values here to experiment!\n2.  **`2. Split Out Users`**: Splits the list into multiple items, one for each user. This is necessary so the next Code nodes can process them one by one."
      },
      "typeVersion": 1
    },
    {
      "id": "bc8ec047-8595-4a07-8422-09779f8490c0",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        912,
        80
      ],
      "parameters": {
        "color": 7,
        "width": 380,
        "height": 580,
        "content": "#### \u2699\ufe0f LESSON 1: Processing Each Item\n\nThis node is in **\"Run Once for Each Item\"** mode. It executes once for every user.\n\n**Goal:** Enrich each user's data.\n\n**Key Concepts:**\n*   `$input.item.json`: Accesses the data of the *current* item being processed.\n*   `return { ... }`: Returns an object that becomes the new output for the item. The `...user` trick keeps the original data.\n\n\nRun the workflow and check this node's output: you'll see multiple items, each with a new `fullName` and `age`."
      },
      "typeVersion": 1
    },
    {
      "id": "acd0b48a-ca88-4dae-ab19-b91db5050e8b",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1312,
        64
      ],
      "parameters": {
        "color": 6,
        "width": 380,
        "height": 600,
        "content": "#### \ud83d\ude80 ADVANCED LESSON 2: Using Helpers\n\nThis node also runs for each item, but demonstrates a powerful, advanced feature.\n\n**Goal:** Enrich data by calling an external API from code.\n\n**Key Concepts:**\n*   `this.helpers.httpRequest`: A built-in function to make API calls directly. This is great for dynamic URLs or when you need to add logic before or after the call.\n*   `await`: We use this because making an API call is an *asynchronous* operation.\n\n\nCheck the output: each user now has `gender` data fetched from the web!"
      },
      "typeVersion": 1
    },
    {
      "id": "da000098-d03f-40a9-b017-fab8223a6afc",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1712,
        80
      ],
      "parameters": {
        "color": 7,
        "width": 380,
        "height": 580,
        "content": "#### \u2699\ufe0f LESSON 3: Processing All Items at Once\n\nThis node is in **\"Run Once for All Items\"** mode. It runs only once and sees all items at the same time.\n\n**Goal:** Aggregate data to create a summary.\n\n**Key Concepts:**\n*   `$items()`: Returns an **array** of all items from the previous node.\n*   `return [ { json: { ... } } ]`: Returns an array containing a single new item with the final result.\n\n\nCheck this node's output: there is only one item containing the total user count and their average age."
      },
      "typeVersion": 1
    },
    {
      "id": "5c84ce9f-32d0-4222-9b1a-3887677bdabe",
      "name": "6. Create a Binary File (Expert)",
      "type": "n8n-nodes-base.code",
      "position": [
        2240,
        480
      ],
      "parameters": {
        "jsCode": "// LESSON 4 (EXPERT): Creating a binary file.\n\n// This node runs only ONCE for ALL items.\n\n// 1. Get all items from the previous node\nconst allUsers = $(\"4. Fetch External Data (Advanced)\").all();\n\n// 2. Create a CSV string from the data\nlet csvContent = \"FullName,Age,GenderGuess,ProcessedBy\\n\"; // CSV Header\n\nfor (const item of allUsers) {\n  const user = item.json;\n  const row = `\"${user.fullName}\",${user.age},${user.gender},n8n`;\n  csvContent += row + \"\\n\";\n}\n\n// 3. Use a helper to create a binary file from the string\nconst binaryData = await this.helpers.prepareBinaryData(Buffer.from(csvContent), 'user_report.csv');\n\n// 4. Return a new item containing the binary data\nreturn [\n  {\n    json: {\n      reportGenerated: new Date().toISOString(),\n      userCount: allUsers.length\n    },\n    binary: {\n      'report': binaryData\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "498b1bf2-1ced-4343-b459-9b6226fa8c46",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2112,
        80
      ],
      "parameters": {
        "color": 3,
        "width": 380,
        "height": 580,
        "content": "#### \ud83d\udcc4 EXPERT LESSON 4: Creating Files\n\n**Goal:** Aggregate all items and generate a binary file (like a CSV in that case).\n**Mode:** `Run Once for All Items`\n\n**Key Concepts:**\n*   `$(\"4. Fetch External Data (Advanced)\").all()`: Gets an array of ALL items from the 4th step.\n*   `this.helpers.prepareBinaryData`: Converts raw data (like a text string) into a proper binary file that n8n can use.\n*   `Buffer`: A standard way to handle binary data in JavaScript."
      },
      "typeVersion": 1
    },
    {
      "id": "c97edb6b-77ac-48ea-8e00-507770cc6373",
      "name": "Start Tutorial",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        224,
        480
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "860eb05c-710d-442b-9c9b-ab6c68e629aa",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2512,
        -432
      ],
      "parameters": {
        "color": 7,
        "width": 528,
        "height": 1088,
        "content": "## Was this helpful? Let me know!\n[![clic](https://supastudio.ia2s.app/storage/v1/object/public/assets/n8n/clic_down_lucas.gif)](https://workflows.ac/form)\n\nI really hope this template helped you. Your feedback is what helps me create better resources for the n8n community.\n\n### **Have Feedback, a Question, or a Project Idea?**\n\n\n#### \u27a1\ufe0f **[Click here to go to the Contact Form](https://workflows.ac/form?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=learn_code_node_java_script_with_an_interactive_hands_on_tutorial&utm_content=5407)**\n\nUse this single link for anything you need:\n\n*   **Give Feedback:** Share your thoughts on this template, whether you found a typo, encountered an unexpected error, have a suggestion, or just want to say thanks!\n\n*   **Automation Coaching:** Get personalized, one-on-one guidance to master n8n. We can work together to help you reach an expert level.\n\n*   **Automation Consulting:** Have a complex business challenge or need custom workflows built from scratch? We offer a plug and play automation department for 8 to 88 people teams with unlimited automation requests.\n\n---\n\nHappy Automating!\nLucas Peyrin | [Workflows Accelerator](https://workflows.ac?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=learn_code_node_java_script_with_an_interactive_hands_on_tutorial&utm_content=5407)"
      },
      "typeVersion": 1
    },
    {
      "id": "296e04dc-ba58-4477-b2d7-21871db660be",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -336,
        -64
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 736,
        "content": "## \ud83e\udd16 Mastering the n8n Code Node: The Ultimate Tutorial\n\nUnlock the full potential of custom logic in n8n with this step-by-step masterclass, designed to take you from basic JavaScript manipulation to advanced API calls and file generation.\n\n**How it works**\n\n*   **Data Preparation**: Starts with sample user data and splits it to demonstrate item-by-item processing.\n*   **Per-Item Logic**: Teaches you how to manipulate JSON (calculating age) and use internal helpers to fetch external data (guessing gender via API) for each specific user.\n*   **Data Aggregation**: Shows how to switch to \"Run Once for All Items\" mode to calculate global statistics, such as the average age of the group.\n*   **File Generation (Expert)**: Demonstrates how to programmatically create a binary CSV file from your data using code buffers.\n\n---\n\n### Automate your operations today\nYour time is valuable. Let us automate the boring stuff for you.\n\n**\ud83d\udc47 CHOOSE YOUR PATH:**\n\n[ **\u26a1\ufe0f I WANT A FREE AUDIT (2 min)** ](https://workflows.ac/audit?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=learn_code_node_java_script_with_an_interactive_hands_on_tutorial&utm_content=5407)\n> *We've put our heart into this business evaluation machine.*\n\n[ **\ud83d\udca1 I HAVE A SPECIFIC REQUEST** ](https://workflows.ac/form?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=learn_code_node_java_script_with_an_interactive_hands_on_tutorial&utm_content=5407)\n\n\n---\n\n*Happy Automating!*\n\nLucas Peyrin | [Workflows Accelerator](https://workflows.ac?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=learn_code_node_java_script_with_an_interactive_hands_on_tutorial&utm_content=5407)"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "1. Sample Data": {
      "main": [
        [
          {
            "node": "2. Split Out Users",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start Tutorial": {
      "main": [
        [
          {
            "node": "1. Sample Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2. Split Out Users": {
      "main": [
        [
          {
            "node": "3. Process Each User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3. Process Each User": {
      "main": [
        [
          {
            "node": "4. Fetch External Data (Advanced)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5. Calculate Average Age": {
      "main": [
        [
          {
            "node": "6. Create a Binary File (Expert)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4. Fetch External Data (Advanced)": {
      "main": [
        [
          {
            "node": "5. Calculate Average Age",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}