{
  "id": 12263,
  "name": "Generate illustrated stories with GPT-4, DALL-E 3 and Firebase",
  "description": "Generate complete illustrated stories using AI. This workflow creates engaging narratives with custom DALL-E 3 images for each scene and saves everything to Firebase.\n\n**How it works**\n1. User fills out a form with story topic, language, art style, and number of scenes\n2. GPT-4 generates a complete story with scenes, characters, and image prompts\n3. DALL-E 3 creates unique illustrations for each scene\n4. Images are uploaded to Firebase Storage for permanent hosting\n5. Complete story data is saved to Firestore\n6. Returns JSON with the full story and image URLs\n\n**Set up steps** (10-15 minutes)\n1. Add your OpenAI API credentials\n2. Add Google Service Account credentials for Firebase\n3. Update 3 variables in the Code nodes: `OPENAI_API_KEY`, `FIREBASE_BUCKET`, `FIREBASE_PROJECT_ID`\n4. Activate and test with the form\n\n**Features**\n- 12 languages supported\n- 10 art styles to choose from\n- 1-12 scenes per story\n- Automatic image hosting on Firebase\n- Full story saved to Firestore database",
  "categories": [
    {
      "id": 31,
      "name": "Content Creation"
    },
    {
      "id": 51,
      "name": "Multimodal AI"
    }
  ],
  "totalViews": 143,
  "createdAt": "2025-12-29T11:47:41.067Z",
  "workflow": {
    "meta": {
      "instanceId": "5a736234c697011c98e45cbb42e3fa6c7274e8d2737d845f99ebfa424b5a19fa"
    },
    "nodes": [
      {
        "id": "fce5d967-5e3e-431a-a6e3-41c42fb07c0d",
        "name": "Sticky Note",
        "type": "n8n-nodes-base.stickyNote",
        "position": [
          -1088,
          -400
        ],
        "parameters": {
          "width": 420,
          "height": 712,
          "content": "## AI Illustrated Story Generator with DALL-E 3 & Firebase\n\nGenerate complete illustrated stories using AI. This workflow creates engaging narratives with custom DALL-E 3 images for each scene and saves everything to Firebase.\n\n**How it works**\n1. User fills out a form with story topic, language, art style, and number of scenes\n2. GPT-4 generates a complete story with scenes, characters, and image prompts\n3. DALL-E 3 creates unique illustrations for each scene\n4. Images are uploaded to Firebase Storage for permanent hosting\n5. Complete story data is saved to Firestore\n6. Returns JSON with the full story and image URLs\n\n**Set up steps** (10-15 minutes)\n1. Add your OpenAI API credentials\n2. Add Google Service Account credentials for Firebase\n3. Update 3 variables in the Code nodes: `OPENAI_API_KEY`, `FIREBASE_BUCKET`, `FIREBASE_PROJECT_ID`\n4. Activate and test with the form\n\n**Features**\n- 12 languages supported\n- 10 art styles to choose from\n- 1-12 scenes per story\n- Automatic image hosting on Firebase\n- Full story saved to Firestore database"
        },
        "typeVersion": 1
      },
      {
        "id": "32048eef-00c4-4bb4-a5e2-e20c95731849",
        "name": "Sticky Note1",
        "type": "n8n-nodes-base.stickyNote",
        "position": [
          -640,
          -192
        ],
        "parameters": {
          "color": 7,
          "width": 260,
          "height": 308,
          "content": "**Step 1: Form Input**\nCollects story topic, language, art style, number of scenes (1-12), audience, and mood."
        },
        "typeVersion": 1
      },
      {
        "id": "0927bacb-1dfb-4768-ad4e-11804cc211bd",
        "name": "Sticky Note2",
        "type": "n8n-nodes-base.stickyNote",
        "position": [
          -352,
          -192
        ],
        "parameters": {
          "color": 7,
          "width": 200,
          "height": 308,
          "content": "**Step 2: Validate**\nEnsures scene count is between 1-12. Generates unique story ID."
        },
        "typeVersion": 1
      },
      {
        "id": "11b0d4a3-5815-410e-a5a7-d93fbdc72666",
        "name": "Sticky Note3",
        "type": "n8n-nodes-base.stickyNote",
        "position": [
          -144,
          -192
        ],
        "parameters": {
          "color": 7,
          "height": 308,
          "content": "**Step 3: Generate Story**\nGPT-4 creates complete narrative with scenes, characters, and image prompts."
        },
        "typeVersion": 1
      },
      {
        "id": "d5acf7f1-6fa6-4329-9f03-add1fab4cf19",
        "name": "Sticky Note4",
        "type": "n8n-nodes-base.stickyNote",
        "position": [
          112,
          -192
        ],
        "parameters": {
          "color": 7,
          "width": 200,
          "height": 308,
          "content": "**Step 4: Prepare Data**\nSanitizes text and optimizes prompts for DALL-E 3."
        },
        "typeVersion": 1
      },
      {
        "id": "6bcdaedb-1fac-4cab-bdba-f73e981658be",
        "name": "Sticky Note5",
        "type": "n8n-nodes-base.stickyNote",
        "position": [
          336,
          -192
        ],
        "parameters": {
          "color": 7,
          "width": 200,
          "height": 308,
          "content": "**Step 5: DALL-E 3**\nGenerates one image per scene. ~15 sec each.\n"
        },
        "typeVersion": 1
      },
      {
        "id": "cd8a00fc-cf7a-497b-938a-77c8731a73b0",
        "name": "Sticky Note6",
        "type": "n8n-nodes-base.stickyNote",
        "position": [
          560,
          -192
        ],
        "parameters": {
          "color": 7,
          "width": 200,
          "height": 308,
          "content": "**Step 6: Upload**\nDownloads from DALL-E, uploads to Firebase Storage.\n"
        },
        "typeVersion": 1
      },
      {
        "id": "de464d9f-6e28-4196-aec6-08746e86a713",
        "name": "Sticky Note7",
        "type": "n8n-nodes-base.stickyNote",
        "position": [
          768,
          -192
        ],
        "parameters": {
          "color": 7,
          "width": 200,
          "height": 308,
          "content": "**Step 7: Finalize**\nCleans up data and prepares final story object."
        },
        "typeVersion": 1
      },
      {
        "id": "1ad4f85e-e2cb-4d2a-8c94-e59ac8d064cc",
        "name": "Sticky Note8",
        "type": "n8n-nodes-base.stickyNote",
        "position": [
          992,
          -192
        ],
        "parameters": {
          "color": 7,
          "width": 216,
          "height": 308,
          "content": "**Step 8: Firestore**\nSaves story to Firestore database.\n"
        },
        "typeVersion": 1
      },
      {
        "id": "2405a411-297f-46b0-b51b-16a101c3004c",
        "name": "Sticky Note9",
        "type": "n8n-nodes-base.stickyNote",
        "position": [
          1232,
          -192
        ],
        "parameters": {
          "color": 7,
          "width": 200,
          "height": 308,
          "content": "**Step 9: Response**\nReturns complete story JSON to the user."
        },
        "typeVersion": 1
      },
      {
        "id": "ddda96c6-4469-4c2d-acfb-bee04ec28cd2",
        "name": "Story Input Form",
        "type": "n8n-nodes-base.formTrigger",
        "position": [
          -592,
          -48
        ],
        "webhookId": "ai-story-generator-dalle",
        "parameters": {
          "options": {
            "respondWithOptions": {
              "values": {
                "formSubmittedText": "Your story is being created! This takes 2-5 minutes. Please wait..."
              }
            }
          },
          "formTitle": "AI Story Generator",
          "formFields": {
            "values": [
              {
                "fieldType": "textarea",
                "fieldLabel": "Story Topic",
                "placeholder": "Example: A brave little robot who learns the meaning of friendship when it helps a lost puppy find its way home through a magical forest...",
                "requiredField": true
              },
              {
                "fieldType": "dropdown",
                "fieldLabel": "Language",
                "fieldOptions": {
                  "values": [
                    {
                      "option": "English"
                    },
                    {
                      "option": "Spanish"
                    },
                    {
                      "option": "French"
                    },
                    {
                      "option": "German"
                    },
                    {
                      "option": "Portuguese"
                    },
                    {
                      "option": "Italian"
                    },
                    {
                      "option": "Japanese"
                    },
                    {
                      "option": "Chinese"
                    },
                    {
                      "option": "Korean"
                    },
                    {
                      "option": "Dutch"
                    },
                    {
                      "option": "Russian"
                    },
                    {
                      "option": "Arabic"
                    }
                  ]
                },
                "requiredField": true
              },
              {
                "fieldType": "dropdown",
                "fieldLabel": "Image Style",
                "fieldOptions": {
                  "values": [
                    {
                      "option": "Anime style, soft colors, kawaii aesthetic"
                    },
                    {
                      "option": "Watercolor illustration, classic storybook"
                    },
                    {
                      "option": "Studio Ghibli style, whimsical and detailed"
                    },
                    {
                      "option": "Disney/Pixar 3D animation style"
                    },
                    {
                      "option": "Minimalist flat illustration, modern"
                    },
                    {
                      "option": "Realistic digital painting"
                    },
                    {
                      "option": "Vintage children's book, nostalgic"
                    },
                    {
                      "option": "Comic book style, bold lines"
                    },
                    {
                      "option": "Dreamy fantasy art, ethereal"
                    },
                    {
                      "option": "Cute cartoon style, bright colors"
                    }
                  ]
                },
                "requiredField": true
              },
              {
                "fieldType": "number",
                "fieldLabel": "Number of Scenes",
                "placeholder": "4",
                "requiredField": true
              },
              {
                "fieldType": "dropdown",
                "fieldLabel": "Target Audience",
                "fieldOptions": {
                  "values": [
                    {
                      "option": "Toddlers (2-4 years)"
                    },
                    {
                      "option": "Young Children (5-7 years)"
                    },
                    {
                      "option": "Children (8-12 years)"
                    },
                    {
                      "option": "Teenagers (13-17 years)"
                    },
                    {
                      "option": "Young Adults"
                    },
                    {
                      "option": "Adults"
                    },
                    {
                      "option": "All Ages"
                    }
                  ]
                },
                "requiredField": true
              },
              {
                "fieldType": "dropdown",
                "fieldLabel": "Story Mood",
                "fieldOptions": {
                  "values": [
                    {
                      "option": "Happy and Fun"
                    },
                    {
                      "option": "Adventurous and Exciting"
                    },
                    {
                      "option": "Calm and Peaceful"
                    },
                    {
                      "option": "Mysterious and Intriguing"
                    },
                    {
                      "option": "Educational and Informative"
                    },
                    {
                      "option": "Funny and Silly"
                    },
                    {
                      "option": "Heartwarming and Emotional"
                    }
                  ]
                },
                "requiredField": true
              }
            ]
          },
          "formDescription": "Create an illustrated story with AI. Fill in the details and get a complete story with DALL-E 3 images for each scene. Generation takes 2-5 minutes."
        },
        "typeVersion": 2.3
      },
      {
        "id": "63a1bedb-00f8-42c4-b01f-c8036628985f",
        "name": "Validate Input",
        "type": "n8n-nodes-base.code",
        "position": [
          -320,
          -48
        ],
        "parameters": {
          "jsCode": "// Validate input and generate story ID\nconst formData = $input.first().json;\n\n// Validate number of scenes (1-12)\nlet numScenes = parseInt(formData['Number of Scenes']) || 4;\nif (numScenes < 1) numScenes = 1;\nif (numScenes > 12) numScenes = 12;\n\n// Generate unique story ID\nconst storyId = `story_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n\nreturn {\n  json: {\n    ...formData,\n    numScenes: numScenes,\n    storyId: storyId\n  }\n};"
        },
        "typeVersion": 2
      },
      {
        "id": "6a9a8aab-3dad-429b-a39c-563445e3671c",
        "name": "Generate Story (GPT-4)",
        "type": "n8n-nodes-base.httpRequest",
        "position": [
          -96,
          -48
        ],
        "parameters": {
          "url": "https://api.openai.com/v1/chat/completions",
          "method": "POST",
          "options": {},
          "jsonBody": "={\n  \"model\": \"gpt-4o\",\n  \"messages\": [\n    {\n      \"role\": \"system\",\n      \"content\": \"You are a master storyteller creating illustrated stories. Generate engaging narratives with vivid, DALL-E-friendly image prompts. Keep prompts concise but descriptive.\"\n    },\n    {\n      \"role\": \"user\",\n      \"content\": \"Create an illustrated story:\\n\\nTOPIC: {{ $json['Story Topic'] }}\\n\\nSPECS:\\n- Language: {{ $json.Language }}\\n- Scenes: {{ $json.numScenes }}\\n- Audience: {{ $json['Target Audience'] }}\\n- Mood: {{ $json['Story Mood'] }}\\n- Art style: {{ $json['Image Style'] }}\\n\\nRULES:\\n1. Exactly {{ $json.numScenes }} scenes\\n2. Write story text in {{ $json.Language }}\\n3. Image prompts in English, include art style\\n4. Age-appropriate content\\n5. Clear beginning, middle, end\"\n    }\n  ],\n  \"response_format\": {\n    \"type\": \"json_schema\",\n    \"json_schema\": {\n      \"name\": \"illustrated_story\",\n      \"strict\": true,\n      \"schema\": {\n        \"type\": \"object\",\n        \"additionalProperties\": false,\n        \"properties\": {\n          \"title\": { \"type\": \"string\" },\n          \"titleEnglish\": { \"type\": \"string\" },\n          \"summary\": { \"type\": \"string\" },\n          \"summaryEnglish\": { \"type\": \"string\" },\n          \"language\": { \"type\": \"string\" },\n          \"targetAudience\": { \"type\": \"string\" },\n          \"mood\": { \"type\": \"string\" },\n          \"moral\": { \"type\": \"string\" },\n          \"scenes\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"type\": \"object\",\n              \"additionalProperties\": false,\n              \"properties\": {\n                \"sceneNumber\": { \"type\": \"number\" },\n                \"title\": { \"type\": \"string\" },\n                \"text\": { \"type\": \"string\" },\n                \"textEnglish\": { \"type\": \"string\" },\n                \"imagePrompt\": { \"type\": \"string\" }\n              },\n              \"required\": [\"sceneNumber\", \"title\", \"text\", \"textEnglish\", \"imagePrompt\"]\n            }\n          },\n          \"characters\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"type\": \"object\",\n              \"additionalProperties\": false,\n              \"properties\": {\n                \"name\": { \"type\": \"string\" },\n                \"description\": { \"type\": \"string\" },\n                \"role\": { \"type\": \"string\" }\n              },\n              \"required\": [\"name\", \"description\", \"role\"]\n            }\n          }\n        },\n        \"required\": [\"title\", \"titleEnglish\", \"summary\", \"summaryEnglish\", \"language\", \"targetAudience\", \"mood\", \"moral\", \"scenes\", \"characters\"]\n      }\n    }\n  }\n}",
          "sendBody": true,
          "specifyBody": "json",
          "authentication": "predefinedCredentialType",
          "nodeCredentialType": "openAiApi"
        },
        "typeVersion": 4.3
      },
      {
        "id": "a1b2c17c-9433-43c8-a031-eba04f3d231d",
        "name": "Prepare Story Data",
        "type": "n8n-nodes-base.code",
        "position": [
          160,
          -48
        ],
        "parameters": {
          "jsCode": "// Prepare story data for image generation\nconst response = $input.first().json;\nconst formData = $('Validate Input').first().json;\nconst imageStyle = formData['Image Style'];\n\nconst story = JSON.parse(response.choices[0].message.content);\n\nfunction sanitize(text) {\n  if (!text) return '';\n  return text\n    .replace(/\\\\/g, '\\\\\\\\')\n    .replace(/\"/g, \"'\")\n    .replace(/\\n/g, ' ')\n    .replace(/\\r/g, '')\n    .replace(/\\t/g, ' ')\n    .replace(/[\\x00-\\x1F\\x7F]/g, '')\n    .trim();\n}\n\nconst preparedScenes = story.scenes.map((scene, index) => {\n  const dallePrompt = `${imageStyle}, children's book illustration: ${sanitize(scene.imagePrompt)}. High quality, vibrant colors, no text in image.`;\n  \n  return {\n    ...scene,\n    sceneIndex: index,\n    dallePrompt: dallePrompt.substring(0, 4000),\n    imageUrl: null\n  };\n});\n\nreturn {\n  json: {\n    story: { ...story, scenes: preparedScenes },\n    formData: formData,\n    storyId: formData.storyId,\n    totalScenes: preparedScenes.length,\n    createdAt: new Date().toISOString()\n  }\n};"
        },
        "typeVersion": 2
      },
      {
        "id": "8eaff9ca-1e46-444d-bceb-661799278aa9",
        "name": "Generate Images (DALL-E 3)",
        "type": "n8n-nodes-base.code",
        "position": [
          384,
          -48
        ],
        "parameters": {
          "jsCode": "// ========================================\n// GENERATE IMAGES WITH DALL-E 3\n// ========================================\n// Update OPENAI_API_KEY with your key or use credentials\n// ========================================\n\nconst data = $input.first().json;\nconst scenes = data.story.scenes;\n\n// \u26a0\ufe0f REPLACE WITH YOUR API KEY\nconst OPENAI_API_KEY = 'YOUR_OPENAI_API_KEY';\n\nconst processedScenes = [];\n\nfor (let i = 0; i < scenes.length; i++) {\n  const scene = scenes[i];\n  \n  try {\n    const response = await fetch('https://api.openai.com/v1/images/generations', {\n      method: 'POST',\n      headers: {\n        'Authorization': `Bearer ${OPENAI_API_KEY}`,\n        'Content-Type': 'application/json'\n      },\n      body: JSON.stringify({\n        model: 'dall-e-3',\n        prompt: scene.dallePrompt,\n        n: 1,\n        size: '1024x1024',\n        quality: 'standard',\n        response_format: 'url'\n      })\n    });\n    \n    const result = await response.json();\n    \n    if (result.error) {\n      processedScenes.push({\n        ...scene,\n        imageUrl: `https://placehold.co/1024x1024/ef4444/ffffff?text=Error`,\n        imageError: result.error.message\n      });\n    } else {\n      processedScenes.push({\n        ...scene,\n        imageUrl: result.data[0].url,\n        imageGeneratedAt: new Date().toISOString()\n      });\n    }\n    \n    // Rate limit: wait 1 second between requests\n    if (i < scenes.length - 1) {\n      await new Promise(resolve => setTimeout(resolve, 1000));\n    }\n    \n  } catch (error) {\n    processedScenes.push({\n      ...scene,\n      imageUrl: `https://placehold.co/1024x1024/ef4444/ffffff?text=Error`,\n      imageError: error.message\n    });\n  }\n}\n\nreturn {\n  json: {\n    story: { ...data.story, scenes: processedScenes },\n    formData: data.formData,\n    storyId: data.storyId,\n    totalScenes: data.totalScenes,\n    createdAt: data.createdAt\n  }\n};"
        },
        "typeVersion": 2
      },
      {
        "id": "46e5ffed-e608-45c0-9379-d09eb4d308f8",
        "name": "Upload to Firebase Storage",
        "type": "n8n-nodes-base.code",
        "position": [
          608,
          -48
        ],
        "parameters": {
          "jsCode": "// ========================================\n// UPLOAD IMAGES TO FIREBASE STORAGE\n// ========================================\n// Update FIREBASE_BUCKET with your bucket name\n// ========================================\n\nconst data = $input.first().json;\nconst scenes = data.story.scenes;\nconst storyId = data.storyId;\n\n// \u26a0\ufe0f REPLACE WITH YOUR FIREBASE BUCKET\nconst FIREBASE_BUCKET = 'your-project.appspot.com';\n\nconst uploadedScenes = [];\n\nfor (let i = 0; i < scenes.length; i++) {\n  const scene = scenes[i];\n  \n  if (scene.imageError || !scene.imageUrl || scene.imageUrl.includes('placehold.co')) {\n    uploadedScenes.push(scene);\n    continue;\n  }\n  \n  try {\n    // Download from DALL-E\n    const imageResponse = await fetch(scene.imageUrl);\n    const imageBuffer = await imageResponse.arrayBuffer();\n    \n    // Upload to Firebase\n    const storagePath = `stories/${storyId}/scene_${i}.png`;\n    const encodedPath = encodeURIComponent(storagePath);\n    \n    const uploadResponse = await fetch(\n      `https://firebasestorage.googleapis.com/v0/b/${FIREBASE_BUCKET}/o?name=${encodedPath}`,\n      {\n        method: 'POST',\n        headers: { 'Content-Type': 'image/png' },\n        body: Buffer.from(imageBuffer)\n      }\n    );\n    \n    const uploadResult = await uploadResponse.json();\n    \n    let firebaseUrl = uploadResult.downloadTokens\n      ? `https://firebasestorage.googleapis.com/v0/b/${FIREBASE_BUCKET}/o/${encodedPath}?alt=media&token=YOUR_TOKEN_HERE\n      : `https://firebasestorage.googleapis.com/v0/b/${FIREBASE_BUCKET}/o/${encodedPath}?alt=media`;\n    \n    uploadedScenes.push({ ...scene, imageUrl: firebaseUrl });\n    \n  } catch (error) {\n    uploadedScenes.push(scene);\n  }\n}\n\nreturn {\n  json: {\n    story: { ...data.story, scenes: uploadedScenes },\n    formData: data.formData,\n    storyId: data.storyId,\n    totalScenes: data.totalScenes,\n    createdAt: data.createdAt\n  }\n};"
        },
        "typeVersion": 2
      },
      {
        "id": "fac63dab-0dc1-4291-98a2-f887c192ca61",
        "name": "Finalize Story",
        "type": "n8n-nodes-base.code",
        "position": [
          816,
          -48
        ],
        "parameters": {
          "jsCode": "// Finalize story object\nconst data = $input.first().json;\n\nconst finalScenes = data.story.scenes.map(scene => {\n  const { sceneIndex, dallePrompt, imageError, ...cleanScene } = scene;\n  return cleanScene;\n});\n\nconst finalStory = {\n  id: data.storyId,\n  title: data.story.title,\n  titleEnglish: data.story.titleEnglish,\n  summary: data.story.summary,\n  summaryEnglish: data.story.summaryEnglish,\n  language: data.story.language,\n  targetAudience: data.story.targetAudience,\n  mood: data.story.mood,\n  moral: data.story.moral,\n  imageStyle: data.formData['Image Style'],\n  totalScenes: finalScenes.length,\n  scenes: finalScenes,\n  characters: data.story.characters,\n  metadata: {\n    createdAt: data.createdAt,\n    updatedAt: new Date().toISOString(),\n    generator: 'AI Story Generator',\n    originalPrompt: data.formData['Story Topic']\n  }\n};\n\nreturn {\n  json: {\n    finalStory: finalStory,\n    language: data.formData.Language.toLowerCase().replace(' ', '_')\n  }\n};"
        },
        "typeVersion": 2
      },
      {
        "id": "aa4481c0-ef84-4931-bbe5-0a2b046adace",
        "name": "Prepare Firestore Data",
        "type": "n8n-nodes-base.code",
        "position": [
          1040,
          -48
        ],
        "parameters": {
          "jsCode": "// ========================================\n// PREPARE FIRESTORE DOCUMENT\n// ========================================\n// Update FIREBASE_PROJECT_ID with your project ID\n// ========================================\n\nconst data = $input.first().json;\nconst story = data.finalStory;\n\n// \u26a0\ufe0f REPLACE WITH YOUR PROJECT ID\nconst FIREBASE_PROJECT_ID = 'your-project-id';\n\nfunction toFirestore(value) {\n  if (value === null || value === undefined) return { nullValue: null };\n  if (typeof value === 'boolean') return { booleanValue: value };\n  if (typeof value === 'number') {\n    return Number.isInteger(value) ? { integerValue: String(value) } : { doubleValue: value };\n  }\n  if (typeof value === 'string') return { stringValue: value };\n  if (Array.isArray(value)) {\n    return { arrayValue: { values: value.map(v => toFirestore(v)) } };\n  }\n  if (typeof value === 'object') {\n    const fields = {};\n    for (const [k, v] of Object.entries(value)) {\n      fields[k] = toFirestore(v);\n    }\n    return { mapValue: { fields } };\n  }\n  return { stringValue: String(value) };\n}\n\nconst docFields = {\n  id: toFirestore(story.id),\n  title: toFirestore(story.title),\n  titleEnglish: toFirestore(story.titleEnglish),\n  summary: toFirestore(story.summary),\n  summaryEnglish: toFirestore(story.summaryEnglish),\n  language: toFirestore(story.language),\n  targetAudience: toFirestore(story.targetAudience),\n  mood: toFirestore(story.mood),\n  moral: toFirestore(story.moral),\n  imageStyle: toFirestore(story.imageStyle),\n  totalScenes: toFirestore(story.totalScenes),\n  scenes: toFirestore(story.scenes),\n  characters: toFirestore(story.characters),\n  metadata: toFirestore(story.metadata),\n  createdAt: { timestampValue: new Date().toISOString() }\n};\n\nreturn {\n  json: {\n    body: { fields: docFields },\n    collection: `stories/${data.language}/items`,\n    docId: story.id,\n    projectId: FIREBASE_PROJECT_ID,\n    finalStory: story\n  }\n};"
        },
        "typeVersion": 2
      },
      {
        "id": "e48ee420-0e8e-4ab0-adf2-4794ece9cdb6",
        "name": "Save to Firestore",
        "type": "n8n-nodes-base.httpRequest",
        "position": [
          1264,
          -48
        ],
        "parameters": {
          "url": "=https://firestore.googleapis.com/v1/projects/{{ $json.projectId }}/databases/(default)/documents/{{ $json.collection }}/{{ $json.docId }}",
          "method": "PATCH",
          "options": {},
          "jsonBody": "={{ JSON.stringify($json.body) }}",
          "sendBody": true,
          "specifyBody": "json",
          "authentication": "predefinedCredentialType",
          "nodeCredentialType": "googleApi"
        },
        "typeVersion": 4.3
      },
      {
        "id": "fe5e2273-9610-442d-815c-d7d06d41cbc3",
        "name": "Return Response",
        "type": "n8n-nodes-base.respondToWebhook",
        "position": [
          1488,
          -48
        ],
        "parameters": {
          "options": {
            "responseHeaders": {
              "entries": [
                {
                  "name": "Content-Type",
                  "value": "application/json"
                }
              ]
            }
          },
          "respondWith": "json",
          "responseBody": "={\n  \"success\": true,\n  \"message\": \"Story generated successfully!\",\n  \"story\": {{ JSON.stringify($('Prepare Firestore Data').first().json.finalStory) }}\n}"
        },
        "typeVersion": 1.1
      }
    ],
    "pinData": {},
    "connections": {
      "Finalize Story": {
        "main": [
          [
            {
              "node": "Prepare Firestore Data",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Validate Input": {
        "main": [
          [
            {
              "node": "Generate Story (GPT-4)",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Story Input Form": {
        "main": [
          [
            {
              "node": "Validate Input",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Save to Firestore": {
        "main": [
          [
            {
              "node": "Return Response",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Prepare Story Data": {
        "main": [
          [
            {
              "node": "Generate Images (DALL-E 3)",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Generate Story (GPT-4)": {
        "main": [
          [
            {
              "node": "Prepare Story Data",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Prepare Firestore Data": {
        "main": [
          [
            {
              "node": "Save to Firestore",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Generate Images (DALL-E 3)": {
        "main": [
          [
            {
              "node": "Upload to Firebase Storage",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Upload to Firebase Storage": {
        "main": [
          [
            {
              "node": "Finalize Story",
              "type": "main",
              "index": 0
            }
          ]
        ]
      }
    }
  },
  "workflowInfo": {
    "nodeCount": 20,
    "nodeTypes": {
      "n8n-nodes-base.code": {
        "count": 6
      },
      "n8n-nodes-base.stickyNote": {
        "count": 10
      },
      "n8n-nodes-base.formTrigger": {
        "count": 1
      },
      "n8n-nodes-base.httpRequest": {
        "count": 2
      },
      "n8n-nodes-base.respondToWebhook": {
        "count": 1
      }
    }
  },
  "nodes": [
    "Sticky Note",
    "Sticky Note1",
    "Sticky Note2",
    "Sticky Note3",
    "Sticky Note4",
    "Sticky Note5",
    "Sticky Note6",
    "Sticky Note7",
    "Sticky Note8",
    "Sticky Note9",
    "Story Input Form",
    "Validate Input",
    "Generate Story (GPT-4)",
    "Prepare Story Data",
    "Generate Images (DALL-E 3)",
    "Upload to Firebase Storage",
    "Finalize Story",
    "Prepare Firestore Data",
    "Save to Firestore",
    "Return Response"
  ],
  "nodeTypes": [
    "n8n-nodes-base.httpRequest",
    "n8n-nodes-base.code",
    "n8n-nodes-base.stickyNote",
    "n8n-nodes-base.formTrigger",
    "n8n-nodes-base.respondToWebhook"
  ]
}