HTML Wizard application icon

HTML Wizard

Create

AI-powered factory for reusable HTML/CSS/JS components. Describe a widget in plain English and get a single self-contained envelope file — one inline stylesheet, one ES6 module, one #root mount point — rendered live in a sandboxed iframe, captured to PNG, and refined iteratively with real vision and console feedback.

OfficeHTMLComponentsDevs
Start New Session

HTML Wizard Documentation

# 🧩 HTML Wizard > **Describe a widget in plain words — get one self-contained HTML file that actually runs, a PNG of how it looks, and a console log of how it behaves.** HTML Wizard is the component-shaped sibling of [SVG Wizard](../svg-wizard) and [TeX Wizard](../tex-wizard). Instead of compiling LaTeX or authoring vectors, it writes **`component.html`** — a strict *single-file envelope* — mounts it in a **sandboxed iframe** (so the JavaScript really executes), captures **`console.log.md`** from the live run, and rasterises the rendered DOM to **`render.png`** using a 100 % browser-based snapshot (`<foreignObject>` → `<canvas>` → PNG). Both artefacts are fed back to a vision model for an iterative *mount → look → critique → fix* loop. --- ## 📦 The envelope format Every component is **one file**, portable by copy-paste, with **no external resources**: ```html <!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Star Rating</title> <style> /* exactly ONE style block — tokens on :root, component styles scoped to #root */ :root { --brand: #5b8dff; } body { margin: 0; font-family: system-ui, sans-serif; } #root { display: inline-flex; gap: 4px; padding: 16px; } #root .star { cursor: pointer; font-size: 28px; color: #444; } #root .star[aria-checked="true"] { color: var(--brand); } </style> </head> <body> <div id="root" data-component="star-rating"></div> <script type="module"> // exactly ONE module block — modern ES6+, no imports, no external URLs function mount(root, props = {}) { const { max = 5, value = 3, onChange = () => {} } = props; /* … build DOM, wire events … */ return { update(next) {/* … */}, destroy() {/* … */} }; } globalThis.component = { mount }; // reusable entry point mount(document.getElementById("root")); // demo instance for the preview </script> </body> </html> ``` The built-in **linter** enforces this: exactly one `<style>`, exactly one `<script type="module">`, a `#root` element, a `mount(root, props)` entry point, no `http(s)://` `src`/`href`, no remote `import`, no inline `on*` handlers. --- ## 🚀 Getting Started ### Step 1 · Set up your inputs 📝 1. **Notes** — what the component does, its props, states, behaviour and a11y needs. 2. **Design Directives** *(optional)* — palette, spacing scale, radii, typography, dark-mode rules. 3. **Models** — Smart model (authoring), Fast model (edits), Image model (visual review). ### Step 2 · Run the pipeline ⚙️ | # | Step | What it does | |---|------|--------------| | 1 | **▶ Render HTML** | Generates `component.html` from `notes.md` + `style.md`. | | 2 | **📸 Mount & Capture** | Mounts the envelope in an iframe, records console output → `console.log.md`, snapshots the live DOM → `render.png`, writes `render.log.md`. | | 3 | **✏️ Update HTML** | Applies `update-notes.md` to `component.html`. | | 4 | **🔍 Review Render** | Vision model inspects `render.png` + `console.log.md` and rewrites `update-notes.md`. | Then loop **4 → 3 → 2** until it looks and behaves right. Tick **Auto-capture** and every code change re-renders instantly. ### Step 3 · Inspect & export 📤 * **Live preview** re-mounts as you type (debounced) — real DOM, real events, real JS. * **🔎 Lint** validates the envelope contract at any time. * **⬇ Download** / **📋 Copy** the HTML, **⬇ Download PNG** for the raster. --- ## 🎛 Capture Options | Option | Meaning | |--------|---------| | **Viewport** | Width of the preview iframe (360 – 1280 px). Height auto-grows to the content. | | **Scale** | PNG is `viewport × scale`. Total pixels capped (~16 MP) and clamped automatically. | | **Background** | Transparent keeps alpha; White/Dark composites a backdrop — useful for contrast checks. | | **Settle delay** | How long to wait after load before snapshotting (lets async JS finish). | | **Live preview** | Re-mount the iframe while you type. | | **Auto-capture** | Re-capture PNG + console whenever `component.html` changes. | --- ## 💡 Pro Tips * **Keep it self-contained.** External `<img src="https://…">` taints the canvas and breaks the PNG export — inline `data:` URIs instead. * **External references are stripped.** During capture any non-`data:` `src`/`href`/`url()` is inlined if fetchable, otherwise dropped (and reported in `render.log.md`) so the canvas stays exportable. * **Fonts:** only fonts already available to the browser render. Prefer generic stacks — `@font-face` with a remote URL is rejected by the linter. * **Snapshot limits:** the PNG is taken via `<foreignObject>`, so `<canvas>` pixels, `<video>` frames and nested iframes are **not** captured. The linter warns when it sees them. * **Errors are gold:** anything thrown at mount time lands in `console.log.md` and the review step will fix it. * `Ctrl/Cmd+S` saves every editor at once; autosave also runs as you type. * If your session's file API rejects binary uploads, the app writes `render.png.base64.txt` instead and warns you in the capture log — use **⬇ Download PNG** to keep a copy. --- ## 📂 Session files | File | Role | |------|------| | `notes.md` | Your brief (input) | | `style.md` | Design directives (input) | | `update-notes.md` | Revision instructions (written by review, read by update) | | `component.html` | The generated single-file envelope | | `render.png` | Browser snapshot of the mounted component | | `render.log.md` | Capture report: envelope lint, sizes, scale, warnings | | `console.log.md` | Runtime console/error output from the live mount | Happy componentising with **HTML Wizard**! 🧩✨