nodality 1.2.5 → 1.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API.md +8 -4
- package/README.md +15 -1
- package/bin/install-skill.mjs +160 -0
- package/bin/nodality.js +12 -0
- package/dist/animator.cjs.js +1 -1
- package/dist/animator.cjs.js.LICENSE.txt +1 -1
- package/dist/animator.esm.js +1 -1
- package/dist/animator.esm.js.LICENSE.txt +1 -1
- package/dist/audionew.cjs.js +1 -1
- package/dist/audionew.cjs.js.LICENSE.txt +1 -1
- package/dist/audionew.esm.js +1 -1
- package/dist/audionew.esm.js.LICENSE.txt +1 -1
- package/dist/base.cjs.js +1 -1
- package/dist/base.cjs.js.LICENSE.txt +1 -1
- package/dist/base.esm.js +1 -1
- package/dist/base.esm.js.LICENSE.txt +1 -1
- package/dist/beta-desktop-bar.cjs.js +1 -1
- package/dist/beta-desktop-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/beta-desktop-bar.esm.js +1 -1
- package/dist/beta-desktop-bar.esm.js.LICENSE.txt +1 -1
- package/dist/beta-mobile-bar.cjs.js +1 -1
- package/dist/beta-mobile-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/beta-mobile-bar.esm.js +1 -1
- package/dist/beta-mobile-bar.esm.js.LICENSE.txt +1 -1
- package/dist/bundle.umd.js +1 -1
- package/dist/bundle.umd.js.LICENSE.txt +1 -1
- package/dist/button.cjs.js +1 -1
- package/dist/button.cjs.js.LICENSE.txt +1 -1
- package/dist/button.esm.js +1 -1
- package/dist/button.esm.js.LICENSE.txt +1 -1
- package/dist/card-getter.cjs.js.LICENSE.txt +1 -1
- package/dist/card-getter.esm.js.LICENSE.txt +1 -1
- package/dist/center.cjs.js +1 -1
- package/dist/center.cjs.js.LICENSE.txt +1 -1
- package/dist/center.esm.js +1 -1
- package/dist/center.esm.js.LICENSE.txt +1 -1
- package/dist/checkbox.cjs.js +1 -1
- package/dist/checkbox.cjs.js.LICENSE.txt +1 -1
- package/dist/checkbox.esm.js +1 -1
- package/dist/checkbox.esm.js.LICENSE.txt +1 -1
- package/dist/code.cjs.js +1 -1
- package/dist/code.cjs.js.LICENSE.txt +1 -1
- package/dist/code.esm.js +1 -1
- package/dist/code.esm.js.LICENSE.txt +1 -1
- package/dist/container.cjs.js +1 -1
- package/dist/container.cjs.js.LICENSE.txt +1 -1
- package/dist/container.esm.js +1 -1
- package/dist/container.esm.js.LICENSE.txt +1 -1
- package/dist/data-list.cjs.js.LICENSE.txt +1 -1
- package/dist/data-list.esm.js.LICENSE.txt +1 -1
- package/dist/designer.cjs.js +1 -1
- package/dist/designer.cjs.js.LICENSE.txt +1 -1
- package/dist/designer.esm.js +1 -1
- package/dist/designer.esm.js.LICENSE.txt +1 -1
- package/dist/element-mapper.cjs.js +1 -1
- package/dist/element-mapper.cjs.js.LICENSE.txt +1 -1
- package/dist/element-mapper.esm.js +1 -1
- package/dist/element-mapper.esm.js.LICENSE.txt +1 -1
- package/dist/finalresult.esm.js +1 -1
- package/dist/finalresult.esm.js.LICENSE.txt +1 -1
- package/dist/flex-card.cjs.js +1 -1
- package/dist/flex-card.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-card.esm.js +1 -1
- package/dist/flex-card.esm.js.LICENSE.txt +1 -1
- package/dist/flex-grid.cjs.js +1 -1
- package/dist/flex-grid.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-grid.esm.js +1 -1
- package/dist/flex-grid.esm.js.LICENSE.txt +1 -1
- package/dist/flex-row.cjs.js +1 -1
- package/dist/flex-row.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-row.esm.js +1 -1
- package/dist/flex-row.esm.js.LICENSE.txt +1 -1
- package/dist/floating-input.cjs.js +1 -1
- package/dist/floating-input.cjs.js.LICENSE.txt +1 -1
- package/dist/floating-input.esm.js +1 -1
- package/dist/floating-input.esm.js.LICENSE.txt +1 -1
- package/dist/free.cjs.js +1 -1
- package/dist/free.cjs.js.LICENSE.txt +1 -1
- package/dist/free.esm.js +1 -1
- package/dist/free.esm.js.LICENSE.txt +1 -1
- package/dist/horizontal-scroller.cjs.js.LICENSE.txt +1 -1
- package/dist/horizontal-scroller.esm.js.LICENSE.txt +1 -1
- package/dist/image-picker.cjs.js +1 -1
- package/dist/image-picker.cjs.js.LICENSE.txt +1 -1
- package/dist/image-picker.esm.js +1 -1
- package/dist/image-picker.esm.js.LICENSE.txt +1 -1
- package/dist/image.cjs.js +1 -1
- package/dist/image.cjs.js.LICENSE.txt +1 -1
- package/dist/image.esm.js +1 -1
- package/dist/image.esm.js.LICENSE.txt +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.LICENSE.txt +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.LICENSE.txt +1 -1
- package/dist/keyframe-animation.cjs.js.LICENSE.txt +1 -1
- package/dist/keyframe-animation.esm.js.LICENSE.txt +1 -1
- package/dist/link-getter.cjs.js +1 -1
- package/dist/link-getter.cjs.js.LICENSE.txt +1 -1
- package/dist/link-getter.esm.js +1 -1
- package/dist/link-getter.esm.js.LICENSE.txt +1 -1
- package/dist/link.cjs.js +1 -1
- package/dist/link.cjs.js.LICENSE.txt +1 -1
- package/dist/link.esm.js +1 -1
- package/dist/link.esm.js.LICENSE.txt +1 -1
- package/dist/meta-adder.cjs.js +1 -1
- package/dist/meta-adder.cjs.js.LICENSE.txt +1 -1
- package/dist/meta-adder.esm.js +1 -1
- package/dist/meta-adder.esm.js.LICENSE.txt +1 -1
- package/dist/modal-2025.cjs.js +1 -1
- package/dist/modal-2025.cjs.js.LICENSE.txt +1 -1
- package/dist/modal-2025.esm.js +1 -1
- package/dist/modal-2025.esm.js.LICENSE.txt +1 -1
- package/dist/multiswitcher.cjs.js +1 -1
- package/dist/multiswitcher.cjs.js.LICENSE.txt +1 -1
- package/dist/multiswitcher.esm.js +1 -1
- package/dist/multiswitcher.esm.js.LICENSE.txt +1 -1
- package/dist/new-nav-bar.cjs.js +1 -1
- package/dist/new-nav-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/new-nav-bar.esm.js +1 -1
- package/dist/new-nav-bar.esm.js.LICENSE.txt +1 -1
- package/dist/picker.cjs.js +1 -1
- package/dist/picker.cjs.js.LICENSE.txt +1 -1
- package/dist/picker.esm.js +1 -1
- package/dist/picker.esm.js.LICENSE.txt +1 -1
- package/dist/progress.cjs.js +1 -1
- package/dist/progress.cjs.js.LICENSE.txt +1 -1
- package/dist/progress.esm.js +1 -1
- package/dist/progress.esm.js.LICENSE.txt +1 -1
- package/dist/radio.cjs.js.LICENSE.txt +1 -1
- package/dist/radio.esm.js.LICENSE.txt +1 -1
- package/dist/range.cjs.js.LICENSE.txt +1 -1
- package/dist/range.esm.js.LICENSE.txt +1 -1
- package/dist/scroll-video.cjs.js.LICENSE.txt +1 -1
- package/dist/scroll-video.esm.js.LICENSE.txt +1 -1
- package/dist/side-bar.cjs.js +1 -1
- package/dist/side-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/side-bar.esm.js +1 -1
- package/dist/side-bar.esm.js.LICENSE.txt +1 -1
- package/dist/side-nav-bar.cjs.js +1 -1
- package/dist/side-nav-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/side-nav-bar.esm.js +1 -1
- package/dist/side-nav-bar.esm.js.LICENSE.txt +1 -1
- package/dist/simple-bar.cjs.js +1 -1
- package/dist/simple-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/simple-bar.esm.js +1 -1
- package/dist/simple-bar.esm.js.LICENSE.txt +1 -1
- package/dist/slider-2025.cjs.js +1 -1
- package/dist/slider-2025.cjs.js.LICENSE.txt +1 -1
- package/dist/slider-2025.esm.js +1 -1
- package/dist/slider-2025.esm.js.LICENSE.txt +1 -1
- package/dist/spacer.cjs.js +1 -1
- package/dist/spacer.cjs.js.LICENSE.txt +1 -1
- package/dist/spacer.esm.js +1 -1
- package/dist/spacer.esm.js.LICENSE.txt +1 -1
- package/dist/stack.cjs.js +1 -1
- package/dist/stack.cjs.js.LICENSE.txt +1 -1
- package/dist/stack.esm.js +1 -1
- package/dist/stack.esm.js.LICENSE.txt +1 -1
- package/dist/stacker.cjs.js.LICENSE.txt +1 -1
- package/dist/stacker.esm.js.LICENSE.txt +1 -1
- package/dist/table.cjs.js +1 -1
- package/dist/table.cjs.js.LICENSE.txt +1 -1
- package/dist/table.esm.js +1 -1
- package/dist/table.esm.js.LICENSE.txt +1 -1
- package/dist/text-field.cjs.js +1 -1
- package/dist/text-field.cjs.js.LICENSE.txt +1 -1
- package/dist/text-field.esm.js +1 -1
- package/dist/text-field.esm.js.LICENSE.txt +1 -1
- package/dist/text.cjs.js +1 -1
- package/dist/text.cjs.js.LICENSE.txt +1 -1
- package/dist/text.esm.js +1 -1
- package/dist/text.esm.js.LICENSE.txt +1 -1
- package/dist/theme.cjs.js.LICENSE.txt +1 -1
- package/dist/theme.esm.js.LICENSE.txt +1 -1
- package/dist/transform-anim.cjs.js.LICENSE.txt +1 -1
- package/dist/transform-anim.esm.js.LICENSE.txt +1 -1
- package/dist/ulist.cjs.js +1 -1
- package/dist/ulist.cjs.js.LICENSE.txt +1 -1
- package/dist/ulist.esm.js +1 -1
- package/dist/ulist.esm.js.LICENSE.txt +1 -1
- package/dist/video.cjs.js +1 -1
- package/dist/video.cjs.js.LICENSE.txt +1 -1
- package/dist/video.esm.js +1 -1
- package/dist/video.esm.js.LICENSE.txt +1 -1
- package/dist/wrap.cjs.js +1 -1
- package/dist/wrap.cjs.js.LICENSE.txt +1 -1
- package/dist/wrap.esm.js +1 -1
- package/dist/wrap.esm.js.LICENSE.txt +1 -1
- package/dist/zoom-card.cjs.js +1 -1
- package/dist/zoom-card.cjs.js.LICENSE.txt +1 -1
- package/dist/zoom-card.esm.js +1 -1
- package/dist/zoom-card.esm.js.LICENSE.txt +1 -1
- package/layout/animator.js +13 -2
- package/layout/audio.js +1 -1
- package/layout/audionew.js +1 -1
- package/layout/base.js +1 -1
- package/layout/beta-desktop-bar.js +1 -1
- package/layout/beta-mobile-bar.js +1 -1
- package/layout/button.js +1 -1
- package/layout/center.js +1 -1
- package/layout/checkbox.js +1 -1
- package/layout/circle.js +1 -1
- package/layout/code.js +1 -1
- package/layout/container.js +1 -1
- package/layout/dropdown-2025.js +1 -1
- package/layout/flex-card.js +1 -1
- package/layout/flex-grid.js +1 -1
- package/layout/flex-row.js +1 -1
- package/layout/form-components/custom.js +1 -1
- package/layout/form-components/data-list.js +1 -1
- package/layout/form-components/floating-input.js +1 -1
- package/layout/form-components/form-all.js +1 -1
- package/layout/form-components/form.js +1 -1
- package/layout/form-components/image-picker.js +1 -1
- package/layout/form-components/picker.js +1 -1
- package/layout/form-components/radio.js +1 -1
- package/layout/form-components/radiogroup.js +1 -1
- package/layout/form-components/range.js +1 -1
- package/layout/free.js +1 -1
- package/layout/grid-switcher.js +1 -1
- package/layout/grid.js +1 -1
- package/layout/horizontal-scroller.js +1 -1
- package/layout/image.js +1 -1
- package/layout/index.js +1 -1
- package/layout/link.js +1 -1
- package/layout/list.js +1 -1
- package/layout/meta-adder.js +1 -1
- package/layout/modal-2025.js +1 -1
- package/layout/morph.js +1 -1
- package/layout/multiswitcher.js +1 -1
- package/layout/nav-bar.js +1 -1
- package/layout/nav-factor/custom-div.js +1 -1
- package/layout/new-nav-bar.js +1 -1
- package/layout/polygon.js +1 -1
- package/layout/prerender-site.js +1 -1
- package/layout/prerender.js +1 -1
- package/layout/progress.js +1 -1
- package/layout/row.js +1 -1
- package/layout/scroll-video.js +1 -1
- package/layout/side-bar.js +1 -1
- package/layout/side-nav-bar.js +1 -1
- package/layout/simple-bar.js +1 -1
- package/layout/slider-2025.js +1 -1
- package/layout/spacer.js +1 -1
- package/layout/stack.js +1 -1
- package/layout/svg.js +1 -1
- package/layout/switcher.js +1 -1
- package/layout/table.js +1 -1
- package/layout/text-field.js +1 -1
- package/layout/text.js +1 -1
- package/layout/ulist.js +1 -1
- package/layout/video.js +1 -1
- package/layout/wrap.js +1 -1
- package/layout/zoom-card.js +1 -1
- package/lib/agent-surface.js +1 -1
- package/lib/card-getter.js +1 -1
- package/lib/codegen.js +1 -1
- package/lib/data.js +1 -1
- package/lib/designer.js +6 -2
- package/lib/element-mapper.js +5 -5
- package/lib/keyframe-animation.js +1 -1
- package/lib/link-getter.js +1 -1
- package/lib/morph-node.js +1 -1
- package/lib/raster-inspect.js +1 -1
- package/lib/raster-ops.js +1 -1
- package/lib/raster-presets.js +1 -1
- package/lib/scroll-video.js +1 -1
- package/lib/seo.js +1 -1
- package/lib/stacker.js +1 -1
- package/lib/suggest.js +1 -1
- package/lib/theme.js +1 -1
- package/lib/transform-anim.js +1 -1
- package/lib/transition.js +1 -1
- package/lib/validate-nodes.js +107 -2
- package/lib/webmcp-adapter.js +1 -1
- package/package.json +3 -2
- package/skills/nodality/SKILL.md +203 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nodality
|
|
3
|
+
description: Build or edit a page with the Nodality library – declarative static UI from two arrays (elements + nodes), GPU raster effects, morph navigation graphs, prerendering, and agent surfaces. Use when the user asks to create or change a Nodality page, mentions (E, N), Des(), morph/raster/agent-surface nodes, works with imperative Nodality code (new Text(), new Link(), .render()), or asks to draft a landing page with Nodality.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Working with Nodality
|
|
7
|
+
|
|
8
|
+
Nodality builds static, content-shaped sites from a pair of plain-data
|
|
9
|
+
arrays. You do not write components, CSS files, or DOM code. You write
|
|
10
|
+
data, and the library compiles it.
|
|
11
|
+
|
|
12
|
+
```js
|
|
13
|
+
import { Des } from "nodality";
|
|
14
|
+
|
|
15
|
+
const elements = [ // E – what exists
|
|
16
|
+
{ id: "hero", type: "h1", text: "Hello" },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const nodes = [ // N – what is done to it
|
|
20
|
+
{ op: { name: "gradient", gradient: "linear-gradient(90deg, #1d6fe0, #7fd1ff)" },
|
|
21
|
+
target: ["hero"] },
|
|
22
|
+
{ op: "dither", target: ["hero"], levels: 6, size: 2 },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
new Des().nodes(nodes).add(elements).set({ mount: "#mount" });
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Nothing in `elements` names an effect; nothing in `nodes` names a
|
|
29
|
+
component. The two arrays meet only through `target`, `from`, and `to`,
|
|
30
|
+
each naming an element `id` (bare `"hero"` or selector form `"#hero"`).
|
|
31
|
+
Keep that separation absolute: if you find yourself putting styling in E
|
|
32
|
+
or content in N, you are writing it wrong.
|
|
33
|
+
|
|
34
|
+
## The workflow – always in this order
|
|
35
|
+
|
|
36
|
+
The `nodality` MCP server is the source of truth for the vocabulary.
|
|
37
|
+
This skill deliberately contains **no op tables and no element-type
|
|
38
|
+
lists**: those come from the live registry via the MCP, so they cannot
|
|
39
|
+
drift. If the MCP is not configured, add it:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{ "mcpServers": { "nodality": { "command": "npx", "args": ["nodality", "mcp"] } } }
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
1. **`list_ops` first.** Never guess an op name, a parameter, an easing
|
|
46
|
+
name, a transition preset, or an element type. One call returns all
|
|
47
|
+
of them as data.
|
|
48
|
+
2. **Author the pair.** E top-down (page structure), then N (what
|
|
49
|
+
happens to it). Small pages fit in one file.
|
|
50
|
+
3. **`validate_nodes` before showing the user anything.** Pass both
|
|
51
|
+
`nodes` AND `elements` – with elements included, targets are checked
|
|
52
|
+
against real ids and E itself is validated. The report never throws;
|
|
53
|
+
repair from its `did-you-mean` suggestions and re-validate until
|
|
54
|
+
clean.
|
|
55
|
+
4. **`preview` to render.** It writes a self-contained HTML file through
|
|
56
|
+
the jsdom prerenderer. Know the boundary: the file is prerendered DOM
|
|
57
|
+
and morph scaffolding only and carries no runtime, so raster effects
|
|
58
|
+
and transitions will not run from it. To see them, put the pair in a
|
|
59
|
+
real page with the library loaded (the CDN snippet is enough).
|
|
60
|
+
|
|
61
|
+
Skipping step 3 is the classic failure: a misspelled op renders
|
|
62
|
+
*nothing* rather than erroring, so the page looks plausible and is
|
|
63
|
+
silently missing its effects.
|
|
64
|
+
|
|
65
|
+
## The four node families
|
|
66
|
+
|
|
67
|
+
Told apart by the shape of `op`:
|
|
68
|
+
|
|
69
|
+
| Family | Shape | Example |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| Design | `op` is an object, or one of seven shorthand strings | `{ op: { name: "shadow" }, target: ["card"] }` |
|
|
72
|
+
| Raster | `op` is any other string | `{ op: "dither", target: ["hero"], levels: 6 }` |
|
|
73
|
+
| Morph | `op: "morph"` | one transition, or a whole graph via `chain` |
|
|
74
|
+
| Agent surface | `op: "agent-surface"` | exposes the page to AI agents as tools |
|
|
75
|
+
|
|
76
|
+
**The design family has two shapes.** The object form takes its options
|
|
77
|
+
inside `op`. The seven shorthand names – `blast`, `gradient`, `shadow`,
|
|
78
|
+
`filter`, `animation`, `transform`, `span` – expand against a table of
|
|
79
|
+
defaults, so `{ op: "gradient" }` is a whole valid node. Only the
|
|
80
|
+
shorthand accepts `gradient`, `filter`, `color` and `width` as top-level
|
|
81
|
+
keys, because its expansion lifts them into the op it substitutes. Any
|
|
82
|
+
other string is a raster op.
|
|
83
|
+
|
|
84
|
+
Rules that are not obvious from the schema:
|
|
85
|
+
|
|
86
|
+
- **Raster ops compose.** Several raster nodes aimed at the same element
|
|
87
|
+
become ONE shader pass, applied in array order. Order matters; do not
|
|
88
|
+
"fix" a wrong-looking result by duplicating nodes.
|
|
89
|
+
- **A morph `chain` is a list of EDGES, not keyframes.** Edge two is
|
|
90
|
+
reachable *from* the state edge one lands on – a landed view becomes a
|
|
91
|
+
source. Node-level settings (`effect`, `duration`) are defaults each
|
|
92
|
+
edge may override. `chain` wins outright: node-level `from`/`to` are
|
|
93
|
+
ignored beside it. `back: true` unwinds the path the user actually
|
|
94
|
+
took, not a lookup of a reverse edge.
|
|
95
|
+
- **`agent-surface` is opt-in and allow-listed.** No form is exposed
|
|
96
|
+
unless named in `forms`. Do not add it unless the user asks for an
|
|
97
|
+
agent-operable page.
|
|
98
|
+
|
|
99
|
+
A complete navigation graph is one node:
|
|
100
|
+
|
|
101
|
+
```js
|
|
102
|
+
{ op: "morph", effect: "t-vhs", duration: 620, back: true,
|
|
103
|
+
chain: [
|
|
104
|
+
{ from: "home", to: { Work: "work", Contact: "contact" } },
|
|
105
|
+
{ from: "work", to: { Aurora: "aurora" }, effect: "t-split" },
|
|
106
|
+
{ from: "aurora", to: { Contact: "contact" }, effect: "t-bloom" },
|
|
107
|
+
] }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## House rules – violations are bugs even when the page looks right
|
|
111
|
+
|
|
112
|
+
- **Never touch the DOM to style or fix a Nodality page.** No
|
|
113
|
+
`el.style.*`, no `createElement` in page code, no post-render DOM
|
|
114
|
+
patching. If the library cannot express something, the fix is a custom
|
|
115
|
+
element/op (extend the library), or the `keySet` option on an element
|
|
116
|
+
(`keySet: { key, value }`) for one custom CSS property. Note the
|
|
117
|
+
spelling: `keySet`, capital S.
|
|
118
|
+
- **Elements take `text`, never `value`.**
|
|
119
|
+
- **Every element that a node targets needs an `id`.** Short and stable
|
|
120
|
+
(`"hero"`, `"topnav"`); ids are the joint between the two arrays and
|
|
121
|
+
appear in generated code.
|
|
122
|
+
- **Know where options live.** Raster-op options sit on the node
|
|
123
|
+
(`levels: 6`); design-node options sit INSIDE the `op` object
|
|
124
|
+
(`op: { name: "gradient", gradient: "linear-gradient(...)" }`).
|
|
125
|
+
Putting a design option at the top level is the single most common
|
|
126
|
+
mistake with this library – the project's own README shipped
|
|
127
|
+
`colors: [...]` there and rendered its headline invisible. Since 1.2.7
|
|
128
|
+
`validate_nodes` reports it and tells you where it belongs, so run the
|
|
129
|
+
validator rather than trusting the shape by eye.
|
|
130
|
+
- **Do not invent options.** An option that no op declares is ignored in
|
|
131
|
+
silence rather than reported. If `list_ops` does not name it, it does
|
|
132
|
+
not exist.
|
|
133
|
+
- **Codegen:** the on-page panel showing the imperative equivalent of
|
|
134
|
+
the pair is on by default; pass `code: false` (and `elements: false`)
|
|
135
|
+
to `.set()` to hide it on a production page. From the CLI,
|
|
136
|
+
`npx nodality compile src/<file>.js` emits the same code as a
|
|
137
|
+
companion file without rendering anything.
|
|
138
|
+
|
|
139
|
+
## The imperative layer – direct instantiation
|
|
140
|
+
|
|
141
|
+
The component classes behind E are public API, exported from the package
|
|
142
|
+
root. An agent can instantiate them directly instead of writing the
|
|
143
|
+
pair:
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
import { Text, Link, FlexRow } from "nodality";
|
|
147
|
+
|
|
148
|
+
new Text("Hello").set({ fluidc: "S3", color: "#f97316" }).render("#mount");
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
This is exactly the code the codegen panel emits, so the two forms are
|
|
152
|
+
equivalent and interchangeable: `.set()` returns the instance, and
|
|
153
|
+
`.render(selector)` mounts it. Reach for it when adding a few elements
|
|
154
|
+
to an existing page or adapting generated code; prefer the (E, N) pair
|
|
155
|
+
for whole pages, because only the pair gets `validate_nodes`, morphs,
|
|
156
|
+
prerendering, and the agent surface – imperative code is not validated.
|
|
157
|
+
|
|
158
|
+
One naming caution: `Text` and `Image` collide with DOM constructor
|
|
159
|
+
names. Always use the module import; on a page using the CDN globals,
|
|
160
|
+
never assume `window.Text` / `window.Image` are still the DOM's own.
|
|
161
|
+
|
|
162
|
+
## Verifying your work
|
|
163
|
+
|
|
164
|
+
- **Verify a morph by progress, not by DOM presence.** The destination
|
|
165
|
+
view is inserted before capture begins, so "the element exists" passes
|
|
166
|
+
even when the transition hangs. Assert that the animation *progressed*
|
|
167
|
+
(or landed state + painted output), and unwind with `back`/`go_back`
|
|
168
|
+
to check the reverse path.
|
|
169
|
+
- **Add a negative control.** When you write a check, break the thing
|
|
170
|
+
once and confirm the check fails; a check that cannot fail is not a
|
|
171
|
+
check.
|
|
172
|
+
- **Prerender caveat:** the jsdom build silently drops CSS `min()` /
|
|
173
|
+
`clamp()`. If the design depends on them, verify in a real browser,
|
|
174
|
+
not in the preview file.
|
|
175
|
+
|
|
176
|
+
## Static site generation
|
|
177
|
+
|
|
178
|
+
`npx nodality prerender` interprets the same pair at build time: it
|
|
179
|
+
emits crawlable HTML, a sitemap, `hreflang` alternates, and JSON-LD. The
|
|
180
|
+
browser then re-reads the pair and rebuilds on top – the pair is
|
|
181
|
+
*shipped, not consumed*. `jsdom` must be present in the project
|
|
182
|
+
(deliberately not bundled). Builds are deterministic: the same pair
|
|
183
|
+
yields byte-identical output, so diffing two builds is a valid check.
|
|
184
|
+
|
|
185
|
+
## When NOT to use Nodality
|
|
186
|
+
|
|
187
|
+
Static, content-shaped sites: marketing pages, storefronts,
|
|
188
|
+
documentation, brochures. It is not a component framework with
|
|
189
|
+
client-side state management. If the user needs an app (auth, live
|
|
190
|
+
data, complex client state), say so and recommend an app framework
|
|
191
|
+
instead of stretching Nodality.
|
|
192
|
+
|
|
193
|
+
## References
|
|
194
|
+
|
|
195
|
+
- Docs: https://nodalityjs.github.io – machine index at
|
|
196
|
+
https://nodalityjs.github.io/llms.txt
|
|
197
|
+
- `node_modules/nodality/API.md` ships in the package: the full page
|
|
198
|
+
index with one-line summaries, readable offline.
|
|
199
|
+
- Copy-paste-ready full morph page:
|
|
200
|
+
https://nodalityjs.github.io/docs/raster/morph (section "A complete
|
|
201
|
+
page you can paste").
|
|
202
|
+
- Validator without MCP:
|
|
203
|
+
`import { validateNodes, describeOps } from "nodality/validate"`.
|