Skip to content
Back to skills

Html Craft

ASecurity

Create and verify single-file interactive HTML pages in the sandbox: build or edit the file, then prove the result with headless-Chromium screenshots, in-page DOM/geometry assertions, and JS-error capture (Playwright). No GPU, no service, no network. Use when the user wants an HTML page, animation, demo, dashboard, or a screenshot/verification of an existing HTML file.

  • 61 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 29, 2026
ai-agentspythonrustgoshellbashexpressapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 8 files and shows the line behind each finding

Scanned September 29, 2026

npx -y skills add Elumenotion/GuideAnts --skill html-craft --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Html Craft?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Html Craft
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/elumenotion-html-craft/badge)](https://www.skillsdirectory.com/skills/elumenotion-html-craft)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: html-craft
description: "Create and verify single-file interactive HTML pages in the sandbox: build or edit the file, then prove the result with headless-Chromium screenshots, in-page DOM/geometry assertions, and JS-error capture (Playwright). No GPU, no service, no network. Use when the user wants an HTML page, animation, demo, dashboard, or a screenshot/verification of an existing HTML file."
metadata:
  guideants:
    enabled: true
    display_order: 40
    requires_toolsets: [sandbox]
---

# html-craft

Paths - fixed layout, do not probe or re-derive. The sandbox CWD is the
notebook's **output directory**. This skill's scripts live under
`Skills/html-craft/scripts/` relative to it, so run the commands in this file
exactly as written. Write every deliverable to the CWD with a **bare filename**
(e.g. `-o page.png`): never prefix an output path with `Output/` - the CWD *is*
the output directory, so `Output/...` would create a nested `Output/` folder.

Builds **single-file HTML artifacts** (inline CSS + JS, no build step, no
network) and verifies them the way a user would see them: a real headless
Chromium loads the file, drives it (key presses, clicks, waits), screenshots
the moments that matter, and asserts on the DOM. Everything runs inside the
sandbox: sandbox-venv Python + `playwright` + `openai` SDK + the Chromium binary already in
the image.

## Preflight (cheap; once per session)

```bash
python3 Skills/html-craft/scripts/preflight.py
```

Prints one JSON verdict: `{"scenario", "open": bool, "blockers": [...],
"warnings": [...], "evidence": {...}}` after a live 320x200 render.
`open: false` - stop and report the blockers; do not guess browser paths.

## Commands

```bash
python3 Skills/html-craft/scripts/html_craft.py probe  PAGE
python3 Skills/html-craft/scripts/html_craft.py shot   PAGE -o name.png
python3 Skills/html-craft/scripts/html_craft.py text   PAGE --sel "#el" [--sel "#el2"]
python3 Skills/html-craft/scripts/html_craft.py eval   PAGE "document.title"
python3 Skills/html-craft/scripts/html_craft.py compare A.png B.png -o cmp.png
python3 Skills/html-craft/scripts/vision_qa.py  NAME.png --ask "1) ... 2) ..." --label "..."
```

Drive flags shared by `probe` / `shot` / `text` / `eval`:

| Flag | Meaning |
|------|---------|
| `--action "press:Space"` | repeatable, applied in order: `press:KEY`, `click:SELECTOR`, `wait:MS` |
| `--wait MS` | settle after page load (default 700) |
| `--settle MS` | wait after each action (default 1200) |
| `--viewport WxH` | default `1280x800` |
| `--full-page` | `shot`: capture the full scrollable page |
| `--timeout MS` | navigation timeout (default 60000) |
| `--browser PATH` | chromium binary; else `$HTML_CRAFT_BROWSER`; else auto-find |

Every page command prints one JSON object including `pageerrors` (uncaught JS
exceptions) and `console_errors`. Treat a non-empty `pageerrors` as a failure
even when the screenshot looks right.

## The build-verify loop (every time, in this order)

1. **Read the whole source first.** For an existing file, read it end-to-end
   before touching anything - phases, timing constants, key handlers, IDs.
   Every verification wait must come from the page's own `TIMING`/phase
   lengths, never from guessing.
2. **Minimal-diff edits.** Change only what the request names. If the user
   asked for *one element* bigger, make that element bigger - do not
   rearrange the layout, move panels, or restructure the DOM "while at it".
   Before moving on, diff your edit against the original (`diff -u`) and
   confirm every hunk maps to the request.
3. **`probe`** - the file loads with zero `pageerrors`.
4. **`shot` the key states.** Drive the page like a user via `--action` (its
   own key handlers). For animations, screenshot each phase/state - not just
   one frame.
5. **Assert, don't eyeball.** `text` for visible copy; `eval` for geometry.
   Measure in **screen pixels** (`getBoundingClientRect`, or `getCTM()` +
   `getBBox()` for SVG) - never trust source units, because CSS/SVG scaling
   changes what the user actually sees. Audit rendered `font-size` values to
   catch invisible shrink-to-fit: a `fitText`-style scaler silently makes
   text 6 px unless you check the final attribute.
6. **Sweep every state.** If the page has N turns/steps, verify all N - the
   failure mode (overflow, overlap, clipping) usually shows up in the
   *fullest* state, not the first.
7. **Vision QA the key states.** `vision_qa.py` on the screenshots with
   specific numbered checks (see "Vision QA" below) - the second opinion on
   what the measurements produce.
8. **`compare` before/after** when editing an existing file, so the delta is
   provable.
9. **Report** the deliverable (bare CWD name) plus the screenshots, embedded
   with `Output/...` notebook-tree paths, and the JSON evidence (pageerrors
   empty, measured sizes, vision PASS/FAIL bullets).

## Driving animations like a user

- Use the page's own handlers: if it listens for Space/Enter/R/A,
  `--action "press:Space"` fires the real code path - no DOM hacking.
- Time waits from the source: with phases `show:3.0, fold:3.2, crank:4.6`,
  the crank phase is ~6.2-7.8 s after the press
  (`--action "press:Space" --action "wait:7000"`).
- One `shot` call per state. Five states = five calls; cleaner than one
  long-running sweep.

## In-page assertion recipes

Copy-paste `eval` expressions - SVG-to-screen geometry, font-size audit,
overlap checks, state sweeps: `references/verify-recipes.md`.

## Vision QA (after Playwright, on the screenshots)

Playwright proves the page *works*; the Wire vision model proves it *looks
right*. Run `vision_qa.py` on the screenshots from step 4 - each one already
on disk, one call per state:

```bash
python3 Skills/html-craft/scripts/vision_qa.py t1.png \
  --ask "1) Is all text on the paper sheet legible? 2) Does any element clip or overlap another? 3) Is the highlighted question clearly marked?" \
  --label "INTAKE frame: conversation sheet held over machine hopper"
```

Prints one JSON object: `{"ok": true, "review": "...", "usage": {...}}`.
The `review` is the model's answer in the tool's fixed PASS/FAIL bullet
format. `ok: false` carries the error and a hint.

**Wire prompt discipline - non-negotiable.** The Wire endpoint routes the
prompt to an *agentic* thread: a vague "critique this image" gave it license
to keep doing unrequested remediation work, and the call ran until the
platform killed it at its 30-minute timeout. The tool enforces the safe
shape - read-only boilerplate, numbered checks only, PASS/FAIL format,
capped bullets, capped `max_tokens` - and never relax it:

- Ask **numbered, answerable checks**, one per thing you care about
  ("Is X legible?", "Does A overlap B?") - never "critique", "review",
  or "improve this".
- **Read-only:** the prompt must not invite fixes, rewrites, or alternatives.
  (The tool's boilerplate states this explicitly.)
- **Small `max_tokens` (default 250).** Long generations on this endpoint
  hang; bounded output is what keeps the call in seconds, not hours.
- **One state per call.** Don't batch five screenshots into one prompt.
- **Retries are capped:** on a timeout, make the checks more specific and
  retry **once** with smaller `max_tokens`; do not loop. A hung call is a
  prompt problem, not a flake.

**Interpreting vision output:** the model can misread subtle styling (it
once described a highlight box as an underline) and has no motion context
(animations read as "disconnected" in stills). Treat each FAIL bullet as a
*hypothesis*: re-check the specific pixel region with `html_craft.py eval`
/ a zoomed crop before acting. Playwright measurements stay the source of
truth; vision is the second opinion on what those measurements produce.

## Failure modes

| Symptom | Cause / fix |
|---------|-------------|
| `file not found` for a real file | relative path or a guessed absolute path - pass the file as the CWD sees it; the tool resolves it to absolute and re-checks |
| `ERR_FILE_NOT_FOUND` inside Chromium | same root cause: `file://` needs a real absolute path *in the sandbox*, not a host path |
| `no chromium binary found` | `preflight.py` evidence lists the roots scanned; set `HTML_CRAFT_BROWSER` to the binary |
| launch crash / SIGTRAP | the tool always passes `--no-sandbox --disable-dev-shm-usage`; if it still dies, point `HTML_CRAFT_BROWSER` at a `chromium_headless_shell` build |
| `pageerrors` non-empty but the shot looks right | trust the errors - the exception can kill a phase *after* the captured frame |
| measured text smaller than the source font | a fit-to-width scaler is shrinking it - read the final `font-size` attribute and raise the wrap budget (verify-recipes.md) |
| `vision_qa.py` hangs / platform 30-min timeout | the prompt was vague and the Wire thread improvised work - rerun with specific numbered checks, `--max-tokens 250` (or less), and never retry more than once |
| `vision_qa.py` says `ok: false - OPENAI_API_KEY / OPENAI_BASE_URL not set` | the guide's environment variables are missing - set them in the guide editor (not secret values here: the key IS the secret) |
| vision FAILs a thing Playwright measured fine | the model misread (common with subtle styling / no motion context) - confirm with a zoomed crop or `eval` before changing the asset |

## Reporting

State the deliverable filename (bare, CWD), what you verified (number of
states swept, pageerrors, measured pixel sizes), and show the screenshots -
embedded in the reply via `Output/<name>` notebook-tree paths. If a state
failed, show the failing state's shot and the exact measured number that is
off.

Files in this skill

  • README.md3.5 KB
  • SKILL.md9.4 KB
  • references/verify-recipes.md3 KB
  • scripts/fixture.html745 B
  • scripts/html_craft.py7.3 KB
  • scripts/preflight.py4.4 KB
  • scripts/test_html_craft.sh2.4 KB
  • scripts/vision_qa.py4.3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.