SSO CMS converts raw dealer page HTML or natural-language prompts into structured, renderable content-block JSON — powered by GPT-4o mini.
AI endpoints require an X-Service-Key header. /blocks-to-html is open — no auth, no AI cost.
Paste raw dealer page HTML (up to 100 KB) and receive a normalized content-block JSON array — widgets, layout, and props extracted automatically.
Describe a page in plain language ("About page for a luxury Honda dealer") and receive a full content-block layout — no existing HTML required.
Submit an existing content JSON array for AI-assisted validation and repair. Fixes unknown widget types, missing required props, and malformed layouts.
Render a content-block JSON array to a scoped HTML fragment. No AI call — deterministic, fast, and free. Returns the fragment and a unique scopeId for CSS targeting.
All /ai/* routes require a valid X-Service-Key header matching
the CMS_SERVICE_KEY environment variable. Requests with a missing or wrong key
receive a 401 or 403 response. In local development, leave
CMS_SERVICE_KEY unset to bypass auth entirely.
SSO CMS is the API layer in a full content authoring pipeline — AI generation feeds a visual editor, the editor renders to scoped HTML, and that HTML goes anywhere.
POST a prompt or raw HTML. GPT-4o mini returns structured content-block JSON.
Drag, reorder, and edit blocks in <content-blocks-editor>. Change fires on every update.
POST the edited blocks to /blocks-to-html. Receive a scoped HTML fragment instantly.
Inject the HTML anywhere — dealer pages, emails, CMS previews. The scopeId keeps CSS isolated.
<content-blocks-editor>
A drag-and-drop WYSIWYG web component for authoring content-block JSON. The host form owns
all data fetching — pass context and content in via JS, listen for change events
to save. Works in any form context; the component has no opinion on what context contains.
readonly — view-only mode ·
JS: editor.context = obj — forwarded to AI + preview ·
JS: editor.value = rows to init · editor.value to read
Pick a request style and copy the snippet.
# Convert a prompt to content blocks curl -X POST http://localhost:4132/ai/prompt-to-blocks \ -H "Content-Type: application/json" \ -H "X-Service-Key: your-key" \ -d '{ "prompt": "About page for a luxury Honda dealership in Phoenix", "hostname": "dealer.example.com" }'
const res = await fetch('http://localhost:4132/ai/prompt-to-blocks', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Service-Key': process.env.CMS_SERVICE_KEY, }, body: JSON.stringify({ prompt: 'About page for a luxury Honda dealership in Phoenix', hostname: 'dealer.example.com', }), }); const { rows, usage } = await res.json(); // rows → array of layout rows with columns and widgets // usage → { prompt_tokens, completion_tokens, total_tokens }
{
"rows": [
{
"layout": "full",
"columns": [
{
"widgets": [
{
"type": "header",
"props": { "text": "About Our Dealership", "tag": "h1" }
},
{
"type": "text",
"props": { "content": "Serving Phoenix since 1987..." }
}
]
}
]
},
{
"layout": "1/3+2/3",
"columns": [ /* ... */ ]
}
],
"usage": {
"prompt_tokens": 312,
"completion_tokens": 487,
"total_tokens": 799
}
}
Each row declares one of these layouts to control how columns divide the horizontal space.
Every deploy is verified via GET /health. The response includes a
SHA-256 file hash of server.js — deploy scripts compare this against
the built artifact to confirm the correct version is running.