18 KiB
Dynamically generate a webpage from user request using OpenAI Structured Output
Dynamically generate a webpage from user request using OpenAI Structured Output
1. Workflow Overview
This workflow dynamically generates an HTML webpage based on a user’s query parameter by leveraging OpenAI’s Structured Output feature. Users specify what kind of page they want (e.g., a signup form) via a URL query parameter. The workflow then:
- Receives the user request through a webhook (1.1 Input Reception).
- Sends the query to OpenAI’s GPT model using a structured JSON schema to ensure the output follows a predefined UI component format (1.2 Structured UI Generation).
- Converts the structured JSON UI description into HTML using OpenAI’s language model (1.3 JSON-to-HTML Transformation).
- Wraps the generated HTML inside a full HTML document including Tailwind CSS for styling (1.4 HTML Formatting).
- Returns the fully formed HTML page as a response to the webhook (1.5 Webhook Response).
Logical Blocks:
- 1.1 Input Reception: Webhook node receives user HTTP requests with query parameter.
- 1.2 Structured UI Generation: HTTP Request node calls OpenAI API with a JSON schema prompt to generate UI components.
- 1.3 JSON-to-HTML Transformation: OpenAI node converts JSON UI structure to HTML markup.
- 1.4 HTML Formatting: HTML node wraps the HTML snippet with proper document structure and Tailwind CSS.
- 1.5 Webhook Response: Respond To Webhook node sends the final HTML page back to the user.
2. Block-by-Block Analysis
1.1 Input Reception
Overview:
Receives HTTP requests with a query parameter specifying the desired webpage content. This is the entry point of the workflow.
Nodes Involved:
- Webhook
Node Details:
- Webhook
- Type: Webhook (n8n-nodes-base.webhook)
- Configuration:
- Path: Unique webhook path (
d962c916-6369-431a-9d80-af6e6a50fdf5) - Allowed Origins: All (
*) for CORS flexibility - Response Mode:
responseNodeto delegate response to a later node
- Path: Unique webhook path (
- Input: External HTTP requests with URL query parameters, expects
queryparameter - Output: Passes received data forward, including the raw query string under
$json.query.query - Failures: Invalid or missing query parameter will cause downstream nodes to fail or produce empty results. No explicit validation here.
- Version: 2 (Webhook node version)
1.2 Structured UI Generation
Overview:
Sends the user query to OpenAI’s chat completions endpoint using a structured JSON schema as the response format to generate a UI definition in JSON.
Nodes Involved:
- Open AI - Using Structured Output (HTTP Request)
Node Details:
- Open AI - Using Structured Output
- Type: HTTP Request (n8n-nodes-base.httpRequest)
- Configuration:
- URL:
https://api.openai.com/v1/chat/completions - Method: POST
- Body Type: JSON with the following payload structure:
- Model:
gpt-4o-2024-08-06(latest GPT-4 variant supporting structured output) - Messages:
- System role: Defines assistant as a UI designer and copywriter using Tailwind CSS
- User role: Injects the user query string dynamically (
{{ $json.query.query }})
- Response Format: JSON schema defining allowed UI components and their properties (strict validation)
- The schema enumerates HTML element types (e.g., div, span, input, form, button, etc.)
- Each component includes
type,label,children(recursive), andattributes(name-value pairs for Tailwind classes or events)
- Model:
- Headers: Content-Type application/json
- Authentication: OpenAI API Key via predefined credential
- URL:
- Input: Receives webhook data containing the
querystring - Output: JSON structured UI definition in the response body (OpenAI chat completion)
- Potential Failures:
- Authentication errors with OpenAI API key
- Rate limiting or API timeouts
- Schema validation errors if prompt or model output doesn’t conform
- Version: 4.2 (HTTP Request node)
- Sticky Note attached explaining this node’s special role and usage of HTTP Request node due to missing native OpenAI structured output support
1.3 JSON-to-HTML Transformation
Overview:
Transforms the JSON UI structure generated by the previous node into HTML markup using an OpenAI model specialized for this conversion.
Nodes Involved:
- OpenAI - JSON to HTML
Node Details:
- OpenAI - JSON to HTML
- Type: OpenAI (Langchain) Node (
@n8n/n8n-nodes-langchain.openAi) - Configuration:
- Model:
gpt-4o-mini(smaller GPT-4 variant for faster response) - Temperature: 0.2 (low randomness for consistent output)
- Messages:
- System message instructs the AI to convert JSON fields
htmlandtitleinto HTML output - User message contains the JSON UI definition extracted from previous node's output (
{{ $json.choices[0].message.content }})
- System message instructs the AI to convert JSON fields
- Output: JSON expected output (
jsonOutputset to true), containing at leasthtmlandtitlefields
- Model:
- Input: JSON UI structure from previous OpenAI HTTP Request node
- Output: JSON containing the HTML snippet and page title
- Potential Failures:
- Parsing errors if input JSON is malformed
- API errors or timeouts
- Inconsistent HTML generation if input is unexpected
- Version: 1.3
- Type: OpenAI (Langchain) Node (
1.4 HTML Formatting
Overview:
Wraps the generated HTML snippet and title into a complete HTML document including standard document structure and Tailwind CSS integration.
Nodes Involved:
- Format the HTML result (HTML Node)
Node Details:
- Format the HTML result
- Type: HTML (n8n-nodes-base.html)
- Configuration:
- HTML Template:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <script src="https://cdn.tailwindcss.com"></script> <title>{{ $json.message.content.title }}</title> </head> <body> {{ $json.message.content.html }} </body> </html> - Uses expressions to insert
titleandhtmlfields dynamically from the previous node output
- HTML Template:
- Input: JSON with fields
message.content.titleandmessage.content.htmlfrom OpenAI JSON-to-HTML node - Output: Complete HTML document as a string
- Potential Failures:
- Missing or malformed fields in input JSON
- Expression evaluation errors
- Version: 1.2
1.5 Webhook Response
Overview:
Sends the final generated HTML page back to the user as the HTTP response with appropriate content-type headers.
Nodes Involved:
- Respond to Webhook
Node Details:
- Respond to Webhook
- Type: Respond to Webhook (n8n-nodes-base.respondToWebhook)
- Configuration:
- Response Body: Sends the formatted HTML from the previous node (
={{ $json.html }}) - Response Headers: Sets
Content-Typetotext/html; charset=UTF-8to render as a webpage
- Response Body: Sends the formatted HTML from the previous node (
- Input: HTML document string from the "Format the HTML result" node
- Output: HTTP response to the original webhook request
- Potential Failures:
- If input is empty or malformed, browser may display errors or blank page
- Version: 1.1
3. Summary Table
| Node Name | Node Type | Functional Role | Input Node(s) | Output Node(s) | Sticky Note |
|---|---|---|---|---|---|
| Webhook | Webhook (n8n-nodes-base.webhook) | Receives user HTTP requests with query param | None | Open AI - Using Structured Output | |
| Open AI - Using Structured Output | HTTP Request (n8n-nodes-base.httpRequest) | Sends user query to OpenAI with JSON schema | Webhook | OpenAI - JSON to HTML | Explains use of HTTP Request node for Structured Output and JSON response format, inspired by OpenAI structured outputs introduction. |
| OpenAI - JSON to HTML | OpenAI Langchain Node | Converts JSON UI structure to HTML | Open AI - Using Structured Output | Format the HTML result | |
| Format the HTML result | HTML (n8n-nodes-base.html) | Wraps HTML snippet in full HTML doc with Tailwind CSS | OpenAI - JSON to HTML | Respond to Webhook | |
| Respond to Webhook | Respond to Webhook (n8n-nodes-base.respondToWebhook) | Sends final HTML page as HTTP response | Format the HTML result | None | |
| Sticky Note | Sticky Note | Documentation and explanation | None | None | Explains the workflow concept and user instructions including example usage and general thoughts on structured output utility. |
| Sticky Note1 | Sticky Note | Documentation and explanation | None | None | Overview of workflow purpose and how it works; notes on Tailwind CSS and structured output benefits, with example URL usage instructions. |
4. Reproducing the Workflow from Scratch
-
Create Webhook Node
- Type: Webhook
- Parameters:
- Path: Set a unique webhook identifier (e.g.,
d962c916-6369-431a-9d80-af6e6a50fdf5) - Allowed Origins:
* - Response Mode:
responseNode(to delegate response)
- Path: Set a unique webhook identifier (e.g.,
- This node will receive HTTP requests containing the
queryparameter.
-
Create HTTP Request Node for Structured Output
- Name: Open AI - Using Structured Output
- Type: HTTP Request
- Parameters:
- URL:
https://api.openai.com/v1/chat/completions - Method: POST
- Authentication: Select or create OpenAI API credentials (OpenAI API key)
- Headers: Content-Type: application/json
- Body Content (JSON):
{ "model": "gpt-4o-2024-08-06", "messages": [ { "role": "system", "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" }, { "role": "user", "content": "{{ $json.query.query }}" } ], "response_format": { "type": "json_schema", "json_schema": { "name": "ui", "description": "Dynamically generated UI", "strict": true, "schema": { "type": "object", "properties": { "type": { "type": "string", "description": "The type of the UI component", "enum": [ "div", "span", "a", "p", "h1", "h2", "h3", "h4", "h5", "h6", "ul", "ol", "li", "img", "button", "input", "textarea", "select", "option", "label", "form", "table", "thead", "tbody", "tr", "th", "td", "nav", "header", "footer", "section", "article", "aside", "main", "figure", "figcaption", "blockquote", "q", "hr", "code", "pre", "iframe", "video", "audio", "canvas", "svg", "path", "circle", "rect", "line", "polyline", "polygon", "g", "use", "symbol" ] }, "label": { "type": "string", "description": "The label of the UI component, used for buttons or form fields" }, "children": { "type": "array", "description": "Nested UI components", "items": { "$ref": "#" } }, "attributes": { "type": "array", "description": "Arbitrary attributes for the UI component, suitable for any element using Tailwind framework", "items": { "type": "object", "properties": { "name": { "type": "string" }, "value": { "type": "string" } }, "required": ["name", "value"], "additionalProperties": false } } }, "required": ["type", "label", "children", "attributes"], "additionalProperties": false } } } } - Enable "Send Body" and "Send Headers"
- URL:
- Connect Webhook node output to this HTTP Request node input.
-
Create OpenAI Node for JSON-to-HTML Conversion
- Name: OpenAI - JSON to HTML
- Type: OpenAI (Langchain) Node
- Parameters:
- Model ID:
gpt-4o-mini - Temperature: 0.2
- Messages:
- System role content:
You convert a JSON to HTML. The JSON output has the following fields: - html: the page HTML - title: the page title - User role content:
={{ $json.choices[0].message.content }}(maps the JSON UI structure from previous node)
- System role content:
- Enable JSON output option
- Model ID:
- Credentials: Use the same OpenAI API key credential
- Connect the HTTP Request node output to this OpenAI node input.
-
Create HTML Node to Format Complete HTML Document
- Name: Format the HTML result
- Type: HTML
- Parameters:
- HTML Content:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <script src="https://cdn.tailwindcss.com"></script> <title>{{ $json.message.content.title }}</title> </head> <body> {{ $json.message.content.html }} </body> </html>
- HTML Content:
- Connect OpenAI JSON-to-HTML node output to this HTML node input.
-
Create Respond to Webhook Node
- Name: Respond to Webhook
- Type: Respond to Webhook
- Parameters:
- Respond With: Text
- Response Body:
={{ $json.html }}(injects the full HTML document) - Response Headers: Add entry with Name
Content-Typeand Valuetext/html; charset=UTF-8
- Connect the HTML node output to this Respond to Webhook node input.
-
Activate the workflow.
-
Usage:
- Call the webhook URL with a query parameter
querydescribing the desired page, e.g.:
https://<your-production-url>/<webhook-path>?query=a signup form - The workflow generates and returns a fully formed HTML page.
- Call the webhook URL with a query parameter
5. General Notes & Resources
| Note Content | Context or Link |
|---|---|
| This workflow is a proof of concept demonstrating OpenAI’s Structured Output feature to generate UI components | OpenAI Structured Outputs Intro: https://openai.com/index/introducing-structured-outputs-in-the-api |
| Tailwind CSS is embedded via CDN script tag to style generated pages effortlessly | https://tailwindcss.com |
| OpenAI API Key creation required for credentials setup | https://platform.openai.com/api-keys |
Example query usage: ?query=a signup form to generate a signup form webpage |
Highlighted in workflow description |
| The workflow uses HTTP Request node for Structured Output as official OpenAI node does not yet support it | Sticky note on the HTTP Request node explains this design choice |
| Results currently are experimental and may need prompt tuning for production readiness | Workflow sticky notes mention limitations and thoughts on structured output robustness |
This comprehensive documentation enables users and developers to fully understand, reproduce, and extend the workflow with confidence.