§ Atlas docs · Manifest reference
The schema is the contract.
Six fields at the top. Seven on every block. Read this once and you have the whole surface.
The shape
A manifest is a JSON object the compiler emits and the plugin reads. The
top level is AtlasFormat; the leaves are
BlockNodes nested through innerBlocks. There is
no second representation, no intermediate cache, no editor state to
reconcile.
{ "meta": { "name": "home", "version": "0.4.2", "platform": "wordpress", "wpVersion": "6.4", "atlasVersion": "0.4.2" }, "tokens": { /* colors, typography, spacing, radii, shadows */ }, "layout": { "templates": { "home": { "blocks": [ /* BlockNode[] */ ] } } }, "motion": { "presets": { ... }, "easings": { ... } }, "validation": { "rules": [ /* ValidationRule[] */ ] } }
Top-level fields
- meta
- Identity for the manifest itself.
name,version,platform: "wordpress",wpVersion,atlasVersion. The plugin usesatlasVersionto decide whether it knows how to render this manifest. - tokens
- Design tokens scoped to this manifest — colors, typography, spacing, radii, shadows. Resolved into CSS custom properties at render time and emitted on the block's root element. Keeps a manifest portable across themes.
- layout
- The block tree.
templatesis required;partsandpatternsare optional. Each is a record of named{ blocks: BlockNode[] }collections — the atomic shape every renderer walks. - motion
- Animation presets and easings shared across the manifest. Presets pick from a fixed set (
fade-in,slide-up,zoom-in, …); easings pick from a fixed set (ease-out,spring,snap, …). Components reference them by name; the runtime resolves them through GSAP. - validation
- A list of rules the compiler runs against the block tree before emitting the manifest. Built-in rule IDs include
heading-hierarchy,image-alt-required,color-contrast,max-nesting-depth. A failing rule with severityerroraborts the build. - runtime
- Optional. Per-manifest runtime hooks — extra
css, extrajs, and agsapopt-in flag. Most manifests leave this off. Use it when a block needs CSS or JS that is not expressible as tokens or motion presets.
BlockNode
Every entry in layout.templates[*].blocks is a
BlockNode. The shape mirrors WordPress\'s native block
JSON — Atlas wraps it, it does not replace it. That is why one block
inside Atlas can compose with any block WordPress ships natively.
- type
- The block type — a namespaced string like
core/heading,core/paragraph, oratlas/hero. The plugin looks up the renderer by this key. Unknown types render theirinnerHTMLverbatim and emit a console warning. - attrs
- The block's typed attributes — the data the renderer needs to produce HTML. Shape varies by
type; the compiler validates each block'sattrsagainst the schema registered for that type. - innerHTML
- The HTML the compiler emitted for this node, captured at compile time. The renderer uses it as the canonical output and as the graceful-degradation fallback when something downstream fails.
- innerBlocks
- Child
BlockNodes. The same shape applies at every depth. Composition is recursion — there is no separate container or wrapper type. - innerContent
- Optional. Interleaving array of strings and
nullplaceholders that mirrors WordPress's native block JSON.nullmarks a slot where an entry frominnerBlocksis rendered. Only set when this block came from a WordPress source post. - rawCSS
- Optional. Block-scoped CSS, compiled and hashed. Emitted inline alongside the rendered HTML. Use sparingly — most styling should come from
tokens. - metadata.bindings
- Optional. Maps an attribute key to a data source (
{ source: "post_meta", args: { key: "..." } }). At render time the plugin resolves the binding against WordPress and substitutes the result intoattrs.
Block tree
A page is a tree of BlockNodes. Composition is recursion
through innerBlocks — there is no separate group or
section primitive. The compiler walks the tree, runs every
validation.rules check at every depth, and emits the
final manifest only if every error-severity rule passes.
[ { "type": "atlas/hero", "attrs": { "heading": "Page builders hold you back." }, "innerHTML": "<section class=\"hero\">...</section>", "innerBlocks": [] }, { "type": "core/group", "attrs": {}, "innerHTML": "<div class=\"wp-block-group\">...</div>", "innerBlocks": [ { "type": "core/heading", "attrs": { "level": 2 }, "innerHTML": "…", "innerBlocks": [] } ] } ]
Islands & motion
A node opts into client-side hydration through an
atlas:island entry on its attrs — values
mirror Astro\'s directive vocabulary ("client:load",
"client:visible", "client:idle"). The
renderer emits a data-island attribute on the rendered
element and queues the JS bundle for the matching directive. Nodes
without an island entry ship zero JavaScript.
Motion is declared the same way — an atlas:motion entry
on attrs names a preset from motion.presets.
The runtime resolves it through GSAP at hydration time. Reduced-motion
preferences pin the end state automatically.
Graceful degradation
Every BlockNode carries its rendered HTML in
innerHTML. When the plugin cannot perform a live render —
component removed, schema drift, plugin deactivated — the editor
falls back to that snapshot. Deactivation degrades to plain HTML,
not to shortcode debris. The page stays readable while you
decide what to do next.
Failure modes
Three things can go wrong with a manifest. All three have deterministic outcomes.
- Unknown
atlasVersioninmeta. The plugin refuses to render the manifest and emits a console warning. Upgrade the plugin or recompile the manifest against the installed version. - Unknown block
type. The renderer emits the block\'sinnerHTMLverbatim and logs a warning. Common cause: a block was renamed in a package without recompiling the manifests that reference it. - A
validation.ruleserror fires at compile time. The build aborts before the manifest is emitted — the broken page never reaches production. Warning-severity rules log but do not block.
There is no fourth case. If a page renders blank, the cause is in troubleshooting — not in the manifest schema.