Skip to main content
@juo/blocks ships a small set of custom elements that connect block definitions to the page. These are the only @juo/blocks APIs called from HTML; everything else (services, contexts, signals) lives in JavaScript. Two builds ship the same tag set:
  • @juo/blocks/web-components/runtime — lean storefront elements.
  • @juo/blocks/web-components/editor — same elements plus selection wrappers, drop zones, and inline-text editing.
Import one or the other from the portal entry. See Editor for how the editor build layers on top.

<juo-context-root>

Hosts the context tree. Providers call provideContext against it; blocks below it call injectContext and the request is answered by the nearest root above the requester.
Nest a second root to override services for a sub-tree. See Scoping and overrides for the pattern and the typical uses (previews, workflow overlays, tenant scoping).

<juo-page>

The root page renderer. Subscribes to ThemeStateContext, asks it to resolve a route, and renders the resulting first block reactively. When the theme state’s blocks change — because the editor updated a prop, a translation flipped, or the route changed — the page re-renders automatically.
Attributes
  • routeoptional. When set, the element calls themeState.resolve(surface, route) as soon as a ThemeState becomes available, and again whenever the attribute changes. Omit it to drive resolution from JavaScript (e.g. from a custom router).
  • surfaceoptional. "page" (default) or "overlay". Selects which ThemeState surface to render.
<juo-page> does not take a block name — what it renders is whatever ThemeState.resolve() returns for the given path. That keeps routing in one place (RouterService / theme state) instead of duplicated across markup.

<juo-extension-root>

Renders the children placed into a named slot of the surrounding page’s root block. Page renderers emit one <juo-extension-root> per slot they expose; the editor decorates each child with selection chrome via a wrapper.
Attributes
  • namerequired. The slot name to render. Must match a key in the page block’s slots schema.
  • surfaceoptional. "page" (default) or "overlay". Selects which surface to read children from.
<juo-extension-root> reads from the same ThemeState that <juo-page> resolves, so nothing needs to be passed through props — child blocks just appear when the merchant places them in that slot.

<juo-block>

Mounts a fresh ad-hoc instance of a registered block, parameterized by its HTML attributes. Useful for dropping a block into static markup — a one-off mount in a sidebar, a Storybook story, a hand-written page that isn’t driven by theme state.
Attributes
  • namerequired. The registered block name (the value passed to defineBlock/registerBlock).
  • Any other attribute is forwarded as a prop on the block’s instance.
<juo-block> is not what renders pages from theme state — for that use <juo-page>. Use <juo-block> only to drop a block by name into markup independently of routing or stored slot composition.

<juo-text>

An inline text node. In the runtime build it’s a passive container — it shows its text content. In the editor build it becomes editable inline, with its content flowing through the theme state’s translation catalog.
Block renderers typically emit <juo-text> for any merchant-editable copy. See Localization for how the key resolves against the active locale’s catalog.

Composition

A typical page rendered through the platform looks like:
The root block, the children in each slot, the prop values, and the translations all come from the same ThemeState — the only thing pinned in markup is the route. Editing in the Juo Editor updates the theme state; everything below <juo-page> re-renders automatically. <juo-block> doesn’t appear in this tree because page rendering goes through theme state, not through ad-hoc instances. Use <juo-block> only for a one-off mount that is not part of an editable page.