This workflow corresponds to n8n.io template #5407 — we link there as the canonical source.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"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[](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
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow is a hands-on tutorial for the Code node in n8n, covering both basic and advanced concepts through a simple data processing task. Provides Sample Data: The workflow begins with a sample list of users. Processes Each Item (): The first Code node iterates through…
Source: https://n8n.io/workflows/5407/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Blotato. Uses googleSheets, @blotato/n8n-nodes-blotato. Event-driven trigger; 65 nodes.
This template is a hands-on, practical exam designed to help you master n8n Expressions—the key to accessing and manipulating data in your workflows.
This template is a hands-on, practical exam designed to test your understanding of the fundamental JSON data types. It's the perfect way to solidify your knowledge after learning the basics.
Agendamiento. Uses n8n-nodes-evolution-api, redis, dataTable, executeWorkflowTrigger. Event-driven trigger; 60 nodes.
Kv Cloudflare Key Value Database Full Api Integration Workflow. Uses stickyNote, httpRequest, manualTrigger. Event-driven trigger; 47 nodes.