Dynamically Generate A Webpage From User Request Using Openai Structured Output

1 Tools

Explore Tool Categories

Find Agencies for This Project

Know a Better Recipe?

Help the community by sharing your proven tool combinations.

Submit a Recipe

About this recipe

A recipe for Dynamically Generate A Webpage From User Request Using Openai Structured Output

Recipe Template

{
    "id": "eXiaTDyKfXpMeyLh",
    "meta": {
        "instanceId": "f4f5d195bb2162a0972f737368404b18be694648d365d6c6771d7b4909d28167",
        "templateCredsSetupCompleted": true
    },
    "name": "Dynamically generate HTML page from user request using OpenAI Structured Output",
    "tags": [],
    "nodes": [
        {
            "id": "b1d9659f-4cd0-4f87-844d-32b2af1dcf13",
            "name": "Respond to Webhook",
            "type": "n8n-nodes-base.respondToWebhook",
            "position": [
                2160,
                380
            ],
            "parameters": {
                "options": {
                    "responseHeaders": {
                        "entries": [
                            {
                                "name": "Content-Type",
                                "value": "text\/html; charset=UTF-8"
                            }
                        ]
                    }
                },
                "respondWith": "text",
                "responseBody": "={{ $json.html }}"
            },
            "typeVersion": 1.1
        },
        {
            "id": "5ca8ad3e-7702-4f07-af24-d38e94fdc4ec",
            "name": "Open AI - Using Structured Output",
            "type": "n8n-nodes-base.httpRequest",
            "position": [
                1240,
                380
            ],
            "parameters": {
                "url": "https:\/\/api.openai.com\/v1\/chat\/completions",
                "method": "POST",
                "options": [],
                "jsonBody": "={\n \"model\": \"gpt-4o-2024-08-06\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"You are a user interface designer and copy writter. Your job is to help users visualize their website ideas. You design elegant and simple webs, with professional text. You use Tailwind framework\"\n },\n {\n \"role\": \"user\",\n \"content\": \"{{ $json.query.query }}\"\n }\n ],\n \"response_format\":\n{\n \"type\": \"json_schema\",\n \"json_schema\": {\n \"name\": \"ui\",\n \"description\": \"Dynamically generated UI\",\n \"strict\": true,\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"type\": {\n \"type\": \"string\",\n \"description\": \"The type of the UI component\",\n \"enum\": [\n \"div\",\n \"span\",\n \"a\",\n \"p\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"ul\",\n \"ol\",\n \"li\",\n \"img\",\n \"button\",\n \"input\",\n \"textarea\",\n \"select\",\n \"option\",\n \"label\",\n \"form\",\n \"table\",\n \"thead\",\n \"tbody\",\n \"tr\",\n \"th\",\n \"td\",\n \"nav\",\n \"header\",\n \"footer\",\n \"section\",\n \"article\",\n \"aside\",\n \"main\",\n \"figure\",\n \"figcaption\",\n \"blockquote\",\n \"q\",\n \"hr\",\n \"code\",\n \"pre\",\n \"iframe\",\n \"video\",\n \"audio\",\n \"canvas\",\n \"svg\",\n \"path\",\n \"circle\",\n \"rect\",\n \"line\",\n \"polyline\",\n \"polygon\",\n \"g\",\n \"use\",\n \"symbol\"\n]\n },\n \"label\": {\n \"type\": \"string\",\n \"description\": \"The label of the UI component, used for buttons or form fields\"\n },\n \"children\": {\n \"type\": \"array\",\n \"description\": \"Nested UI components\",\n \"items\": {\n \"$ref\": \"#\"\n }\n },\n \"attributes\": {\n \"type\": \"array\",\n \"description\": \"Arbitrary attributes for the UI component, suitable for any element using Tailwind framework\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"description\": \"The name of the attribute, for example onClick or className\"\n },\n \"value\": {\n \"type\": \"string\",\n \"description\": \"The value of the attribute using the Tailwind framework classes\"\n }\n },\n \"additionalProperties\": false,\n \"required\": [\"name\", \"value\"]\n }\n }\n },\n \"required\": [\"type\", \"label\", \"children\", \"attributes\"],\n \"additionalProperties\": false\n }\n }\n}\n}",
                "sendBody": true,
                "sendHeaders": true,
                "specifyBody": "json",
                "authentication": "predefinedCredentialType",
                "headerParameters": {
                    "parameters": [
                        {
                            "name": "Content-Type",
                            "value": "application\/json"
                        }
                    ]
                },
                "nodeCredentialType": "openAiApi"
            },
            "credentials": {
                "openAiApi": {
                    "id": "WqzqjezKh8VtxdqA",
                    "name": "OpenAi account - Baptiste"
                }
            },
            "typeVersion": 4.2
        },
        {
            "id": "24e5ca73-a3b3-4096-8c66-d84838d89b0c",
            "name": "OpenAI - JSON to HTML",
            "type": "@n8n\/n8n-nodes-langchain.openAi",
            "position": [
                1420,
                380
            ],
            "parameters": {
                "modelId": {
                    "__rl": true,
                    "mode": "list",
                    "value": "gpt-4o-mini",
                    "cachedResultName": "GPT-4O-MINI"
                },
                "options": {
                    "temperature": 0.2
                },
                "messages": {
                    "values": [
                        {
                            "role": "system",
                            "content": "You convert a JSON to HTML. \nThe JSON output has the following fields:\n- html: the page HTML\n- title: the page title"
                        },
                        {
                            "content": "={{ $json.choices[0].message.content }}"
                        }
                    ]
                },
                "jsonOutput": true
            },
            "credentials": {
                "openAiApi": {
                    "id": "WqzqjezKh8VtxdqA",
                    "name": "OpenAi account - Baptiste"
                }
            },
            "typeVersion": 1.3
        },
        {
            "id": "c50bdc84-ba59-4f30-acf7-496cee25068d",
            "name": "Format the HTML result",
            "type": "n8n-nodes-base.html",
            "position": [
                1940,
                380
            ],
            "parameters": {
                "html": "<!DOCTYPE html>\n\n<html>\n<head>\n <meta charset=\"UTF-8\" \/>\n <script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\n <title>{{ $json.message.content.title }}<\/title>\n<\/head>\n<body>\n{{ $json.message.content.html }}\n<\/body>\n<\/html>"
            },
            "typeVersion": 1.2
        },
        {
            "id": "193093f4-b1ce-4964-ab10-c3208e343c69",
            "name": "Sticky Note",
            "type": "n8n-nodes-base.stickyNote",
            "position": [
                1134,
                62
            ],
            "parameters": {
                "color": 7,
                "width": 638,
                "height": 503,
                "content": "## Generate HTML from user query\n\n**HTTP Request node**\n- Send the user query to OpenAI, with a defined JSON response format - *using HTTP Request node as it has not yet been implemented in the OpenAI nodes*\n- The response format is inspired by the [Structured Output defined in OpenAI Introduction post](https:\/\/openai.com\/index\/introducing-structured-outputs-in-the-api)\n- The output is a JSON containing HTML components and attributed\n\n\n**OpenAI node**\n- Format the response from the previous node from JSON format to HTML format"
            },
            "typeVersion": 1
        },
        {
            "id": "0371156a-211f-4d92-82b1-f14fe60d4b6b",
            "name": "Sticky Note1",
            "type": "n8n-nodes-base.stickyNote",
            "position": [
                0,
                60
            ],
            "parameters": {
                "color": 7,
                "width": 768,
                "height": 503,
                "content": "## Workflow: Dynamically generate an HTML page from a user request using OpenAI Structured Output\n\n**Overview**\n- This workflow is a experiment to build HTML pages from a user input using the new Structured Output from OpenAI.\n- The Structured Output could be used in a variety of cases. Essentially, it guarantees the output from the GPT will follow a defined structure (JSON object).\n- It uses Tailwind CSS to make it slightly nicer, but any\n\n**How it works**\n- Once active, go to the production URL and add what you'd like to build as the parameter \"query\"\n- Example: https:\/\/production_url.com?query=a%20signup%20form\n- OpenAI nodes will first output the UI as a JSON then convert it to HTML\n- Finally, the response is integrated in a HTML container and rendered to the user\n\n**Further thoughts**\n- Results are not yet amazing, it is hard to see the direct value of such an experiment\n- But it showcase the potential of the Structured Output. Being able to guarantee the output format is key to build robust AI applications."
            },
            "typeVersion": 1
        },
        {
            "id": "06380781-5189-4d99-9ecd-d8913ce40fd5",
            "name": "Webhook",
            "type": "n8n-nodes-base.webhook",
            "position": [
                820,
                380
            ],
            "webhookId": "d962c916-6369-431a-9d80-af6e6a50fdf5",
            "parameters": {
                "path": "d962c916-6369-431a-9d80-af6e6a50fdf5",
                "options": {
                    "allowedOrigins": "*"
                },
                "responseMode": "responseNode"
            },
            "typeVersion": 2
        }
    ],
    "active": true,
    "pinData": [],
    "settings": {
        "executionOrder": "v1"
    },
    "versionId": "d2307a2a-5427-4769-94a6-10eab703a788",
    "connections": {
        "Webhook": {
            "main": [
                [
                    {
                        "node": "Open AI - Using Structured Output",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "OpenAI - JSON to HTML": {
            "main": [
                [
                    {
                        "node": "Format the HTML result",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "Format the HTML result": {
            "main": [
                [
                    {
                        "node": "Respond to Webhook",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "Open AI - Using Structured Output": {
            "main": [
                [
                    {
                        "node": "OpenAI - JSON to HTML",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        }
    }
}

How to Use an n8n Template

1

Create a New Workflow

Click "New Workflow" in your n8n dashboard to get started.

2

Copy & Paste Template

First, copy this template: Click here to copy the JSON .
Then, in n8n, click the three dots (···) → "Import from file" and paste the JSON code.

3

Customize the Nodes

Go through each node in the workflow to update inputs like spreadsheet IDs, email addresses, or message content. Adjust field mappings to match your data.

4

Grant Access

For nodes that connect to external apps (like Google Sheets or Slack), you'll need to grant access. Connect your accounts using OAuth or an API key and save the credentials in the node.

5

Test It

Run the workflow by clicking "Execute Node" for each step or "Run Once" for the whole thing. Check the right sidebar to inspect data and debug any errors (they'll show up in red).

6

Activate Workflow

Once everything works as expected, click the "Activate" toggle to turn your workflow on. You're all set!