Created
February 11, 2026 15:44
-
-
Save maniasmk-collab/029ee2c9b230fa6ddef18a13dc4271e6 to your computer and use it in GitHub Desktop.
n8n workflow - Automated Facebook science facts page
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "name": "Weird Science - Daily Auto Post", | |
| "nodes": [ | |
| { | |
| "parameters": { | |
| "rule": { | |
| "interval": [ | |
| { | |
| "field": "cronExpression", | |
| "expression": "0 6 * * *" | |
| } | |
| ] | |
| } | |
| }, | |
| "id": "d1a2b3c4-0001-4000-8000-000000000001", | |
| "name": "Daily 6AM EST Trigger", | |
| "type": "n8n-nodes-base.scheduleTrigger", | |
| "typeVersion": 1.2, | |
| "position": [ | |
| 240, | |
| 300 | |
| ] | |
| }, | |
| { | |
| "parameters": { | |
| "operation": "read", | |
| "documentId": { | |
| "__rl": true, | |
| "value": "YOUR_GOOGLE_SHEET_ID", | |
| "mode": "id" | |
| }, | |
| "sheetName": { | |
| "__rl": true, | |
| "value": "Posted_Facts", | |
| "mode": "list" | |
| }, | |
| "options": {} | |
| }, | |
| "id": "d1a2b3c4-0002-4000-8000-000000000002", | |
| "name": "Read Recent Facts", | |
| "type": "n8n-nodes-base.googleSheets", | |
| "typeVersion": 4.5, | |
| "position": [ | |
| 460, | |
| 300 | |
| ], | |
| "credentials": { | |
| "googleSheetsOAuth2Api": { | |
| "id": "", | |
| "name": "Google Sheets" | |
| } | |
| } | |
| }, | |
| { | |
| "parameters": { | |
| "jsCode": "// Node 3: Prepare Dedup List + Build OpenAI Request Body\r\n// Runs once for all items from Google Sheets read\r\n\r\nconst rows = $input.all();\r\nconst recentFacts = rows\r\n .slice(-200)\r\n .map(item => item.json.fact_text || '')\r\n .filter(f => f.length > 0);\r\n\r\nconst recentCategories = rows\r\n .slice(-50)\r\n .map(item => item.json.category || '')\r\n .filter(c => c.length > 0);\r\n\r\nconst dedupLines = recentFacts.slice(-30).join('\\n');\r\nconst categoryList = [...new Set(recentCategories)].join(', ');\r\nconst dedupContext = 'RECENTLY USED FACTS (avoid similar topics):\\n' + dedupLines + '\\n\\nRECENT CATEGORIES (vary from these):\\n' + categoryList;\r\n\r\nconst systemPrompt = 'You are a science content writer for \\'Weird Science,\\' a Facebook page targeting a USA audience.\\n\\n' +\r\n'TASK: Generate exactly 6 unique, fascinating science facts.\\n\\n' +\r\n'RULES FOR FACTS:\\n' +\r\n'- Each fact must be genuinely surprising, curiosity-driven, and scientifically verified\\n' +\r\n'- Topics: space, biology, physics, chemistry, earth science, human body, animals, ocean, technology history, paleontology, geology, weather, mathematics in nature\\n' +\r\n'- NO health claims, NO medical advice, NO political science, NO controversial topics\\n' +\r\n'- NO unverified viral claims (e.g., \\'no scientist knows why\\' — if it\\'s explained by science, say so honestly)\\n' +\r\n'- Each fact must be 2-3 sentences, 20-40 words maximum for image text\\n' +\r\n'- Write in simple, punchy language — like telling a friend something amazing\\n' +\r\n'- Never start two facts with the same word\\n' +\r\n'- Never repeat a topic category in the same batch\\n' +\r\n'- All facts must be accurate and verifiable from mainstream scientific sources\\n\\n' +\r\n'RULES FOR HIGHLIGHT WORDS:\\n' +\r\n'- Pick exactly 2-3 of the most impactful words or short phrases from the fact\\n' +\r\n'- These should be the words that make someone stop scrolling\\n' +\r\n'- Highlights must be exact substrings of the fact_text\\n\\n' +\r\n'RULES FOR CAPTION:\\n' +\r\n'- 3-4 short paragraphs expanding on the fact (150-250 words total)\\n' +\r\n'- Conversational tone, like explaining to a curious friend\\n' +\r\n'- Include one additional interesting detail NOT in the image text\\n' +\r\n'- No more than 1 emoji in the entire caption (use sparingly or none)\\n' +\r\n'- End with: Follow Weird Science for daily mind-blowing facts!\\n' +\r\n'- Then add a blank line and disclaimer: Disclaimer: This post is for educational and entertainment purposes only. All facts are based on publicly available scientific research. Images are AI-generated.\\n\\n' +\r\n'RULES FOR HASHTAGS:\\n' +\r\n'- Exactly 5 hashtags\\n' +\r\n'- Mix of broad (#Science #Facts) and specific (#SpaceExploration #DeepSea)\\n' +\r\n'- No made-up hashtags — only use real, commonly searched hashtags\\n' +\r\n'- Always include #WeirdScience as the first hashtag\\n\\n' +\r\n'RULES FOR IMAGE GENERATION:\\n' +\r\n'- Provide a \\'dalle_prompt\\' — one detailed sentence describing a dramatic, atmospheric background scene related to the fact\\n' +\r\n'- The dalle_prompt must specify: \\'no text, no words, no letters, no numbers, no watermarks, no people faces\\'\\n' +\r\n'- Style: cinematic lighting, dark moody tone, high detail, suitable as background for overlaid text\\n' +\r\n'- The scene should be visually dramatic and related to the fact\\'s subject\\n\\n' +\r\n'RULES FOR CATEGORY:\\n' +\r\n'- Assign one category from: space, biology, physics, chemistry, earth_science, human_body, animals, ocean, tech_history, paleontology, geology, weather, math_nature\\n\\n' +\r\n'OUTPUT FORMAT (strict JSON):\\n' +\r\n'{\\n' +\r\n' \"facts\": [\\n' +\r\n' {\\n' +\r\n' \"id\": 1,\\n' +\r\n' \"fact_text\": \"...\",\\n' +\r\n' \"highlight_words\": [\"word1\", \"word2\"],\\n' +\r\n' \"caption\": \"...\",\\n' +\r\n' \"hashtags\": \"#WeirdScience #Tag2 #Tag3 #Tag4 #Tag5\",\\n' +\r\n' \"dalle_prompt\": \"...\",\\n' +\r\n' \"category\": \"space\"\\n' +\r\n' }\\n' +\r\n' ]\\n' +\r\n'}\\n\\n' +\r\n'Return ONLY valid JSON. No explanation, no markdown, no extra text.';\r\n\r\nconst requestBody = {\r\n model: 'gpt-4o-mini',\r\n temperature: 0.9,\r\n max_tokens: 4000,\r\n response_format: { type: 'json_object' },\r\n messages: [\r\n { role: 'system', content: systemPrompt },\r\n { role: 'user', content: 'Generate 6 unique science facts for today.\\n\\n' + dedupContext }\r\n ]\r\n};\r\n\r\nreturn [{ json: { openai_request_body: JSON.stringify(requestBody), dedup_context: dedupContext } }];\r\n", | |
| "mode": "runOnceForAllItems" | |
| }, | |
| "id": "d1a2b3c4-0003-4000-8000-000000000003", | |
| "name": "Prepare Dedup List", | |
| "type": "n8n-nodes-base.code", | |
| "typeVersion": 2, | |
| "position": [ | |
| 680, | |
| 300 | |
| ] | |
| }, | |
| { | |
| "parameters": { | |
| "method": "POST", | |
| "url": "https://api.openai.com/v1/chat/completions", | |
| "authentication": "genericCredentialType", | |
| "genericAuthType": "httpHeaderAuth", | |
| "sendHeaders": true, | |
| "headerParameters": { | |
| "parameters": [ | |
| { | |
| "name": "Content-Type", | |
| "value": "application/json" | |
| } | |
| ] | |
| }, | |
| "sendBody": true, | |
| "specifyBody": "string", | |
| "body": "={{ $json.openai_request_body }}", | |
| "options": { | |
| "timeout": 120000 | |
| } | |
| }, | |
| "id": "d1a2b3c4-0004-4000-8000-000000000004", | |
| "name": "Generate 6 Facts", | |
| "type": "n8n-nodes-base.httpRequest", | |
| "typeVersion": 4.2, | |
| "position": [ | |
| 900, | |
| 300 | |
| ], | |
| "credentials": { | |
| "httpHeaderAuth": { | |
| "id": "", | |
| "name": "OpenAI API Key" | |
| } | |
| }, | |
| "retryOnFail": true, | |
| "maxTries": 3, | |
| "waitBetweenTries": 30000, | |
| "onError": "continueErrorOutput" | |
| }, | |
| { | |
| "parameters": { | |
| "jsCode": "// Node 5: Parse GPT Response\r\n// Validates each fact, assigns post times, prepares for loop\r\n\r\nconst response = $input.first().json;\r\nlet factsData;\r\n\r\n// Parse from OpenAI response structure\r\nconst content = response.choices[0].message.content;\r\nfactsData = JSON.parse(content);\r\n\r\n// Handle both { facts: [...] } and direct array\r\nconst facts = factsData.facts || factsData;\r\n\r\nif (!Array.isArray(facts) || facts.length === 0) {\r\n throw new Error('GPT returned no facts');\r\n}\r\n\r\n// USA peak times (EST) for 6 posts per day\r\nconst postTimesEST = [\r\n '08:00', '10:30', '12:30', '15:00', '18:00', '20:30'\r\n];\r\n\r\n// Validate and enrich each fact\r\nconst validated = facts.slice(0, 6).map((fact, index) => {\r\n if (!fact.fact_text || !fact.highlight_words || !fact.caption || !fact.dalle_prompt) {\r\n throw new Error('Fact ' + (index + 1) + ' missing required fields');\r\n }\r\n\r\n if (fact.fact_text.length > 300) {\r\n throw new Error('Fact ' + (index + 1) + ' text too long for image (' + fact.fact_text.length + ' chars)');\r\n }\r\n\r\n // Calculate scheduled post time in EST\r\n const now = new Date();\r\n const parts = postTimesEST[index].split(':');\r\n const hours = parseInt(parts[0]);\r\n const minutes = parseInt(parts[1]);\r\n\r\n // Create date in EST (UTC-5)\r\n // We set hours in local time assuming n8n timezone is America/New_York\r\n const postTime = new Date(now);\r\n postTime.setHours(hours, minutes, 0, 0);\r\n\r\n const unixTimestamp = Math.floor(postTime.getTime() / 1000);\r\n\r\n return {\r\n id: fact.id || (index + 1),\r\n fact_text: fact.fact_text,\r\n highlight_words: fact.highlight_words,\r\n caption: fact.caption,\r\n hashtags: fact.hashtags,\r\n dalle_prompt: fact.dalle_prompt,\r\n category: fact.category,\r\n index: index,\r\n post_time_est: postTimesEST[index],\r\n post_time_unix: unixTimestamp,\r\n post_time_iso: postTime.toISOString(),\r\n generated_at: new Date().toISOString()\r\n };\r\n});\r\n\r\nreturn validated.map(f => ({ json: f }));\r\n", | |
| "mode": "runOnceForAllItems" | |
| }, | |
| "id": "d1a2b3c4-0005-4000-8000-000000000005", | |
| "name": "Parse GPT Response", | |
| "type": "n8n-nodes-base.code", | |
| "typeVersion": 2, | |
| "position": [ | |
| 1120, | |
| 300 | |
| ] | |
| }, | |
| { | |
| "parameters": { | |
| "batchSize": 1, | |
| "options": {} | |
| }, | |
| "id": "d1a2b3c4-0006-4000-8000-000000000006", | |
| "name": "Loop Facts", | |
| "type": "n8n-nodes-base.splitInBatches", | |
| "typeVersion": 3, | |
| "position": [ | |
| 1340, | |
| 300 | |
| ] | |
| }, | |
| { | |
| "parameters": { | |
| "method": "POST", | |
| "url": "https://api.openai.com/v1/images/generations", | |
| "authentication": "genericCredentialType", | |
| "genericAuthType": "httpHeaderAuth", | |
| "sendHeaders": true, | |
| "headerParameters": { | |
| "parameters": [ | |
| { | |
| "name": "Content-Type", | |
| "value": "application/json" | |
| } | |
| ] | |
| }, | |
| "sendBody": true, | |
| "specifyBody": "json", | |
| "jsonBody": "={{ JSON.stringify({ model: \"dall-e-3\", prompt: $json.dalle_prompt, n: 1, size: \"1024x1024\", quality: \"standard\", response_format: \"url\" }) }}", | |
| "options": { | |
| "timeout": 120000 | |
| } | |
| }, | |
| "id": "d1a2b3c4-0007-4000-8000-000000000007", | |
| "name": "DALL-E 3 Image", | |
| "type": "n8n-nodes-base.httpRequest", | |
| "typeVersion": 4.2, | |
| "position": [ | |
| 1560, | |
| 300 | |
| ], | |
| "credentials": { | |
| "httpHeaderAuth": { | |
| "id": "", | |
| "name": "OpenAI API Key" | |
| } | |
| }, | |
| "retryOnFail": true, | |
| "maxTries": 2, | |
| "waitBetweenTries": 30000, | |
| "onError": "continueErrorOutput" | |
| }, | |
| { | |
| "parameters": { | |
| "jsCode": "// Node 8: Build HTML Template + HCTI Request Body\r\n// Composes the branded 1080x1080 image HTML with fact text, highlights, and DALL-E background\r\n\r\nconst fact = $input.first().json;\r\n\r\n// Get DALL-E image URL from the DALL-E 3 Image node output\r\nconst dalleResponse = $('DALL-E 3 Image').first().json;\r\nconst bgUrl = dalleResponse.data[0].url;\r\n\r\n// Escape HTML special characters in fact text\r\nlet factHtml = fact.fact_text\r\n .replace(/&/g, '&')\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/\"/g, '"')\r\n .replace(/'/g, ''');\r\n\r\n// Apply highlight styling (sort by length, longest first to avoid partial matches)\r\nconst highlights = [...fact.highlight_words].sort((a, b) => b.length - a.length);\r\nfor (const word of highlights) {\r\n // Escape regex special characters in the highlight word\r\n const escaped = word\r\n .replace(/&/g, '&')\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/\"/g, '"')\r\n .replace(/'/g, ''')\r\n .replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n const regex = new RegExp('(' + escaped + ')', 'gi');\r\n factHtml = factHtml.replace(regex, '<span class=\"highlight\">$1</span>');\r\n}\r\n\r\n// Build the complete HTML/CSS template\r\nconst html = [\r\n '<html>',\r\n '<head>',\r\n '<link href=\"https://fonts.googleapis.com/css2?family=Montserrat:wght@700;800;900&display=swap\" rel=\"stylesheet\">',\r\n '<style>',\r\n ' * { margin: 0; padding: 0; box-sizing: border-box; }',\r\n ' body {',\r\n ' width: 1080px;',\r\n ' height: 1080px;',\r\n ' overflow: hidden;',\r\n \" font-family: 'Montserrat', sans-serif;\",\r\n ' background: #000;',\r\n ' }',\r\n ' .container {',\r\n ' width: 1080px;',\r\n ' height: 1080px;',\r\n ' position: relative;',\r\n \" background-image: url('\" + bgUrl + \"');\",\r\n ' background-size: cover;',\r\n ' background-position: center;',\r\n ' }',\r\n ' .border-frame {',\r\n ' position: absolute;',\r\n ' top: 0; left: 0; right: 0; bottom: 0;',\r\n ' border: 3px solid rgba(0, 229, 255, 0.5);',\r\n ' z-index: 10;',\r\n ' }',\r\n ' .overlay {',\r\n ' position: absolute;',\r\n ' top: 0; left: 0; right: 0; bottom: 0;',\r\n ' background: linear-gradient(to bottom, rgba(0,0,0,0.15) 0%, rgba(0,0,0,0.1) 25%, rgba(0,0,0,0.4) 45%, rgba(0,0,0,0.78) 65%, rgba(0,0,0,0.92) 85%, rgba(0,0,0,0.97) 100%);',\r\n ' z-index: 1;',\r\n ' }',\r\n ' .brand-badge {',\r\n ' position: absolute;',\r\n ' top: 28px;',\r\n ' right: 28px;',\r\n ' background: rgba(0,0,0,0.5);',\r\n ' padding: 10px 20px;',\r\n ' border-radius: 24px;',\r\n ' border: 1.5px solid rgba(0, 229, 255, 0.3);',\r\n ' z-index: 5;',\r\n ' }',\r\n ' .brand-name {',\r\n ' color: #00E5FF;',\r\n ' font-size: 16px;',\r\n ' font-weight: 800;',\r\n ' letter-spacing: 1.5px;',\r\n ' text-transform: uppercase;',\r\n ' }',\r\n ' .fact-area {',\r\n ' position: absolute;',\r\n ' bottom: 75px;',\r\n ' left: 55px;',\r\n ' right: 55px;',\r\n ' z-index: 5;',\r\n ' text-align: center;',\r\n ' }',\r\n ' .fact-text {',\r\n ' color: #FFFFFF;',\r\n ' font-size: 38px;',\r\n ' font-weight: 800;',\r\n ' line-height: 1.4;',\r\n ' text-shadow: 0 2px 12px rgba(0,0,0,0.9), 0 1px 3px rgba(0,0,0,0.8);',\r\n ' }',\r\n ' .highlight {',\r\n ' color: #00E5FF;',\r\n ' text-shadow: 0 0 20px rgba(0,229,255,0.3), 0 2px 12px rgba(0,0,0,0.9);',\r\n ' }',\r\n ' .glow-line {',\r\n ' width: 80px;',\r\n ' height: 3px;',\r\n ' background: #00E5FF;',\r\n ' margin: 0 auto 22px auto;',\r\n ' box-shadow: 0 0 12px rgba(0,229,255,0.5);',\r\n ' }',\r\n ' .footer-bar {',\r\n ' position: absolute;',\r\n ' bottom: 0; left: 0; right: 0;',\r\n ' height: 52px;',\r\n ' background: rgba(0,0,0,0.95);',\r\n ' border-top: 2px solid #00E5FF;',\r\n ' display: flex;',\r\n ' align-items: center;',\r\n ' justify-content: center;',\r\n ' z-index: 5;',\r\n ' }',\r\n ' .footer-text {',\r\n ' color: #00E5FF;',\r\n ' font-size: 17px;',\r\n ' font-weight: 900;',\r\n ' letter-spacing: 6px;',\r\n ' text-transform: uppercase;',\r\n ' }',\r\n '</style>',\r\n '</head>',\r\n '<body>',\r\n ' <div class=\"container\">',\r\n ' <div class=\"overlay\"></div>',\r\n ' <div class=\"border-frame\"></div>',\r\n ' <div class=\"brand-badge\">',\r\n ' <span class=\"brand-name\">⚛ Weird Science</span>',\r\n ' </div>',\r\n ' <div class=\"fact-area\">',\r\n ' <div class=\"glow-line\"></div>',\r\n ' <div class=\"fact-text\">' + factHtml + '</div>',\r\n ' </div>',\r\n ' <div class=\"footer-bar\">',\r\n ' <span class=\"footer-text\">Weird Science</span>',\r\n ' </div>',\r\n ' </div>',\r\n '</body>',\r\n '</html>'\r\n].join('\\n');\r\n\r\n// Build HCTI request body\r\nconst hctiBody = {\r\n html: html,\r\n google_fonts: 'Montserrat',\r\n viewport_width: 1080,\r\n viewport_height: 1080,\r\n device_scale: 1,\r\n ms_delay: 1500\r\n};\r\n\r\nreturn [{\r\n json: {\r\n ...fact,\r\n dalle_image_url: bgUrl,\r\n composed_html: html,\r\n hcti_request_body: JSON.stringify(hctiBody)\r\n }\r\n}];\r\n", | |
| "mode": "runOnceForAllItems" | |
| }, | |
| "id": "d1a2b3c4-0008-4000-8000-000000000008", | |
| "name": "Build HTML Template", | |
| "type": "n8n-nodes-base.code", | |
| "typeVersion": 2, | |
| "position": [ | |
| 1780, | |
| 300 | |
| ] | |
| }, | |
| { | |
| "parameters": { | |
| "method": "POST", | |
| "url": "https://hcti.io/v1/image", | |
| "authentication": "genericCredentialType", | |
| "genericAuthType": "httpBasicAuth", | |
| "sendHeaders": true, | |
| "headerParameters": { | |
| "parameters": [ | |
| { | |
| "name": "Content-Type", | |
| "value": "application/json" | |
| } | |
| ] | |
| }, | |
| "sendBody": true, | |
| "specifyBody": "string", | |
| "body": "={{ $json.hcti_request_body }}", | |
| "options": { | |
| "timeout": 30000 | |
| } | |
| }, | |
| "id": "d1a2b3c4-0009-4000-8000-000000000009", | |
| "name": "HTMLCSSToImage", | |
| "type": "n8n-nodes-base.httpRequest", | |
| "typeVersion": 4.2, | |
| "position": [ | |
| 2000, | |
| 300 | |
| ], | |
| "credentials": { | |
| "httpBasicAuth": { | |
| "id": "", | |
| "name": "HTMLCSSToImage" | |
| } | |
| }, | |
| "retryOnFail": true, | |
| "maxTries": 3, | |
| "waitBetweenTries": 15000, | |
| "onError": "continueErrorOutput" | |
| }, | |
| { | |
| "parameters": { | |
| "resume": "specificTime", | |
| "dateTime": "={{ $json.post_time_iso }}" | |
| }, | |
| "id": "d1a2b3c4-0010-4000-8000-000000000010", | |
| "name": "Wait Until Post Time", | |
| "type": "n8n-nodes-base.wait", | |
| "typeVersion": 1.1, | |
| "position": [ | |
| 2220, | |
| 300 | |
| ] | |
| }, | |
| { | |
| "parameters": { | |
| "method": "POST", | |
| "url": "=https://graph.facebook.com/v19.0/YOUR_PAGE_ID/photos", | |
| "authentication": "noAuth", | |
| "sendBody": true, | |
| "contentType": "multipart-form-data", | |
| "bodyParameters": { | |
| "parameters": [ | |
| { | |
| "name": "url", | |
| "value": "={{ $('HTMLCSSToImage').first().json.url }}" | |
| }, | |
| { | |
| "name": "message", | |
| "value": "={{ $('Build HTML Template').first().json.caption + '\\n\\n' + $('Build HTML Template').first().json.hashtags }}" | |
| }, | |
| { | |
| "name": "access_token", | |
| "value": "YOUR_FACEBOOK_PAGE_ACCESS_TOKEN" | |
| }, | |
| { | |
| "name": "published", | |
| "value": "true" | |
| } | |
| ] | |
| }, | |
| "options": { | |
| "timeout": 60000 | |
| } | |
| }, | |
| "id": "d1a2b3c4-0011-4000-8000-000000000011", | |
| "name": "Post to Facebook", | |
| "type": "n8n-nodes-base.httpRequest", | |
| "typeVersion": 4.2, | |
| "position": [ | |
| 2440, | |
| 300 | |
| ], | |
| "retryOnFail": true, | |
| "maxTries": 3, | |
| "waitBetweenTries": 60000, | |
| "onError": "continueErrorOutput" | |
| }, | |
| { | |
| "parameters": { | |
| "operation": "append", | |
| "documentId": { | |
| "__rl": true, | |
| "value": "YOUR_GOOGLE_SHEET_ID", | |
| "mode": "id" | |
| }, | |
| "sheetName": { | |
| "__rl": true, | |
| "value": "Posted_Facts", | |
| "mode": "list" | |
| }, | |
| "columns": { | |
| "mappingMode": "defineBelow", | |
| "value": { | |
| "date_posted": "={{ $now.format('yyyy-MM-dd') }}", | |
| "time_posted": "={{ $('Build HTML Template').first().json.post_time_est }}", | |
| "fact_text": "={{ $('Build HTML Template').first().json.fact_text }}", | |
| "category": "={{ $('Build HTML Template').first().json.category }}", | |
| "caption": "={{ $('Build HTML Template').first().json.caption }}", | |
| "hashtags": "={{ $('Build HTML Template').first().json.hashtags }}", | |
| "image_url": "={{ $('HTMLCSSToImage').first().json.url }}", | |
| "dalle_image_url": "={{ $('Build HTML Template').first().json.dalle_image_url }}", | |
| "facebook_post_id": "={{ $json.id || $json.post_id || '' }}", | |
| "status": "success" | |
| } | |
| }, | |
| "options": {} | |
| }, | |
| "id": "d1a2b3c4-0012-4000-8000-000000000012", | |
| "name": "Log Success", | |
| "type": "n8n-nodes-base.googleSheets", | |
| "typeVersion": 4.5, | |
| "position": [ | |
| 2660, | |
| 300 | |
| ], | |
| "credentials": { | |
| "googleSheetsOAuth2Api": { | |
| "id": "", | |
| "name": "Google Sheets" | |
| } | |
| } | |
| }, | |
| { | |
| "parameters": { | |
| "jsCode": "// Node 13: Error Handler\r\n// Formats error data for logging to Google Sheets\r\n\r\nconst error = $input.first().json;\r\n\r\nconst errorData = {\r\n date: new Date().toISOString(),\r\n node: error.node || error.description || 'unknown',\r\n message: error.message || JSON.stringify(error).substring(0, 500),\r\n fact_index: error.index !== undefined ? String(error.index) : 'N/A'\r\n};\r\n\r\nreturn [{ json: errorData }];\r\n", | |
| "mode": "runOnceForAllItems" | |
| }, | |
| "id": "d1a2b3c4-0013-4000-8000-000000000013", | |
| "name": "Error Handler", | |
| "type": "n8n-nodes-base.code", | |
| "typeVersion": 2, | |
| "position": [ | |
| 1900, | |
| 540 | |
| ] | |
| }, | |
| { | |
| "parameters": { | |
| "operation": "append", | |
| "documentId": { | |
| "__rl": true, | |
| "value": "YOUR_GOOGLE_SHEET_ID", | |
| "mode": "id" | |
| }, | |
| "sheetName": { | |
| "__rl": true, | |
| "value": "Errors", | |
| "mode": "list" | |
| }, | |
| "columns": { | |
| "mappingMode": "defineBelow", | |
| "value": { | |
| "date": "={{ $json.date }}", | |
| "node": "={{ $json.node }}", | |
| "error_message": "={{ $json.message }}", | |
| "fact_index": "={{ $json.fact_index }}", | |
| "resolved": "no" | |
| } | |
| }, | |
| "options": {} | |
| }, | |
| "id": "d1a2b3c4-0014-4000-8000-000000000014", | |
| "name": "Log Error", | |
| "type": "n8n-nodes-base.googleSheets", | |
| "typeVersion": 4.5, | |
| "position": [ | |
| 2120, | |
| 540 | |
| ], | |
| "credentials": { | |
| "googleSheetsOAuth2Api": { | |
| "id": "", | |
| "name": "Google Sheets" | |
| } | |
| } | |
| } | |
| ], | |
| "connections": { | |
| "Daily 6AM EST Trigger": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Read Recent Facts", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Read Recent Facts": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Prepare Dedup List", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Prepare Dedup List": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Generate 6 Facts", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Generate 6 Facts": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Parse GPT Response", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ], | |
| [ | |
| { | |
| "node": "Error Handler", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Parse GPT Response": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Loop Facts", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Loop Facts": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "DALL-E 3 Image", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ], | |
| [] | |
| ] | |
| }, | |
| "DALL-E 3 Image": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Build HTML Template", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ], | |
| [ | |
| { | |
| "node": "Error Handler", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Build HTML Template": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "HTMLCSSToImage", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "HTMLCSSToImage": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Wait Until Post Time", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ], | |
| [ | |
| { | |
| "node": "Error Handler", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Wait Until Post Time": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Post to Facebook", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Post to Facebook": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Log Success", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ], | |
| [ | |
| { | |
| "node": "Error Handler", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Log Success": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Loop Facts", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Error Handler": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Log Error", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| } | |
| }, | |
| "active": false, | |
| "settings": { | |
| "timezone": "America/New_York", | |
| "executionTimeout": 600, | |
| "saveManualExecutions": true, | |
| "callerPolicy": "workflowsFromSameOwner" | |
| }, | |
| "pinData": {}, | |
| "tags": [ | |
| { | |
| "name": "social-media" | |
| }, | |
| { | |
| "name": "automation" | |
| } | |
| ] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment