Validation
A misspelled op does not throw – it renders nothing. Content in the wrong slot of a composite renders placeholders. The validator turns those silent failures into a report an agent can act on.
import { validateNodes, describeOps } from "nodality/validate";
const report = validateNodes([{ op: "dithr", target: ["hero"] }], elements);
{ "ok": false,
"errors": [
{ "code": "UNKNOWN_OP", "path": "nodes[0].op", "got": "dithr",
"suggestions": ["dither"], "valid": ["hexalize", "offset", "flow", "…"] } ],
"warnings": [] }
Each error carries a code, the path that failed, what it got,
did-you-mean suggestions and the valid vocabulary for that position. Pass elements too and every target is checked against real
ids, and the elements themselves are validated.
Common codes:
| Code | Means |
|---|---|
UNKNOWN_OP | No op by that name |
UNKNOWN_PARAM | The op has no such parameter |
UNKNOWN_TARGET | A target id that no element has |
UNKNOWN_ELEMENT_TYPE | An element type that names nothing |
WRONG_CONTENT_SLOT | Content in items where the type reads children, or the reverse |
MISSING_FIELD | A required field, such as an element's type, is absent |
Checking the rendered page
Valid input can still produce a wrong page. checkPage drives a real browser
at a phone and a desktop width and reports in the same shape:
import { checkPage } from "nodality/check"; // needs Playwright in your project
const report = await checkPage(html);
Both are also MCP tools.