Skip to main content
Components are per site. A site ships the renderers its design uses and nothing else; the platform contains no designs. A renderer is an Astro component that receives a stored component’s props and emits anchored HTML.

The reference component

The template’s Hero is the shape to copy:
Four things make it work:
  1. Typed props for every editable field, plus _stageId, _stageType and index, which the page passes in.
  2. Anchors: stageAttrs on the wrapper, stagePath on each field, { rich: true } for HTML.
  3. Tokens-first styling: utilities against the site’s design tokens, no scoped styles. Re-skinning is a token change.
  4. Media through <Media>, never a hand-written <img>. The slot renders even when empty so it stays a clickable picker in the admin.

The registry

lib/components.ts maps a stored component type to its renderer. The page templates look each component up here; unknown types render nothing.
Keys are typed against the SDK’s component type union, so a key that is not a current type is a compile error rather than an orphaned string. Site globals such as the header and footer render from the base layout and stay out of the registry.

What is editable with no schema

Anything anchored. A field with data-e-path is editable the moment it renders. Lists render their items with stageArray on the container and stageField on the item fields, and each item is editable in place. Adding, reordering and removing items needs a schema.

Media slots

An image slot is a pair of sibling props: an image key and a video key (default ${imageKey}Video). Exactly one is set. The admin’s combined picker fills one and clears the other, so the renderer never reconciles both. <Media> decides the element:
  • video set: <video autoplay muted loop playsinline preload="metadata"> with a poster
  • else: <img> with a CDN srcset and focal-point object-position, or a transparent placeholder when empty
Props reach renderers raw; <Media> expands mux: ids at the last moment through the SDK, so the same stored value works in public and in the admin. Converting an existing slot is a markup-only change. See Media.

Shared content

A field can declare that its canonical value lives on another row: a component prop on another page, a field on an article (row-level or inside its body), or a path into a global. It is routing, not new storage.
kind is page, article or global. key is the page slug, the article id, or the global key. id is the component id inside the row’s stream, required for pages, omitted for row-level article fields and globals. In an editing session every render of the same ref repaints live, and on publish one versioned write goes to each home row through that row’s own save path. Current limits: page sessions only, single fields not whole lists, live repaint within the current page.

Stateful components

A carousel or tabs stays in its live state while editing. It stamps data-e-current on the active item so the settings cog and inline edits act on it, and it handles the custom events the edit notch dispatches to page through items.

Next steps

Page schemas

Make lists addable.

Media

The image pipeline and video.