This workflow follows the Form Trigger → Gmail 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 →
{
"name": "Generate three recipes using AI for quick meal options",
"nodes": [
{
"parameters": {
"content": "## \ud83c\udf73 Lazy Chef: AI Recipe Generator\n\nTurn fridge leftovers into a feast. This workflow accepts ingredients (via **Form**), uses **Gemini** to generate 3 distinct recipe styles (Speed, Healthy, Creative), fetches images via **Google Search**, saves them to **Sheets**, and emails you a menu.\n\n## How it works\n1. **Input:** Submit ingredients via n8n Form or use Test Mode.\n - *Includes a **Test Mode** to simulate \"Eggs, Milk, Tomato\" input.*\n2. **Generate:** Gemini creates 3 recipes based on your mood and ingredients.\n3. **Visuals:** Searches Google Images for a matching photo for each dish.\n4. **Deliver:** Aggregates everything into a beautiful HTML email.\n\n## Setup steps\n1. **Connect:** Gemini, Google Custom Search, Sheets, Gmail.\n2. **Config:** Open **\"Config\"** to set API Keys and Sheet ID.\n3. **Test:** Set `TEST_MODE` to `true` to generate mock recipes instantly.",
"height": 360,
"width": 500,
"color": 3
},
"id": "sticky-main",
"name": "Sticky Note - Main",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-380,
240
]
},
{
"parameters": {
"content": "## \u2699\ufe0f Configuration\nSet APIs & IDs.",
"height": 140,
"width": 240,
"color": 6
},
"id": "sticky-config",
"name": "Sticky Note - Config",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-380,
640
]
},
{
"parameters": {
"content": "## \ud83e\udd55 Ingredient Input\nForm or Mock Data.",
"height": 140,
"width": 700,
"color": 6
},
"id": "sticky-input",
"name": "Sticky Note - Input",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
180,
240
]
},
{
"parameters": {
"content": "## \ud83d\udc68\u200d\ud83c\udf73 AI Chef\nGenerates 3 variations.",
"height": 140,
"width": 440,
"color": 6
},
"id": "sticky-ai",
"name": "Sticky Note - AI",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
920,
240
]
},
{
"parameters": {
"content": "## \ud83d\uddbc\ufe0f Visuals & DB\nFetches images & Logs.",
"height": 340,
"width": 500,
"color": 6
},
"id": "sticky-visuals",
"name": "Sticky Note - Visuals",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
1400,
240
]
},
{
"parameters": {
"content": "## \ud83d\udce7 Menu Delivery\nSends HTML email.",
"height": 140,
"width": 380,
"color": 6
},
"id": "sticky-email",
"name": "Sticky Note - Email",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
1940,
240
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "id-1",
"name": "sheetId",
"value": "",
"type": "string"
},
{
"id": "id-2",
"name": "googleSearchApiKey",
"value": "",
"type": "string"
},
{
"id": "id-3",
"name": "googleSearchEngineId",
"value": "",
"type": "string"
},
{
"id": "id-4",
"name": "TEST_MODE",
"value": "true",
"type": "string"
},
{
"id": "id-5",
"name": "USER_EMAIL",
"value": "me@example.com",
"type": "string"
}
]
},
"options": {}
},
"id": "config-node",
"name": "Config",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-360,
700
]
},
{
"parameters": {
"formTitle": "\ud83c\udf73 Lazy Chef - Recipe Generator",
"formDescription": "Enter your fridge leftovers.",
"formFields": {
"values": [
{
"fieldLabel": "Ingredients",
"placeholder": "e.g., Eggs, Milk, Leftover Rice",
"requiredField": true
},
{
"fieldLabel": "Current Mood",
"defaultValue": "Hungry!",
"requiredField": true
},
{
"fieldLabel": "Your Email",
"fieldType": "email",
"requiredField": true
}
]
},
"options": {
"buttonLabel": "Generate Recipes"
}
},
"id": "form-trigger",
"name": "Ingredient Form",
"type": "n8n-nodes-base.formTrigger",
"typeVersion": 2.3,
"position": [
220,
400
]
},
{
"parameters": {
"options": {}
},
"id": "manual-trigger",
"name": "Manual Trigger",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-600,
700
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "is_test",
"leftValue": "={{ $('Config').first().json.TEST_MODE }}",
"rightValue": "true",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "check-mode",
"name": "Test Mode?",
"type": "n8n-nodes-base.switch",
"typeVersion": 3.2,
"position": [
220,
200
]
},
{
"parameters": {
"jsCode": "// Generate Mock Input\nreturn [{\n json: {\n Ingredients: \"Eggs, Milk, Tomato, Old Bread\",\n \"Current Mood\": \"Need energy\",\n \"Your Email\": \"test@example.com\"\n }\n}];"
},
"id": "mock-input",
"name": "Mock Input",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
460,
200
]
},
{
"parameters": {
"jsCode": "// Unify Inputs\nconst items = $input.all();\nconst inputData = items[0].json;\n\nreturn [{\n json: {\n Ingredients: inputData.Ingredients || \"Unknown\",\n Mood: inputData['Current Mood'] || \"Normal\",\n Email: inputData['Your Email'] || $('Config').first().json.USER_EMAIL\n }\n}];"
},
"id": "normalize-input",
"name": "Normalize Input",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
700,
300
]
},
{
"parameters": {
"modelId": {
"__rl": true,
"value": "models/gemini-1.5-flash",
"mode": "list",
"cachedResultName": "models/gemini-1.5-flash"
},
"messages": {
"values": [
{
"content": "=You are a master chef.\nGenerate 3 distinct recipe styles based on ingredients: {{ $json.Ingredients }}\n\n1. Speed (5 min)\n2. Healthy (Low cal)\n3. Creative (Unexpected)\n\n[Output JSON Array ONLY]\n[\n { \"style\": \"Speed\", \"recipe_name\": \"...\", \"search_query\": \"Dish Name\", \"recipe_text\": \"...\" },\n ...\n]"
}
]
},
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.googleGemini",
"typeVersion": 1,
"position": [
960,
300
],
"id": "gemini-generate",
"name": "Gemini: Generate Recipes",
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// Parse Gemini output\nconst text = $input.first().json.content.parts[0].text;\nlet recipes = [];\ntry {\n const cleanText = text.replace(/```json/g, '').replace(/```/g, '').trim();\n recipes = JSON.parse(cleanText);\n} catch (e) {\n recipes = [{ style: \"Error\", recipe_name: \"Failed\", search_query: \"Food\", recipe_text: \"Error\" }];\n}\nreturn recipes;"
},
"id": "split-items",
"name": "Split into Items",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1180,
300
]
},
{
"parameters": {
"url": "https://www.googleapis.com/customsearch/v1",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "={{ $json.search_query }}"
},
{
"name": "cx",
"value": "={{ $('Config').first().json.googleSearchEngineId }}"
},
{
"name": "key",
"value": "={{ $('Config').first().json.googleSearchApiKey }}"
},
{
"name": "searchType",
"value": "image"
},
{
"name": "num",
"value": "1"
}
]
},
"options": {}
},
"id": "image-search",
"name": "Google Image Search",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
1440,
200
]
},
{
"parameters": {
"operation": "appendOrUpdate",
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Config').first().json.sheetId }}"
},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Recipes"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"date": "={{ $now.format('yyyy-MM-dd HH:mm') }}",
"style": "={{ $json.style }}",
"recipe_name": "={{ $json.recipe_name }}",
"image_url": "={{ $('Google Image Search').item.json.items[0].link }}"
}
},
"options": {}
},
"id": "save-sheet",
"name": "Save to Sheets",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
1660,
300
],
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// Aggregate to HTML\nconst items = $input.all();\nlet html = \"<h2>\ud83c\udf73 Your 3 Recipe Proposals</h2><hr>\";\nitems.forEach(item => {\n const d = item.json;\n const img = $('Google Image Search').item.json.items[0].link || \"\";\n html += `<h3>${d.style}: ${d.recipe_name}</h3><img src='${img}' width='200'><p>${d.recipe_text}</p>`;\n});\nreturn { json: { emailBody: html, recipient: $('Normalize Input').first().json.Email } };"
},
"id": "aggregate-html",
"name": "Aggregate to HTML",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1800,
460
]
},
{
"parameters": {
"sendTo": "={{ $json.recipient }}",
"subject": "\ud83c\udf73 Your AI Recipe Menu",
"emailType": "text",
"message": "={{ $json.emailBody }}",
"options": {}
},
"id": "send-email",
"name": "Send Email",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
2000,
300
],
"credentials": {
"gmailOAuth2Api": {
"name": "<your credential>"
}
}
}
],
"connections": {
"Config": {
"main": [
[
{
"node": "Test Mode?",
"type": "main",
"index": 0
}
]
]
},
"Manual Trigger": {
"main": [
[
{
"node": "Config",
"type": "main",
"index": 0
}
]
]
},
"Test Mode?": {
"main": [
[
{
"node": "Mock Input",
"type": "main",
"index": 0
}
],
[
{
"node": "Ingredient Form",
"type": "main",
"index": 0
}
]
]
},
"Mock Input": {
"main": [
[
{
"node": "Normalize Input",
"type": "main",
"index": 0
}
]
]
},
"Ingredient Form": {
"main": [
[
{
"node": "Normalize Input",
"type": "main",
"index": 0
}
]
]
},
"Normalize Input": {
"main": [
[
{
"node": "Gemini: Generate Recipes",
"type": "main",
"index": 0
}
]
]
},
"Gemini: Generate Recipes": {
"main": [
[
{
"node": "Split into Items",
"type": "main",
"index": 0
}
]
]
},
"Split into Items": {
"main": [
[
{
"node": "Google Image Search",
"type": "main",
"index": 0
},
{
"node": "Save to Sheets",
"type": "main",
"index": 0
}
]
]
},
"Google Image Search": {
"main": [
[
{
"node": "Save to Sheets",
"type": "main",
"index": 0
}
]
]
},
"Save to Sheets": {
"main": [
[
{
"node": "Aggregate to HTML",
"type": "main",
"index": 0
}
]
]
},
"Aggregate to HTML": {
"main": [
[
{
"node": "Send Email",
"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.
gmailOAuth2ApigooglePalmApigoogleSheetsOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Generate three recipes using AI for quick meal options. Uses formTrigger, googleGemini, httpRequest, googleSheets. Event-driven trigger; 18 nodes.
Source: https://github.com/alternativescom/n8n-automation-workflows/blob/main/08-ai-recipe-generator/workflow.json — 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.
Understand your customers before you build for them. This workflow, Market Segmentation: Buyer Persona Pain Point Report, automates the grueling process of primary market research. By scraping real-wo
The competitive edge, delivered. This Customer Intelligence Engine simultaneously analyzes the web, Reddit, and X/Twitter to generate a professional, actionable executive briefing.
following up on every lead by hand is slow, inconsistent, and lets good opportunities slip. by the time you read a form submission, write a reply, and figure out what to do next — the lead has moved o
This workflow automatically generates and sends personalized client emails using portfolio data and live market trends. It fetches client details from Google Sheets, retrieves market news via API, fil
Smart Lead Scraper: Keyword to Sales List. Uses formTrigger, httpRequest, googleGemini, googleSheets. Event-driven trigger; 15 nodes.