{
  "name": "Turn a Webhook Into a Self-Designing Fun Fact Website",
  "tags": [],
  "nodes": [
    {
      "id": "35654581-d945-49c8-8023-c109473b019f",
      "name": "Fun Fact Site",
      "type": "n8n-nodes-base.webhook",
      "position": [
        0,
        224
      ],
      "parameters": {
        "path": "fun-fact-site",
        "options": {},
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "160e31ea-5e75-4efc-92d5-01c855429e84",
      "name": "Fetch Fun Fact",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "maxTries": 3,
      "position": [
        240,
        224
      ],
      "parameters": {
        "url": "https://uselessfacts.jsph.pl/api/v2/facts/random?language=en",
        "options": {}
      },
      "retryOnFail": true,
      "typeVersion": 4.4,
      "waitBetweenTries": 5000
    },
    {
      "id": "6cf4544a-a2ac-44ce-9802-94e3506c517e",
      "name": "Build Fun Fact Page",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "onError": "continueErrorOutput",
      "maxTries": 3,
      "position": [
        448,
        112
      ],
      "parameters": {
        "text": "=Build a full webpage about this fun fact:\n\nFact: {{ $json.text }}\nSource: {{ $json.source }}\nSource URL: {{ $json.source_url }}",
        "options": {
          "systemMessage": "You are a creative web designer and copywriter. Given a fun fact, its source, and source URL, produce ONE complete, self-contained HTML document that turns that fact into a delightful little single-page website.\n\nRequirements:\n- Output ONLY raw HTML, starting exactly with \"<!DOCTYPE html>\". No markdown code fences, no commentary, no explanation before or after the HTML.\n- Everything must be self-contained: inline <style> only, no external stylesheets, fonts, or script CDNs, no network requests.\n- Freely choose a color palette, layout, and tone that fits the specific topic of the fact (e.g. playful and bright for an animal fact, sleek and dark for a space fact). Make every page visually distinct rather than reusing one template.\n- Include a bold headline, the fact itself presented prominently, and a short 2-4 paragraph creative write-up expanding on why the fact is interesting.\n- Near the bottom, credit the source as a link using the provided source URL.\n- Page must be readable on mobile (responsive, no fixed pixel-width containers wider than the viewport)."
        },
        "promptType": "define"
      },
      "retryOnFail": true,
      "typeVersion": 3.1,
      "waitBetweenTries": 5000
    },
    {
      "id": "a9a846db-8a20-419b-80d4-8ecc5109373d",
      "name": "Mistral Cloud Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatMistralCloud",
      "position": [
        448,
        304
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "9836c888-32e9-4a98-bfbe-27322bddf0b7",
      "name": "Respond With Page",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        896,
        96
      ],
      "parameters": {
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/html; charset=UTF-8"
              }
            ]
          }
        },
        "respondWith": "text",
        "responseBody": "={{ (() => {\n  const raw = String($('Build Fun Fact Page').item.json.output || \"\").trim();\n  const fenced = raw.match(/^```(?:html)?\\s*([\\s\\S]*?)\\s*```$/i);\n  return fenced ? fenced[1].trim() : raw;\n})() }}"
      },
      "typeVersion": 1.5
    },
    {
      "id": "87fc9075-2ed1-4457-9c1f-a102b3e92cd9",
      "name": "Respond With Error",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        896,
        240
      ],
      "parameters": {
        "options": {
          "responseCode": 502
        },
        "respondWith": "json",
        "responseBody": {
          "error": "upstream_error",
          "message": "={{ $json.error?.message ?? 'Could not fetch the fun fact or generate the page right now. Please try again in a moment.' }}"
        }
      },
      "typeVersion": 1.5
    },
    {
      "id": "d381fc22-d583-4797-b587-1244b93121d8",
      "name": "Sticky Note 008cccf2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -608,
        -112
      ],
      "parameters": {
        "width": 556,
        "height": 616,
        "content": "## \ud83c\udfb2 Fun Fact Webpage: n8n Builds Real Websites, Not Just Backends\n\n### How it works\nVisit the webhook URL. It pulls a random fact from a public API. An AI agent designs a full HTML page around that fact: fresh layout, fresh colors, fresh copy. Every single visit. No separate host. No build step. The webhook response is the website.\n\n### Setup\n1. Add a Mistral Cloud credential to \"Mistral Cloud Chat Model\" (swap in any chat model node you prefer).\n2. Activate the workflow.\n3. Open the Production URL on \"Fun Fact Site.\" Reload for a new page.\n\n### Customization\nChange the system prompt on \"Build Fun Fact Page\" to shift the style. Point \"Fetch Fun Fact\" at a different API for a different kind of page entirely."
      },
      "typeVersion": 1
    },
    {
      "id": "8b010321-8bb8-4547-a502-801072918c09",
      "name": "Sticky Note 0b465953",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        176,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 572,
        "height": 616,
        "content": "## \ud83c\udfb2 Fetch \u2192 \ud83e\udd16 Design\nPulls a fact from a public API. An AI agent turns it into a full, self-contained HTML page. New look every time."
      },
      "typeVersion": 1
    },
    {
      "id": "672f4059-fd50-49c5-a94d-98ab10e15300",
      "name": "Sticky Note 12a90952",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        784,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 332,
        "height": 616,
        "content": "## \ud83c\udf10 Respond\nSends the page back as real HTML. Fetch or AI generation fails: a structured JSON error goes out instead. No hanging browser."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": true,
    "executionOrder": "v1"
  },
  "nodeGroups": [],
  "connections": {
    "Fun Fact Site": {
      "main": [
        [
          {
            "node": "Fetch Fun Fact",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Fun Fact": {
      "main": [
        [
          {
            "node": "Build Fun Fact Page",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond With Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Fun Fact Page": {
      "main": [
        [
          {
            "node": "Respond With Page",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond With Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mistral Cloud Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Build Fun Fact Page",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}