This workflow corresponds to n8n.io template #8206 — we link there as the canonical source.
This workflow follows the Agent → Chainllm recipe pattern — see all workflows that pair these two integrations.
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 →
{
"id": "ile4IWJUcJlAyxCJ",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Group toolbar items",
"tags": [],
"nodes": [
{
"id": "43fda72d-029f-4e2a-bc33-29fed6f6e7d5",
"name": "On form submission",
"type": "n8n-nodes-base.formTrigger",
"position": [
0,
-80
],
"parameters": {
"options": {},
"formTitle": "Icon submission",
"formFields": {
"values": [
{
"fieldType": "file",
"fieldLabel": "The screen",
"multipleFiles": false,
"requiredField": true
},
{
"fieldType": "file",
"fieldLabel": "Icons",
"requiredField": true
}
]
},
"formDescription": "Please upload:\n- the screen;\n- the set of icons for the screen."
},
"typeVersion": 2.3
},
{
"id": "115e9569-3b26-4533-82b6-34cee976cf72",
"name": "Gemini",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
224,
64
],
"parameters": {
"options": {}
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "c6901892-b4b8-4636-a0aa-4df78bba6c46",
"name": "Gemini: Reordering",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
816,
64
],
"parameters": {
"options": {}
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "bcf6195d-7d67-4c0d-8095-77ec8d9202e5",
"name": "Google Gemini Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
1376,
48
],
"parameters": {
"options": {}
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "12e987da-a185-469e-b831-9b70c336aa7b",
"name": "Code: Clean Outcome",
"type": "n8n-nodes-base.code",
"position": [
576,
-80
],
"parameters": {
"jsCode": "// Get the input data from the previous node\nconst input = $json[\"output\"]; // This contains the string with ```json ... ```\n\n// Remove the ```json wrapper\nconst jsonString = input.replace(/```json|```/g, '').trim();\n\n// Parse the JSON string\nconst data = JSON.parse(jsonString);\n\n// Return each part separately in n8n\nreturn [\n {\n json: {\n screen: data.Screen,\n groups: data.Groups,\n placement: data.Placement\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "52ff450a-8710-4807-87df-40f97f954968",
"name": "UI Guidance",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
1376,
-80
],
"parameters": {
"text": "=You are given icon filenames, their groups, and their screen placements:\n\n```json\n{{ $('AI Agent: Icon Categorizer').item.json.output }}\n```\n\n**Task:**\n\n1. Read and follow the Apple Human Interface Guidelines for toolbars:\n [https://developer.apple.com/design/human-interface-guidelines/toolbars]\n2. Based on these guidelines and the provided icon data, create a **full structured design proposal** for arranging and organizing the icons in the UI.\n",
"batching": {},
"promptType": "define"
},
"typeVersion": 1.7
},
{
"id": "bbe240ae-2728-4af8-ba05-1ce341884a86",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-80,
-208
],
"parameters": {
"height": 400,
"content": "## Get the screen"
},
"typeVersion": 1
},
{
"id": "84fcb22a-1dfb-4c78-8ceb-8971c2366aa2",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
208,
-208
],
"parameters": {
"color": 4,
"width": 544,
"height": 400,
"content": "## Analysing the screen and icons to categories them"
},
"typeVersion": 1
},
{
"id": "bb48382b-a1cf-432e-b6f3-963a14fa14b5",
"name": "AI Agent: Icon Categorizer",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
224,
-80
],
"parameters": {
"text": "=The form receives the screen context and a set of icons.\n\nScreen: {{ $json['The screen'].filename }}\nIcons: {{ JSON.stringify($json.Icons) }}\n\nYour task:\n1. Analyze the screen context.\n2. Group each icon into one of the following roles (from Apple HIG) based on the uploaded screen:\n - .primaryAction\n - .secondaryAction\n - .confirmationAction\n - .destructiveAction\n - .cancellationAction\n - .navigation\n - .navigationBarLeading\n - .navigationBarTrailing\n - .principal\n - .bottomBar\n - .status\n - .automatic\n - .keyboard\n\n3. After grouping the icons by role, assign their **placement** as follows:\n\n* **Left (Leading):**\n - .navigation\n - .navigationBarLeading\n - .cancellationAction\n\n* **Right (Trailing):**\n - .primaryAction\n - .secondaryAction\n - .confirmationAction\n - .destructiveAction\n - .navigationBarTrailing\n\n* **Center:**\n - .principal\n\n* **Bottom:**\n - .bottomBar\n - .status\n - .keyboard\n\n* **System-decided:**\n - .automatic\n\nOutput strictly in JSON format:\n{\n \"Screen\": \"<Describe the screen>\",\n \"Groups\": {\n \"<RoleName01>\": [\"iconName01\", \"iconName02\"],\n \"<RoleName02>\": [\"iconName03\"]\n },\n \"Placement\": {\n \"Left\": [\"iconName01\", \"iconName02\"],\n \"Right\": [\"iconName01\", \"iconName02\"],\n \"Center\": [\"iconName01\", \"iconName02\"],\n \"Bottom\": [\"iconName01\", \"iconName02\"],\n \"System-decided\": [\"iconName01\", \"iconName02\"]\n }\n}\n",
"options": {},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "547e0c7d-227f-4d4f-b9ee-05044c090d0b",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
768,
-208
],
"parameters": {
"color": 7,
"width": 544,
"height": 400,
"content": "## Reordering based on the usage"
},
"typeVersion": 1
},
{
"id": "0c9a268d-8d31-4f9b-b227-3f2457765b9f",
"name": "Code: Clean Outcomes",
"type": "n8n-nodes-base.code",
"position": [
1136,
-80
],
"parameters": {
"jsCode": "// Get the text field from input\nconst input = items[0].json.text;\n\n// Remove code block markers (```json ... ```)\nconst cleaned = input.replace(/```json\\n?/, '').replace(/```$/, '').trim();\n\n// Parse into object\nconst parsed = JSON.parse(cleaned);\n\n// Return in n8n format\nreturn [\n {\n json: parsed\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "99007016-102a-4ca3-8009-42662830a34d",
"name": "Basic LLM Chain: Reordering",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
816,
-80
],
"parameters": {
"text": "=You are given sets of icon filenames for different screen placements:\n\n```json\n{\n \"Left\": {{ $json.placement.Left }},\n \"Right\": {{ $json.placement.Right }},\n \"Center\": {{ $json.placement.Center }},\n \"Bottom\": {{ $json.placement.Bottom }},\n \"System-decided\": {{ $json.placement[\"System-decided\"] }}\n}\n```\n\n**Task:**\n\n1. For each placement (Left, Right, Center, Bottom, System-decided), reorder the icons by typical usage frequency in applications (web, desktop, mobile), from most used (left) to least used (right).\n2. If a placement has no icons, return an empty array.\n3. Return the final result as a JSON object with the same keys (`Left`, `Right`, `Center`, `Bottom`, `System-decided`) and the arrays of filenames in order.\n4. Do not include explanations or extra text.",
"batching": {},
"promptType": "define"
},
"typeVersion": 1.7
},
{
"id": "96d48453-28d1-485d-90c1-758009df78e2",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1328,
-208
],
"parameters": {
"color": 3,
"width": 384,
"height": 400,
"content": "## Full structured design proposa"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "317ce80f-d844-493f-b288-ccec91a874cf",
"connections": {
"Gemini": {
"ai_languageModel": [
[
{
"node": "AI Agent: Icon Categorizer",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"UI Guidance": {
"main": [
[]
]
},
"Gemini: Reordering": {
"ai_languageModel": [
[
{
"node": "Basic LLM Chain: Reordering",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"On form submission": {
"main": [
[
{
"node": "AI Agent: Icon Categorizer",
"type": "main",
"index": 0
}
]
]
},
"Code: Clean Outcome": {
"main": [
[
{
"node": "Basic LLM Chain: Reordering",
"type": "main",
"index": 0
}
]
]
},
"Code: Clean Outcomes": {
"main": [
[
{
"node": "UI Guidance",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "UI Guidance",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"AI Agent: Icon Categorizer": {
"main": [
[
{
"node": "Code: Clean Outcome",
"type": "main",
"index": 0
}
]
]
},
"Basic LLM Chain: Reordering": {
"main": [
[
{
"node": "Code: Clean Outcomes",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
googlePalmApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
When designing user interfaces, toolbar icons often get overlooked, even though their placement and grouping dramatically impact usability and user flow. This workflow leverages Gemini AI to automatically analyze UI screens, classify toolbar icons based on Apple’s Human…
Source: https://n8n.io/workflows/8206/ — 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.
It uses the Bright Data community node and Bright Data MCP for scraping and AI message generation. Form Submission
This n8n template automates complaint mining from unstructured text sources and turns raw user feedback into clear, actionable insights. It uses AI to identify recurring complaints, pain points, and t
The Recap AI - Gmail Agent. Uses formTrigger, httpRequest, chainLlm, gmailTrigger. Event-driven trigger; 24 nodes.
This workflow is a content multiplier. Provide a single video topic via a form, and it automatically researches, outlines, and writes two separate scripts: one for a YouTube Shorts and another for a L
The Recap AI - Whats App Chatbot Agent. Uses formTrigger, agent, lmChatGoogleGemini, toolThink. Event-driven trigger; 19 nodes.