From 045d02959e7bb07f9da9ca36799a34ff53f91dd1 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 19 Sep 2026 05:18:02 +0000 Subject: [PATCH] docs(skills): page-builder.md names the channel that publishes expression roots Step 3 of "Wire renderer and registry cleanly" told a reader to provide `dataSource` and contextual data through the renderer provider, and the page's own examples then read `${data.userRole}` / `${data.metrics.*}`. After objectui#9308 the renderer's evaluator binds no `data` root, so a copied example fails silently: a `hidden` gate hides for everyone, and a `text` content / `statistic` value prints its own source text. The step now names one channel, PredicateScopeProvider from @object-ui/react (every key of `scope` is a root), states the roots the renderer adds itself (`record`, `page`), and what the provider's `dataSource` still is. The four example reads use roots the prose says the host published (`userRole`, `metrics`). Section 5 is untouched. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01W5y9kRg1YtYaMQYExVLRc2 --- skills/objectui/guides/page-builder.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/skills/objectui/guides/page-builder.md b/skills/objectui/guides/page-builder.md index ac30a6e6c0..90943a2e31 100644 --- a/skills/objectui/guides/page-builder.md +++ b/skills/objectui/guides/page-builder.md @@ -31,7 +31,8 @@ When helping third-party apps, consume these packages; avoid duplicating core ru ### 3. Compose schema using proven node shape -Use a strict component schema shape similar to: +Use a strict component schema shape similar to this — a page whose host +published `userRole` and `metrics` (section 4, step 3, names the channel): ```json @@ -40,11 +41,11 @@ Use a strict component schema shape similar to: "id": "customer_summary", "className": "col-span-12 lg:col-span-4", "title": "Customer Summary", - "hidden": "${data.userRole !== 'admin'}", + "hidden": "${userRole !== 'admin'}", "children": [ { "type": "text", - "content": "Active users: ${data.metrics.activeUsers}" + "content": "Active users: ${metrics.activeUsers}" } ] } @@ -98,7 +99,13 @@ Typical integration sequence: 1. Register default renderers/components. 2. Register plugin components needed by the page type. -3. Provide `dataSource` and contextual data through renderer provider. +3. Publish the roots the page's expressions read: wrap the tree in + `PredicateScopeProvider` (`@object-ui/react`) — every key of its `scope` is + a root (`userRole`, `metrics` above; `bind` reads the same bag). The renderer + itself adds `record` (the page's row) and `page` (page variables); nothing + publishes `data`, and `SchemaRendererProvider`'s `dataSource` is the adapter + the object-bound blocks fetch through, not a root. Provider fence: + [`guides/auth-permissions.md`](./auth-permissions.md). 4. Render schema via `SchemaRenderer`. Keep custom component registrations namespaced to avoid collisions. @@ -166,7 +173,8 @@ A key must clear **two independent gates** to reach the screen: the renderer has to *read* it, and `SchemaRenderer` has to *evaluate* it. Both lists -- what is evaluated, what is read raw, and what `props` / `properties` each do -- are in [`rules/protocol.md`](../rules/protocol.md). Two consequences shape almost every -page: +page; both examples below read `metrics`, a root the host published (section 4, +step 3): **A `statistic` carries its own text keys**, so both static values and expressions work on the node (`statistic` declares `label` / `value` / @@ -176,7 +184,7 @@ expressions work on the node (`statistic` declares `label` / `value` / { "type": "statistic", "label": "Active Users", - "value": "${data.metrics.activeUsers}", + "value": "${metrics.activeUsers}", "description": "+5% from last month", "trend": "up" } @@ -190,7 +198,7 @@ is evaluated on every component type: "type": "card", "title": "Active Users", "children": [ - { "type": "text", "content": "${data.metrics.activeUsers} active, +${data.metrics.growth}% this month" } + { "type": "text", "content": "${metrics.activeUsers} active, +${metrics.growth}% this month" } ] } ```