scenecast · view gallery
One asset definition · five rendering targets · both agent-UI standards covered.
GitHub →
An agent home screen for canonical types
Each tile is the icon rendering of one asset's defaultView — exactly what an iPhone home-screen widget would look like at 1×1 size. Click an icon to jump to its full size strip.

What you're looking at

Each card below is one defineAsset() declaration from the scenecast library. Every asset comes with a default view that renders state at five sizes (icon · small · medium · large · xlarge — modeled on Apple WidgetKit + Daslab's WidgetSize) and five formats (HTML · Markdown · Text · A2UI v0.9 · MCP Apps).

Same definition. Different consumers. Markdown is typically 3–5× cheaper in tokens than dumping raw JSON; the icon view is ~95% cheaper. The two agent-UI standards that emerged in 2026 split the world: A2UI (Google, native-declarative — Lit/React/Flutter/OpenClaw) and MCP Apps (Anthropic + OpenAI, sandboxed iframe — Claude/ChatGPT/VS Code/Goose/Cursor). scenecast emits both. Every card shows our own HTML render, Google's reference @a2ui/lit renderer, and the same widget rendered inside a sandboxed MCP-Apps iframe — all consuming the exact same WidgetData JSON.

Vendor implementations (Gmail, Slack, Salesforce, SAP S/4HANA, …) ship from benchmark-scoped repos like scenebench as scenecast extensions for that benchmark's domain. Each benchmark owns its vendor types.

Canonical types

Abstract primitives. Use directly, or as targets for vendor extensions in benchmark repos.

Email
email/mailbox · view: EmailInbox
Canonical mailbox — list of email messages.
A2UI Composer ↗ A2UI Theater ↗ OpenClaw Canvas ↗ ChatGPT Apps SDK ↗ MCP Apps in Claude ↗
HTML · medium
Inbox 10 · 4 unread
  • Invoice #4421 — overdue unread
    alice@vendor.com
  • Quick question about Q2 plan unread
    ceo@company.com
  • Payout completed: $1,200 unread
    alerts@stripe.com
  • Re: contract terms unread
    jordan@bigco.example
Markdown · medium ~49 tokens
Inbox · 10 · 4 unread

• Invoice #4421 — overdue unread — alice@vendor.com
• Quick question about Q2 plan unread — ceo@company.com
• Payout completed: $1,200 unread — alerts@stripe.com
• Re: contract terms unread — jordan@bigco.example
A2UI · medium · rendered by @a2ui/lit
live render via @a2ui/lit · catalog basic · v0.9
MCP Apps · medium · sandboxed iframe
how Claude/ChatGPT/VS Code render this · MIME text/html;profile=mcp-app
All sizes
icon ~5 tokens
4
Email
🔵 Email · 4
{ "type": "icon", "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75\"/>\n </svg>", "color": "blue", "label": "Email", "badge": 4 }
{"version":"v0.9","createSurface":{"surfaceId":"Email-icon","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Email-icon","components":[{"id":"c1","component":"Text","text":"Email","variant":"h3"},{"id":"c2","component":"Text","text":"4","variant":"caption"},{"id":"c3","component":"Column","children":["c1","c2"]},{"id":"root","component":"Card","child":"c3"}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Email · icon</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-app-icon"> <div class="ws-app-tile" style="background:linear-gradient(160deg,#0a84ff 0%,#0040dd 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75"/> </svg></div> <div class="ws-app-badge">4</div> </div> <div class="ws-app-name">Email</div> </div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"icon","glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75\"/>\n </svg>","color":"blue","label":"Email","badge":4}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
small ~16 tokens
Inbox 4 unread
  • Invoice #4421 — overdue unread
    alice@vendor.com
Inbox · 4 unread • Invoice #4421 — overdue unread — alice@vendor.com
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75\"/>\n </svg>", "color": "blue", "title": "Inbox", "meta": "4 unread" }, "body": [ { "type": "list", "items": [ { "id": "m1", "title": "Invoice #4421 — overdue", "subtitle": "alice@vendor.com", "badge": "unread" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Email-small","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Email-small","components":[{"id":"c1","component":"Text","text":"Inbox","variant":"h2"},{"id":"c2","component":"Text","text":"4 unread","variant":"caption"},{"id":"c3","component":"Text","text":"Invoice #4421 — overdue","variant":"h4"},{"id":"c4","component":"Text","text":"alice@vendor.com","variant":"body"},{"id":"c5","component":"Text","text":"unread","variant":"caption"},{"id":"c6","component":"Column","children":["c3","c4","c5"]},{"id":"c7","component":"Card","child":"c6"},{"id":"c8","component":"List","children":["c7"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c2","c8"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Email · small</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#0a84ff 0%,#0040dd 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75"/> </svg></div> </div> <span class="ws-stack-title">Inbox</span> <span class="ws-stack-meta">4 unread</span> </div><div class="ws-stack-body"><div class="ws-list ws-list--vertical"><ul><li class="ws-li" data-widget-anchor="item[m1]"> <div class="ws-li-row"> <span class="ws-li-title">Invoice #4421 — overdue</span> <span class="ws-badge">unread</span> </div> <div class="ws-li-sub">alice@vendor.com</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75\"/>\n </svg>","color":"blue","title":"Inbox","meta":"4 unread"},"body":[{"type":"list","items":[{"id":"m1","title":"Invoice #4421 — overdue","subtitle":"alice@vendor.com","badge":"unread"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
medium ~49 tokens
Inbox 10 · 4 unread
  • Invoice #4421 — overdue unread
    alice@vendor.com
  • Quick question about Q2 plan unread
    ceo@company.com
  • Payout completed: $1,200 unread
    alerts@stripe.com
  • Re: contract terms unread
    jordan@bigco.example
Inbox · 10 · 4 unread • Invoice #4421 — overdue unread — alice@vendor.com • Quick question about Q2 plan unread — ceo@company.com • Payout completed: $1,200 unread — alerts@stripe.com • Re: contract terms unread — jordan@bigco.example
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75\"/>\n </svg>", "color": "blue", "title": "Inbox", "meta": "10 · 4 unread" }, "body": [ { "type": "list", "layout": "grid-2", "items": [ { "id": "m1", "title": "Invoice #4421 — overdue", "subtitle": "alice@vendor.com", "badge": "unread" }, { "id": "m2", "title": "Quick question about Q2 plan", "subtitle": "ceo@company.com", "badge": "unread" }, { "id": "m3", "title": "Payout completed: $1,200", "subtitle": "alerts@stripe.com", "badge": "unread" }, { "id": "m4", "title": "Re: contract terms", "subtitle": "jordan@bigco.example", "badge": "unread" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Email-medium","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Email-medium","components":[{"id":"c1","component":"Text","text":"Inbox","variant":"h2"},{"id":"c2","component":"Text","text":"10 · 4 unread","variant":"caption"},{"id":"c3","component":"Text","text":"Invoice #4421 — overdue","variant":"h4"},{"id":"c4","component":"Text","text":"alice@vendor.com","variant":"body"},{"id":"c5","component":"Text","text":"unread","variant":"caption"},{"id":"c6","component":"Column","children":["c3","c4","c5"]},{"id":"c7","component":"Card","child":"c6"},{"id":"c8","component":"Text","text":"Quick question about Q2 plan","variant":"h4"},{"id":"c9","component":"Text","text":"ceo@company.com","variant":"body"},{"id":"c10","component":"Text","text":"unread","variant":"caption"},{"id":"c11","component":"Column","children":["c8","c9","c10"]},{"id":"c12","component":"Card","child":"c11"},{"id":"c13","component":"Text","text":"Payout completed: $1,200","variant":"h4"},{"id":"c14","component":"Text","text":"alerts@stripe.com","variant":"body"},{"id":"c15","component":"Text","text":"unread","variant":"caption"},{"id":"c16","component":"Column","children":["c13","c14","c15"]},{"id":"c17","component":"Card","child":"c16"},{"id":"c18","component":"Text","text":"Re: contract terms","variant":"h4"},{"id":"c19","component":"Text","text":"jordan@bigco.example","variant":"body"},{"id":"c20","component":"Text","text":"unread","variant":"caption"},{"id":"c21","component":"Column","children":["c18","c19","c20"]},{"id":"c22","component":"Card","child":"c21"},{"id":"c23","component":"List","children":["c7","c12","c17","c22"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c2","c23"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Email · medium</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#0a84ff 0%,#0040dd 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75"/> </svg></div> </div> <span class="ws-stack-title">Inbox</span> <span class="ws-stack-meta">10 · 4 unread</span> </div><div class="ws-stack-body"><div class="ws-list ws-list--grid-2"><ul><li class="ws-li" data-widget-anchor="item[m1]"> <div class="ws-li-row"> <span class="ws-li-title">Invoice #4421 — overdue</span> <span class="ws-badge">unread</span> </div> <div class="ws-li-sub">alice@vendor.com</div> </li><li class="ws-li" data-widget-anchor="item[m2]"> <div class="ws-li-row"> <span class="ws-li-title">Quick question about Q2 plan</span> <span class="ws-badge">unread</span> </div> <div class="ws-li-sub">ceo@company.com</div> </li><li class="ws-li" data-widget-anchor="item[m3]"> <div class="ws-li-row"> <span class="ws-li-title">Payout completed: $1,200</span> <span class="ws-badge">unread</span> </div> <div class="ws-li-sub">alerts@stripe.com</div> </li><li class="ws-li" data-widget-anchor="item[m4]"> <div class="ws-li-row"> <span class="ws-li-title">Re: contract terms</span> <span class="ws-badge">unread</span> </div> <div class="ws-li-sub">jordan@bigco.example</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75\"/>\n </svg>","color":"blue","title":"Inbox","meta":"10 · 4 unread"},"body":[{"type":"list","layout":"grid-2","items":[{"id":"m1","title":"Invoice #4421 — overdue","subtitle":"alice@vendor.com","badge":"unread"},{"id":"m2","title":"Quick question about Q2 plan","subtitle":"ceo@company.com","badge":"unread"},{"id":"m3","title":"Payout completed: $1,200","subtitle":"alerts@stripe.com","badge":"unread"},{"id":"m4","title":"Re: contract terms","subtitle":"jordan@bigco.example","badge":"unread"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
large ~247 tokens
Inbox · 10 messages · 4 unread
  • Invoice #4421 — overdue unread
    alice@vendor.com
    Hi, just a heads up the invoice for $1,240 is past due. Please confirm payment status — would help m…
  • Quick question about Q2 plan unread
    ceo@company.com
    Got a sec to chat about the launch timeline for the new product? Want to align on the scope before t…
  • Payout completed: $1,200 unread
    alerts@stripe.com
    Your payout of $1,200 has been deposited. Reference id: po_1Q4Bxz.
  • Re: contract terms unread
    jordan@bigco.example
    Thanks for the redlines. Legal will respond by EOW. Two open questions on the SLA section.
  • Morning briefing — Apr 30
    newsletter@nyt.com
    Top stories: markets, climate, an interview with the new EU AI commissioner.
  • Re: standup notes
    bob@team.com
    Adding two things to the agenda: deploy retro + capacity planning for next sprint.
  • Reminder: Sales review
    calendar-noreply@google
    Sales review tomorrow at 1 PM. Conf Room 3.
  • [scenecast] PR review
    support@github.com
    Alice approved your PR #44. Tests are green; ready to merge.
Inbox · 10 messages · 4 unreadInvoice #4421 — overdue unread — alice@vendor.com > Hi, just a heads up the invoice for $1,240 is past due. Please confirm payment status — would help m… • Quick question about Q2 plan unread — ceo@company.com > Got a sec to chat about the launch timeline for the new product? Want to align on the scope before t… • Payout completed: $1,200 unread — alerts@stripe.com > Your payout of $1,200 has been deposited. Reference id: po_1Q4Bxz. • Re: contract terms unread — jordan@bigco.example > Thanks for the redlines. Legal will respond by EOW. Two open questions on the SLA section. • Morning briefing — Apr 30 — newsletter@nyt.com > Top stories: markets, climate, an interview with the new EU AI commissioner. • Re: standup notes — bob@team.com > Adding two things to the agenda: deploy retro + capacity planning for next sprint. • Reminder: Sales review — calendar-noreply@google > Sales review tomorrow at 1 PM. Conf Room 3. • [scenecast] PR review — support@github.com > Alice approved your PR #44. Tests are green; ready to merge.
{ "type": "list", "title": "Inbox · 10 messages · 4 unread", "items": [ { "id": "m1", "title": "Invoice #4421 — overdue", "subtitle": "alice@vendor.com", "detail": "Hi, just a heads up the invoice for $1,240 is past due. Please confirm payment status — would help m…", "badge": "unread" }, { "id": "m2", "title": "Quick question about Q2 plan", "subtitle": "ceo@company.com", "detail": "Got a sec to chat about the launch timeline for the new product? Want to align on the scope before t…", "badge": "unread" }, { "id": "m3", "title": "Payout completed: $1,200", "subtitle": "alerts@stripe.com", "detail": "Your payout of $1,200 has been deposited. Reference id: po_1Q4Bxz.", "badge": "unread" }, { "id": "m4", "title": "Re: contract terms", "subtitle": "jordan@bigco.example", "detail": "Thanks for the redlines. Legal will respond by EOW. Two open questions on the SLA section.", "badge": "unread" }, { "id": "m5", "title": "Morning briefing — Apr 30", "subtitle": "newsletter@nyt.com", "detail": "Top stories: markets, climate, an interview with the new EU AI commissioner." }, { "id": "m6", "title": "Re: standup notes", "subtitle": "bob@team.com", "detail": "Adding two things to the agenda: deploy retro + capacity planning for next sprint." }, { "id": "m7", "title": "Reminder: Sales review", "subtitle": "calendar-noreply@google", "detail": "Sales review tomorrow at 1 PM. Conf Room 3." }, { "id": "m8", "title": "[scenecast] PR review", "subtitle": "support@github.com", "detail": "Alice approved your PR #44. Tests are green; ready to merge." } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Email-large","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Email-large","components":[{"id":"c1","component":"Text","text":"Inbox · 10 messages · 4 unread","variant":"h2"},{"id":"c2","component":"Text","text":"Invoice #4421 — overdue","variant":"h4"},{"id":"c3","component":"Text","text":"alice@vendor.com","variant":"body"},{"id":"c4","component":"Text","text":"Hi, just a heads up the invoice for $1,240 is past due. Please confirm payment status — would help m…","variant":"caption"},{"id":"c5","component":"Text","text":"unread","variant":"caption"},{"id":"c6","component":"Column","children":["c2","c3","c4","c5"]},{"id":"c7","component":"Card","child":"c6"},{"id":"c8","component":"Text","text":"Quick question about Q2 plan","variant":"h4"},{"id":"c9","component":"Text","text":"ceo@company.com","variant":"body"},{"id":"c10","component":"Text","text":"Got a sec to chat about the launch timeline for the new product? Want to align on the scope before t…","variant":"caption"},{"id":"c11","component":"Text","text":"unread","variant":"caption"},{"id":"c12","component":"Column","children":["c8","c9","c10","c11"]},{"id":"c13","component":"Card","child":"c12"},{"id":"c14","component":"Text","text":"Payout completed: $1,200","variant":"h4"},{"id":"c15","component":"Text","text":"alerts@stripe.com","variant":"body"},{"id":"c16","component":"Text","text":"Your payout of $1,200 has been deposited. Reference id: po_1Q4Bxz.","variant":"caption"},{"id":"c17","component":"Text","text":"unread","variant":"caption"},{"id":"c18","component":"Column","children":["c14","c15","c16","c17"]},{"id":"c19","component":"Card","child":"c18"},{"id":"c20","component":"Text","text":"Re: contract terms","variant":"h4"},{"id":"c21","component":"Text","text":"jordan@bigco.example","variant":"body"},{"id":"c22","component":"Text","text":"Thanks for the redlines. Legal will respond by EOW. Two open questions on the SLA section.","variant":"caption"},{"id":"c23","component":"Text","text":"unread","variant":"caption"},{"id":"c24","component":"Column","children":["c20","c21","c22","c23"]},{"id":"c25","component":"Card","child":"c24"},{"id":"c26","component":"Text","text":"Morning briefing — Apr 30","variant":"h4"},{"id":"c27","component":"Text","text":"newsletter@nyt.com","variant":"body"},{"id":"c28","component":"Text","text":"Top stories: markets, climate, an interview with the new EU AI commissioner.","variant":"caption"},{"id":"c29","component":"Column","children":["c26","c27","c28"]},{"id":"c30","component":"Card","child":"c29"},{"id":"c31","component":"Text","text":"Re: standup notes","variant":"h4"},{"id":"c32","component":"Text","text":"bob@team.com","variant":"body"},{"id":"c33","component":"Text","text":"Adding two things to the agenda: deploy retro + capacity planning for next sprint.","variant":"caption"},{"id":"c34","component":"Column","children":["c31","c32","c33"]},{"id":"c35","component":"Card","child":"c34"},{"id":"c36","component":"Text","text":"Reminder: Sales review","variant":"h4"},{"id":"c37","component":"Text","text":"calendar-noreply@google","variant":"body"},{"id":"c38","component":"Text","text":"Sales review tomorrow at 1 PM. Conf Room 3.","variant":"caption"},{"id":"c39","component":"Column","children":["c36","c37","c38"]},{"id":"c40","component":"Card","child":"c39"},{"id":"c41","component":"Text","text":"[scenecast] PR review","variant":"h4"},{"id":"c42","component":"Text","text":"support@github.com","variant":"body"},{"id":"c43","component":"Text","text":"Alice approved your PR #44. Tests are green; ready to merge.","variant":"caption"},{"id":"c44","component":"Column","children":["c41","c42","c43"]},{"id":"c45","component":"Card","child":"c44"},{"id":"root","component":"List","children":["c1","c7","c13","c19","c25","c30","c35","c40","c45"],"direction":"vertical"}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Email · large</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-list ws-list--vertical"><div class="ws-title">Inbox · 10 messages · 4 unread</div><ul><li class="ws-li" data-widget-anchor="item[m1]"> <div class="ws-li-row"> <span class="ws-li-title">Invoice #4421 — overdue</span> <span class="ws-badge">unread</span> </div> <div class="ws-li-sub">alice@vendor.com</div> <div class="ws-li-detail">Hi, just a heads up the invoice for $1,240 is past due. Please confirm payment status — would help m…</div> </li><li class="ws-li" data-widget-anchor="item[m2]"> <div class="ws-li-row"> <span class="ws-li-title">Quick question about Q2 plan</span> <span class="ws-badge">unread</span> </div> <div class="ws-li-sub">ceo@company.com</div> <div class="ws-li-detail">Got a sec to chat about the launch timeline for the new product? Want to align on the scope before t…</div> </li><li class="ws-li" data-widget-anchor="item[m3]"> <div class="ws-li-row"> <span class="ws-li-title">Payout completed: $1,200</span> <span class="ws-badge">unread</span> </div> <div class="ws-li-sub">alerts@stripe.com</div> <div class="ws-li-detail">Your payout of $1,200 has been deposited. Reference id: po_1Q4Bxz.</div> </li><li class="ws-li" data-widget-anchor="item[m4]"> <div class="ws-li-row"> <span class="ws-li-title">Re: contract terms</span> <span class="ws-badge">unread</span> </div> <div class="ws-li-sub">jordan@bigco.example</div> <div class="ws-li-detail">Thanks for the redlines. Legal will respond by EOW. Two open questions on the SLA section.</div> </li><li class="ws-li" data-widget-anchor="item[m5]"> <div class="ws-li-row"> <span class="ws-li-title">Morning briefing — Apr 30</span> </div> <div class="ws-li-sub">newsletter@nyt.com</div> <div class="ws-li-detail">Top stories: markets, climate, an interview with the new EU AI commissioner.</div> </li><li class="ws-li" data-widget-anchor="item[m6]"> <div class="ws-li-row"> <span class="ws-li-title">Re: standup notes</span> </div> <div class="ws-li-sub">bob@team.com</div> <div class="ws-li-detail">Adding two things to the agenda: deploy retro + capacity planning for next sprint.</div> </li><li class="ws-li" data-widget-anchor="item[m7]"> <div class="ws-li-row"> <span class="ws-li-title">Reminder: Sales review</span> </div> <div class="ws-li-sub">calendar-noreply@google</div> <div class="ws-li-detail">Sales review tomorrow at 1 PM. Conf Room 3.</div> </li><li class="ws-li" data-widget-anchor="item[m8]"> <div class="ws-li-row"> <span class="ws-li-title">[scenecast] PR review</span> </div> <div class="ws-li-sub">support@github.com</div> <div class="ws-li-detail">Alice approved your PR #44. Tests are green; ready to merge.</div> </li></ul></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"list","title":"Inbox · 10 messages · 4 unread","items":[{"id":"m1","title":"Invoice #4421 — overdue","subtitle":"alice@vendor.com","detail":"Hi, just a heads up the invoice for $1,240 is past due. Please confirm payment status — would help m…","badge":"unread"},{"id":"m2","title":"Quick question about Q2 plan","subtitle":"ceo@company.com","detail":"Got a sec to chat about the launch timeline for the new product? Want to align on the scope before t…","badge":"unread"},{"id":"m3","title":"Payout completed: $1,200","subtitle":"alerts@stripe.com","detail":"Your payout of $1,200 has been deposited. Reference id: po_1Q4Bxz.","badge":"unread"},{"id":"m4","title":"Re: contract terms","subtitle":"jordan@bigco.example","detail":"Thanks for the redlines. Legal will respond by EOW. Two open questions on the SLA section.","badge":"unread"},{"id":"m5","title":"Morning briefing — Apr 30","subtitle":"newsletter@nyt.com","detail":"Top stories: markets, climate, an interview with the new EU AI commissioner."},{"id":"m6","title":"Re: standup notes","subtitle":"bob@team.com","detail":"Adding two things to the agenda: deploy retro + capacity planning for next sprint."},{"id":"m7","title":"Reminder: Sales review","subtitle":"calendar-noreply@google","detail":"Sales review tomorrow at 1 PM. Conf Room 3."},{"id":"m8","title":"[scenecast] PR review","subtitle":"support@github.com","detail":"Alice approved your PR #44. Tests are green; ready to merge."}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
xlarge ~340 tokens
Inbox · 10 messages · 4 unread
  • Invoice #4421 — overdue unread
    alice@vendor.com · 2026-04-30
    Hi, just a heads up the invoice for $1,240 is past due. Please confirm payment status — would help me close out the books for the quarter.
  • Quick question about Q2 plan unread
    ceo@company.com · 2026-04-30
    Got a sec to chat about the launch timeline for the new product? Want to align on the scope before the partner call tomorrow.
  • Payout completed: $1,200 unread
    alerts@stripe.com · 2026-04-30
    Your payout of $1,200 has been deposited. Reference id: po_1Q4Bxz.
  • Re: contract terms unread
    jordan@bigco.example · 2026-04-30
    Thanks for the redlines. Legal will respond by EOW. Two open questions on the SLA section.
  • Morning briefing — Apr 30
    newsletter@nyt.com · 2026-04-30
    Top stories: markets, climate, an interview with the new EU AI commissioner.
  • Re: standup notes
    bob@team.com · 2026-04-29
    Adding two things to the agenda: deploy retro + capacity planning for next sprint.
  • Reminder: Sales review
    calendar-noreply@google · 2026-04-29
    Sales review tomorrow at 1 PM. Conf Room 3.
  • [scenecast] PR review
    support@github.com · 2026-04-29
    Alice approved your PR #44. Tests are green; ready to merge.
  • Benefits enrollment open
    people@company.com · 2026-04-29
    Open enrollment runs through May 15. Pick your plan options on Workday.
  • 5 new jobs that match your search
    linkedin@e.linkedin.com · 2026-04-28
    We found 5 new senior engineering roles in your area.
Inbox · 10 messages · 4 unreadInvoice #4421 — overdue unread — alice@vendor.com · 2026-04-30 > Hi, just a heads up the invoice for $1,240 is past due. Please confirm payment status — would help me close out the books for the quarter. • Quick question about Q2 plan unread — ceo@company.com · 2026-04-30 > Got a sec to chat about the launch timeline for the new product? Want to align on the scope before the partner call tomorrow. • Payout completed: $1,200 unread — alerts@stripe.com · 2026-04-30 > Your payout of $1,200 has been deposited. Reference id: po_1Q4Bxz. • Re: contract terms unread — jordan@bigco.example · 2026-04-30 > Thanks for the redlines. Legal will respond by EOW. Two open questions on the SLA section. • Morning briefing — Apr 30 — newsletter@nyt.com · 2026-04-30 > Top stories: markets, climate, an interview with the new EU AI commissioner. • Re: standup notes — bob@team.com · 2026-04-29 > Adding two things to the agenda: deploy retro + capacity planning for next sprint. • Reminder: Sales review — calendar-noreply@google · 2026-04-29 > Sales review tomorrow at 1 PM. Conf Room 3. • [scenecast] PR review — support@github.com · 2026-04-29 > Alice approved your PR #44. Tests are green; ready to merge. • Benefits enrollment open — people@company.com · 2026-04-29 > Open enrollment runs through May 15. Pick your plan options on Workday. • 5 new jobs that match your search — linkedin@e.linkedin.com · 2026-04-28 > We found 5 new senior engineering roles in your area.
{ "type": "list", "title": "Inbox · 10 messages · 4 unread", "items": [ { "id": "m1", "title": "Invoice #4421 — overdue", "subtitle": "alice@vendor.com · 2026-04-30", "detail": "Hi, just a heads up the invoice for $1,240 is past due. Please confirm payment status — would help me close out the books for the quarter.", "badge": "unread" }, { "id": "m2", "title": "Quick question about Q2 plan", "subtitle": "ceo@company.com · 2026-04-30", "detail": "Got a sec to chat about the launch timeline for the new product? Want to align on the scope before the partner call tomorrow.", "badge": "unread" }, { "id": "m3", "title": "Payout completed: $1,200", "subtitle": "alerts@stripe.com · 2026-04-30", "detail": "Your payout of $1,200 has been deposited. Reference id: po_1Q4Bxz.", "badge": "unread" }, { "id": "m4", "title": "Re: contract terms", "subtitle": "jordan@bigco.example · 2026-04-30", "detail": "Thanks for the redlines. Legal will respond by EOW. Two open questions on the SLA section.", "badge": "unread" }, { "id": "m5", "title": "Morning briefing — Apr 30", "subtitle": "newsletter@nyt.com · 2026-04-30", "detail": "Top stories: markets, climate, an interview with the new EU AI commissioner." }, { "id": "m6", "title": "Re: standup notes", "subtitle": "bob@team.com · 2026-04-29", "detail": "Adding two things to the agenda: deploy retro + capacity planning for next sprint." }, { "id": "m7", "title": "Reminder: Sales review", "subtitle": "calendar-noreply@google · 2026-04-29", "detail": "Sales review tomorrow at 1 PM. Conf Room 3." }, { "id": "m8", "title": "[scenecast] PR review", "subtitle": "support@github.com · 2026-04-29", "detail": "Alice approved your PR #44. Tests are green; ready to merge." }, { "id": "m9", "title": "Benefits enrollment open", "subtitle": "people@company.com · 2026-04-29", "detail": "Open enrollment runs through May 15. Pick your plan options on Workday." }, { "id": "m10", "title": "5 new jobs that match your search", "subtitle": "linkedin@e.linkedin.com · 2026-04-28", "detail": "We found 5 new senior engineering roles in your area." } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Email-xlarge","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Email-xlarge","components":[{"id":"c1","component":"Text","text":"Inbox · 10 messages · 4 unread","variant":"h2"},{"id":"c2","component":"Text","text":"Invoice #4421 — overdue","variant":"h4"},{"id":"c3","component":"Text","text":"alice@vendor.com · 2026-04-30","variant":"body"},{"id":"c4","component":"Text","text":"Hi, just a heads up the invoice for $1,240 is past due. Please confirm payment status — would help me close out the books for the quarter.","variant":"caption"},{"id":"c5","component":"Text","text":"unread","variant":"caption"},{"id":"c6","component":"Column","children":["c2","c3","c4","c5"]},{"id":"c7","component":"Card","child":"c6"},{"id":"c8","component":"Text","text":"Quick question about Q2 plan","variant":"h4"},{"id":"c9","component":"Text","text":"ceo@company.com · 2026-04-30","variant":"body"},{"id":"c10","component":"Text","text":"Got a sec to chat about the launch timeline for the new product? Want to align on the scope before the partner call tomorrow.","variant":"caption"},{"id":"c11","component":"Text","text":"unread","variant":"caption"},{"id":"c12","component":"Column","children":["c8","c9","c10","c11"]},{"id":"c13","component":"Card","child":"c12"},{"id":"c14","component":"Text","text":"Payout completed: $1,200","variant":"h4"},{"id":"c15","component":"Text","text":"alerts@stripe.com · 2026-04-30","variant":"body"},{"id":"c16","component":"Text","text":"Your payout of $1,200 has been deposited. Reference id: po_1Q4Bxz.","variant":"caption"},{"id":"c17","component":"Text","text":"unread","variant":"caption"},{"id":"c18","component":"Column","children":["c14","c15","c16","c17"]},{"id":"c19","component":"Card","child":"c18"},{"id":"c20","component":"Text","text":"Re: contract terms","variant":"h4"},{"id":"c21","component":"Text","text":"jordan@bigco.example · 2026-04-30","variant":"body"},{"id":"c22","component":"Text","text":"Thanks for the redlines. Legal will respond by EOW. Two open questions on the SLA section.","variant":"caption"},{"id":"c23","component":"Text","text":"unread","variant":"caption"},{"id":"c24","component":"Column","children":["c20","c21","c22","c23"]},{"id":"c25","component":"Card","child":"c24"},{"id":"c26","component":"Text","text":"Morning briefing — Apr 30","variant":"h4"},{"id":"c27","component":"Text","text":"newsletter@nyt.com · 2026-04-30","variant":"body"},{"id":"c28","component":"Text","text":"Top stories: markets, climate, an interview with the new EU AI commissioner.","variant":"caption"},{"id":"c29","component":"Column","children":["c26","c27","c28"]},{"id":"c30","component":"Card","child":"c29"},{"id":"c31","component":"Text","text":"Re: standup notes","variant":"h4"},{"id":"c32","component":"Text","text":"bob@team.com · 2026-04-29","variant":"body"},{"id":"c33","component":"Text","text":"Adding two things to the agenda: deploy retro + capacity planning for next sprint.","variant":"caption"},{"id":"c34","component":"Column","children":["c31","c32","c33"]},{"id":"c35","component":"Card","child":"c34"},{"id":"c36","component":"Text","text":"Reminder: Sales review","variant":"h4"},{"id":"c37","component":"Text","text":"calendar-noreply@google · 2026-04-29","variant":"body"},{"id":"c38","component":"Text","text":"Sales review tomorrow at 1 PM. Conf Room 3.","variant":"caption"},{"id":"c39","component":"Column","children":["c36","c37","c38"]},{"id":"c40","component":"Card","child":"c39"},{"id":"c41","component":"Text","text":"[scenecast] PR review","variant":"h4"},{"id":"c42","component":"Text","text":"support@github.com · 2026-04-29","variant":"body"},{"id":"c43","component":"Text","text":"Alice approved your PR #44. Tests are green; ready to merge.","variant":"caption"},{"id":"c44","component":"Column","children":["c41","c42","c43"]},{"id":"c45","component":"Card","child":"c44"},{"id":"c46","component":"Text","text":"Benefits enrollment open","variant":"h4"},{"id":"c47","component":"Text","text":"people@company.com · 2026-04-29","variant":"body"},{"id":"c48","component":"Text","text":"Open enrollment runs through May 15. Pick your plan options on Workday.","variant":"caption"},{"id":"c49","component":"Column","children":["c46","c47","c48"]},{"id":"c50","component":"Card","child":"c49"},{"id":"c51","component":"Text","text":"5 new jobs that match your search","variant":"h4"},{"id":"c52","component":"Text","text":"linkedin@e.linkedin.com · 2026-04-28","variant":"body"},{"id":"c53","component":"Text","text":"We found 5 new senior engineering roles in your area.","variant":"caption"},{"id":"c54","component":"Column","children":["c51","c52","c53"]},{"id":"c55","component":"Card","child":"c54"},{"id":"root","component":"List","children":["c1","c7","c13","c19","c25","c30","c35","c40","c45","c50","c55"],"direction":"vertical"}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Email · xlarge</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-list ws-list--vertical"><div class="ws-title">Inbox · 10 messages · 4 unread</div><ul><li class="ws-li" data-widget-anchor="item[m1]"> <div class="ws-li-row"> <span class="ws-li-title">Invoice #4421 — overdue</span> <span class="ws-badge">unread</span> </div> <div class="ws-li-sub">alice@vendor.com · 2026-04-30</div> <div class="ws-li-detail">Hi, just a heads up the invoice for $1,240 is past due. Please confirm payment status — would help me close out the books for the quarter.</div> </li><li class="ws-li" data-widget-anchor="item[m2]"> <div class="ws-li-row"> <span class="ws-li-title">Quick question about Q2 plan</span> <span class="ws-badge">unread</span> </div> <div class="ws-li-sub">ceo@company.com · 2026-04-30</div> <div class="ws-li-detail">Got a sec to chat about the launch timeline for the new product? Want to align on the scope before the partner call tomorrow.</div> </li><li class="ws-li" data-widget-anchor="item[m3]"> <div class="ws-li-row"> <span class="ws-li-title">Payout completed: $1,200</span> <span class="ws-badge">unread</span> </div> <div class="ws-li-sub">alerts@stripe.com · 2026-04-30</div> <div class="ws-li-detail">Your payout of $1,200 has been deposited. Reference id: po_1Q4Bxz.</div> </li><li class="ws-li" data-widget-anchor="item[m4]"> <div class="ws-li-row"> <span class="ws-li-title">Re: contract terms</span> <span class="ws-badge">unread</span> </div> <div class="ws-li-sub">jordan@bigco.example · 2026-04-30</div> <div class="ws-li-detail">Thanks for the redlines. Legal will respond by EOW. Two open questions on the SLA section.</div> </li><li class="ws-li" data-widget-anchor="item[m5]"> <div class="ws-li-row"> <span class="ws-li-title">Morning briefing — Apr 30</span> </div> <div class="ws-li-sub">newsletter@nyt.com · 2026-04-30</div> <div class="ws-li-detail">Top stories: markets, climate, an interview with the new EU AI commissioner.</div> </li><li class="ws-li" data-widget-anchor="item[m6]"> <div class="ws-li-row"> <span class="ws-li-title">Re: standup notes</span> </div> <div class="ws-li-sub">bob@team.com · 2026-04-29</div> <div class="ws-li-detail">Adding two things to the agenda: deploy retro + capacity planning for next sprint.</div> </li><li class="ws-li" data-widget-anchor="item[m7]"> <div class="ws-li-row"> <span class="ws-li-title">Reminder: Sales review</span> </div> <div class="ws-li-sub">calendar-noreply@google · 2026-04-29</div> <div class="ws-li-detail">Sales review tomorrow at 1 PM. Conf Room 3.</div> </li><li class="ws-li" data-widget-anchor="item[m8]"> <div class="ws-li-row"> <span class="ws-li-title">[scenecast] PR review</span> </div> <div class="ws-li-sub">support@github.com · 2026-04-29</div> <div class="ws-li-detail">Alice approved your PR #44. Tests are green; ready to merge.</div> </li><li class="ws-li" data-widget-anchor="item[m9]"> <div class="ws-li-row"> <span class="ws-li-title">Benefits enrollment open</span> </div> <div class="ws-li-sub">people@company.com · 2026-04-29</div> <div class="ws-li-detail">Open enrollment runs through May 15. Pick your plan options on Workday.</div> </li><li class="ws-li" data-widget-anchor="item[m10]"> <div class="ws-li-row"> <span class="ws-li-title">5 new jobs that match your search</span> </div> <div class="ws-li-sub">linkedin@e.linkedin.com · 2026-04-28</div> <div class="ws-li-detail">We found 5 new senior engineering roles in your area.</div> </li></ul></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"list","title":"Inbox · 10 messages · 4 unread","items":[{"id":"m1","title":"Invoice #4421 — overdue","subtitle":"alice@vendor.com · 2026-04-30","detail":"Hi, just a heads up the invoice for $1,240 is past due. Please confirm payment status — would help me close out the books for the quarter.","badge":"unread"},{"id":"m2","title":"Quick question about Q2 plan","subtitle":"ceo@company.com · 2026-04-30","detail":"Got a sec to chat about the launch timeline for the new product? Want to align on the scope before the partner call tomorrow.","badge":"unread"},{"id":"m3","title":"Payout completed: $1,200","subtitle":"alerts@stripe.com · 2026-04-30","detail":"Your payout of $1,200 has been deposited. Reference id: po_1Q4Bxz.","badge":"unread"},{"id":"m4","title":"Re: contract terms","subtitle":"jordan@bigco.example · 2026-04-30","detail":"Thanks for the redlines. Legal will respond by EOW. Two open questions on the SLA section.","badge":"unread"},{"id":"m5","title":"Morning briefing — Apr 30","subtitle":"newsletter@nyt.com · 2026-04-30","detail":"Top stories: markets, climate, an interview with the new EU AI commissioner."},{"id":"m6","title":"Re: standup notes","subtitle":"bob@team.com · 2026-04-29","detail":"Adding two things to the agenda: deploy retro + capacity planning for next sprint."},{"id":"m7","title":"Reminder: Sales review","subtitle":"calendar-noreply@google · 2026-04-29","detail":"Sales review tomorrow at 1 PM. Conf Room 3."},{"id":"m8","title":"[scenecast] PR review","subtitle":"support@github.com · 2026-04-29","detail":"Alice approved your PR #44. Tests are green; ready to merge."},{"id":"m9","title":"Benefits enrollment open","subtitle":"people@company.com · 2026-04-29","detail":"Open enrollment runs through May 15. Pick your plan options on Workday."},{"id":"m10","title":"5 new jobs that match your search","subtitle":"linkedin@e.linkedin.com · 2026-04-28","detail":"We found 5 new senior engineering roles in your area."}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
Message
message/channels · view: MessagingActivity
Canonical messaging — channels + messages.
A2UI Composer ↗ A2UI Theater ↗ OpenClaw Canvas ↗ ChatGPT Apps SDK ↗ MCP Apps in Claude ↗
HTML · medium
Recent activity 2 channels
  • #engineering
    2 messages
    bob: Looks good — bumping to 25%.
  • #marketing
    1 message
    carol: Paused c-retain. CPA was high.
Markdown · medium ~40 tokens
Recent activity · 2 channels

• #engineering — 2 messages
  > bob: Looks good — bumping to 25%.
• #marketing — 1 message
  > carol: Paused c-retain. CPA was high.
A2UI · medium · rendered by @a2ui/lit
live render via @a2ui/lit · catalog basic · v0.9
MCP Apps · medium · sandboxed iframe
how Claude/ChatGPT/VS Code render this · MIME text/html;profile=mcp-app
All sizes
icon ~5 tokens
3
Chat
🟢 Chat · 3
{ "type": "icon", "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155\"/>\n </svg>", "color": "green", "label": "Chat", "badge": 3 }
{"version":"v0.9","createSurface":{"surfaceId":"Message-icon","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Message-icon","components":[{"id":"c1","component":"Text","text":"Chat","variant":"h3"},{"id":"c2","component":"Text","text":"3","variant":"caption"},{"id":"c3","component":"Column","children":["c1","c2"]},{"id":"root","component":"Card","child":"c3"}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Message · icon</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-app-icon"> <div class="ws-app-tile" style="background:linear-gradient(160deg,#34c759 0%,#1ca647 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155"/> </svg></div> <div class="ws-app-badge">3</div> </div> <div class="ws-app-name">Chat</div> </div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"icon","glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155\"/>\n </svg>","color":"green","label":"Chat","badge":3}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
small ~11 tokens
2 channels active
  • #engineering
    2 messages
2 channels active#engineering — 2 messages
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155\"/>\n </svg>", "color": "green", "title": "2 channels active" }, "body": [ { "type": "list", "items": [ { "title": "#engineering", "subtitle": "2 messages" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Message-small","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Message-small","components":[{"id":"c1","component":"Text","text":"2 channels active","variant":"h2"},{"id":"c2","component":"Text","text":"#engineering","variant":"h4"},{"id":"c3","component":"Text","text":"2 messages","variant":"body"},{"id":"c4","component":"Column","children":["c2","c3"]},{"id":"c5","component":"Card","child":"c4"},{"id":"c6","component":"List","children":["c5"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c6"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Message · small</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#34c759 0%,#1ca647 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155"/> </svg></div> </div> <span class="ws-stack-title">2 channels active</span> </div><div class="ws-stack-body"><div class="ws-list ws-list--vertical"><ul><li class="ws-li" data-widget-anchor="row[0]"> <div class="ws-li-row"> <span class="ws-li-title">#engineering</span> </div> <div class="ws-li-sub">2 messages</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155\"/>\n </svg>","color":"green","title":"2 channels active"},"body":[{"type":"list","items":[{"title":"#engineering","subtitle":"2 messages"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
medium ~40 tokens
Recent activity 2 channels
  • #engineering
    2 messages
    bob: Looks good — bumping to 25%.
  • #marketing
    1 message
    carol: Paused c-retain. CPA was high.
Recent activity · 2 channels • #engineering — 2 messages > bob: Looks good — bumping to 25%. • #marketing — 1 message > carol: Paused c-retain. CPA was high.
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155\"/>\n </svg>", "color": "green", "title": "Recent activity", "meta": "2 channels" }, "body": [ { "type": "list", "items": [ { "id": "engineering", "title": "#engineering", "subtitle": "2 messages", "detail": "bob: Looks good — bumping to 25%." }, { "id": "marketing", "title": "#marketing", "subtitle": "1 message", "detail": "carol: Paused c-retain. CPA was high." } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Message-medium","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Message-medium","components":[{"id":"c1","component":"Text","text":"Recent activity","variant":"h2"},{"id":"c2","component":"Text","text":"2 channels","variant":"caption"},{"id":"c3","component":"Text","text":"#engineering","variant":"h4"},{"id":"c4","component":"Text","text":"2 messages","variant":"body"},{"id":"c5","component":"Text","text":"bob: Looks good — bumping to 25%.","variant":"caption"},{"id":"c6","component":"Column","children":["c3","c4","c5"]},{"id":"c7","component":"Card","child":"c6"},{"id":"c8","component":"Text","text":"#marketing","variant":"h4"},{"id":"c9","component":"Text","text":"1 message","variant":"body"},{"id":"c10","component":"Text","text":"carol: Paused c-retain. CPA was high.","variant":"caption"},{"id":"c11","component":"Column","children":["c8","c9","c10"]},{"id":"c12","component":"Card","child":"c11"},{"id":"c13","component":"List","children":["c7","c12"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c2","c13"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Message · medium</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#34c759 0%,#1ca647 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155"/> </svg></div> </div> <span class="ws-stack-title">Recent activity</span> <span class="ws-stack-meta">2 channels</span> </div><div class="ws-stack-body"><div class="ws-list ws-list--vertical"><ul><li class="ws-li" data-widget-anchor="item[engineering]"> <div class="ws-li-row"> <span class="ws-li-title">#engineering</span> </div> <div class="ws-li-sub">2 messages</div> <div class="ws-li-detail">bob: Looks good — bumping to 25%.</div> </li><li class="ws-li" data-widget-anchor="item[marketing]"> <div class="ws-li-row"> <span class="ws-li-title">#marketing</span> </div> <div class="ws-li-sub">1 message</div> <div class="ws-li-detail">carol: Paused c-retain. CPA was high.</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155\"/>\n </svg>","color":"green","title":"Recent activity","meta":"2 channels"},"body":[{"type":"list","items":[{"id":"engineering","title":"#engineering","subtitle":"2 messages","detail":"bob: Looks good — bumping to 25%."},{"id":"marketing","title":"#marketing","subtitle":"1 message","detail":"carol: Paused c-retain. CPA was high."}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
large ~40 tokens
Recent activity 2 channels
  • #engineering
    2 messages
    bob: Looks good — bumping to 25%.
  • #marketing
    1 message
    carol: Paused c-retain. CPA was high.
Recent activity · 2 channels • #engineering — 2 messages > bob: Looks good — bumping to 25%. • #marketing — 1 message > carol: Paused c-retain. CPA was high.
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155\"/>\n </svg>", "color": "green", "title": "Recent activity", "meta": "2 channels" }, "body": [ { "type": "list", "items": [ { "id": "engineering", "title": "#engineering", "subtitle": "2 messages", "detail": "bob: Looks good — bumping to 25%." }, { "id": "marketing", "title": "#marketing", "subtitle": "1 message", "detail": "carol: Paused c-retain. CPA was high." } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Message-large","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Message-large","components":[{"id":"c1","component":"Text","text":"Recent activity","variant":"h2"},{"id":"c2","component":"Text","text":"2 channels","variant":"caption"},{"id":"c3","component":"Text","text":"#engineering","variant":"h4"},{"id":"c4","component":"Text","text":"2 messages","variant":"body"},{"id":"c5","component":"Text","text":"bob: Looks good — bumping to 25%.","variant":"caption"},{"id":"c6","component":"Column","children":["c3","c4","c5"]},{"id":"c7","component":"Card","child":"c6"},{"id":"c8","component":"Text","text":"#marketing","variant":"h4"},{"id":"c9","component":"Text","text":"1 message","variant":"body"},{"id":"c10","component":"Text","text":"carol: Paused c-retain. CPA was high.","variant":"caption"},{"id":"c11","component":"Column","children":["c8","c9","c10"]},{"id":"c12","component":"Card","child":"c11"},{"id":"c13","component":"List","children":["c7","c12"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c2","c13"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Message · large</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#34c759 0%,#1ca647 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155"/> </svg></div> </div> <span class="ws-stack-title">Recent activity</span> <span class="ws-stack-meta">2 channels</span> </div><div class="ws-stack-body"><div class="ws-list ws-list--vertical"><ul><li class="ws-li" data-widget-anchor="item[engineering]"> <div class="ws-li-row"> <span class="ws-li-title">#engineering</span> </div> <div class="ws-li-sub">2 messages</div> <div class="ws-li-detail">bob: Looks good — bumping to 25%.</div> </li><li class="ws-li" data-widget-anchor="item[marketing]"> <div class="ws-li-row"> <span class="ws-li-title">#marketing</span> </div> <div class="ws-li-sub">1 message</div> <div class="ws-li-detail">carol: Paused c-retain. CPA was high.</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155\"/>\n </svg>","color":"green","title":"Recent activity","meta":"2 channels"},"body":[{"type":"list","items":[{"id":"engineering","title":"#engineering","subtitle":"2 messages","detail":"bob: Looks good — bumping to 25%."},{"id":"marketing","title":"#marketing","subtitle":"1 message","detail":"carol: Paused c-retain. CPA was high."}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
xlarge ~40 tokens
Recent activity 2 channels
  • #engineering
    2 messages
    bob: Looks good — bumping to 25%.
  • #marketing
    1 message
    carol: Paused c-retain. CPA was high.
Recent activity · 2 channels • #engineering — 2 messages > bob: Looks good — bumping to 25%. • #marketing — 1 message > carol: Paused c-retain. CPA was high.
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155\"/>\n </svg>", "color": "green", "title": "Recent activity", "meta": "2 channels" }, "body": [ { "type": "list", "items": [ { "id": "engineering", "title": "#engineering", "subtitle": "2 messages", "detail": "bob: Looks good — bumping to 25%." }, { "id": "marketing", "title": "#marketing", "subtitle": "1 message", "detail": "carol: Paused c-retain. CPA was high." } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Message-xlarge","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Message-xlarge","components":[{"id":"c1","component":"Text","text":"Recent activity","variant":"h2"},{"id":"c2","component":"Text","text":"2 channels","variant":"caption"},{"id":"c3","component":"Text","text":"#engineering","variant":"h4"},{"id":"c4","component":"Text","text":"2 messages","variant":"body"},{"id":"c5","component":"Text","text":"bob: Looks good — bumping to 25%.","variant":"caption"},{"id":"c6","component":"Column","children":["c3","c4","c5"]},{"id":"c7","component":"Card","child":"c6"},{"id":"c8","component":"Text","text":"#marketing","variant":"h4"},{"id":"c9","component":"Text","text":"1 message","variant":"body"},{"id":"c10","component":"Text","text":"carol: Paused c-retain. CPA was high.","variant":"caption"},{"id":"c11","component":"Column","children":["c8","c9","c10"]},{"id":"c12","component":"Card","child":"c11"},{"id":"c13","component":"List","children":["c7","c12"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c2","c13"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Message · xlarge</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#34c759 0%,#1ca647 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155"/> </svg></div> </div> <span class="ws-stack-title">Recent activity</span> <span class="ws-stack-meta">2 channels</span> </div><div class="ws-stack-body"><div class="ws-list ws-list--vertical"><ul><li class="ws-li" data-widget-anchor="item[engineering]"> <div class="ws-li-row"> <span class="ws-li-title">#engineering</span> </div> <div class="ws-li-sub">2 messages</div> <div class="ws-li-detail">bob: Looks good — bumping to 25%.</div> </li><li class="ws-li" data-widget-anchor="item[marketing]"> <div class="ws-li-row"> <span class="ws-li-title">#marketing</span> </div> <div class="ws-li-sub">1 message</div> <div class="ws-li-detail">carol: Paused c-retain. CPA was high.</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155\"/>\n </svg>","color":"green","title":"Recent activity","meta":"2 channels"},"body":[{"type":"list","items":[{"id":"engineering","title":"#engineering","subtitle":"2 messages","detail":"bob: Looks good — bumping to 25%."},{"id":"marketing","title":"#marketing","subtitle":"1 message","detail":"carol: Paused c-retain. CPA was high."}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
Contact
contact/list · view: ContactList
Canonical contact list — people with email, phone, role.
A2UI Composer ↗ A2UI Theater ↗ OpenClaw Canvas ↗ ChatGPT Apps SDK ↗ MCP Apps in Claude ↗
HTML · medium
Contacts 3
NameEmailTitle
Jordan Leejordan@acme.comDirector of Ops
Maria Santosmaria@brightwave.comVP Marketing
Aiden Parkaiden@meridian.comCEO
Markdown · medium ~59 tokens
Contacts · 3

NameEmailTitle
Jordan Leejordan@acme.comDirector of Ops
Maria Santosmaria@brightwave.comVP Marketing
Aiden Parkaiden@meridian.comCEO
A2UI · medium · rendered by @a2ui/lit
live render via @a2ui/lit · catalog basic · v0.9
MCP Apps · medium · sandboxed iframe
how Claude/ChatGPT/VS Code render this · MIME text/html;profile=mcp-app
All sizes
icon ~5 tokens
3
Contacts
🟣 Contacts · 3
{ "type": "icon", "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z\"/>\n </svg>", "color": "purple", "label": "Contacts", "badge": 3 }
{"version":"v0.9","createSurface":{"surfaceId":"Contact-icon","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Contact-icon","components":[{"id":"c1","component":"Text","text":"Contacts","variant":"h3"},{"id":"c2","component":"Text","text":"3","variant":"caption"},{"id":"c3","component":"Column","children":["c1","c2"]},{"id":"root","component":"Card","child":"c3"}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Contact · icon</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-app-icon"> <div class="ws-app-tile" style="background:linear-gradient(160deg,#af52de 0%,#7e3fb1 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z"/> </svg></div> <div class="ws-app-badge">3</div> </div> <div class="ws-app-name">Contacts</div> </div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"icon","glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z\"/>\n </svg>","color":"purple","label":"Contacts","badge":3}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
small ~12 tokens
3 contacts
  • Jordan Lee
    Director of Ops
3 contactsJordan Lee — Director of Ops
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z\"/>\n </svg>", "color": "purple", "title": "3 contacts" }, "body": [ { "type": "list", "items": [ { "id": "c1", "title": "Jordan Lee", "subtitle": "Director of Ops" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Contact-small","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Contact-small","components":[{"id":"c1","component":"Text","text":"3 contacts","variant":"h2"},{"id":"c2","component":"Text","text":"Jordan Lee","variant":"h4"},{"id":"c3","component":"Text","text":"Director of Ops","variant":"body"},{"id":"c4","component":"Column","children":["c2","c3"]},{"id":"c5","component":"Card","child":"c4"},{"id":"c6","component":"List","children":["c5"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c6"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Contact · small</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#af52de 0%,#7e3fb1 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z"/> </svg></div> </div> <span class="ws-stack-title">3 contacts</span> </div><div class="ws-stack-body"><div class="ws-list ws-list--vertical"><ul><li class="ws-li" data-widget-anchor="item[c1]"> <div class="ws-li-row"> <span class="ws-li-title">Jordan Lee</span> </div> <div class="ws-li-sub">Director of Ops</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z\"/>\n </svg>","color":"purple","title":"3 contacts"},"body":[{"type":"list","items":[{"id":"c1","title":"Jordan Lee","subtitle":"Director of Ops"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
medium ~59 tokens
Contacts 3
NameEmailTitle
Jordan Leejordan@acme.comDirector of Ops
Maria Santosmaria@brightwave.comVP Marketing
Aiden Parkaiden@meridian.comCEO
Contacts · 3
NameEmailTitle
Jordan Leejordan@acme.comDirector of Ops
Maria Santosmaria@brightwave.comVP Marketing
Aiden Parkaiden@meridian.comCEO
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z\"/>\n </svg>", "color": "purple", "title": "Contacts", "meta": "3" }, "body": [ { "type": "table", "columns": [ "Name", "Email", "Title" ], "rows": [ { "Name": "Jordan Lee", "Email": "jordan@acme.com", "Title": "Director of Ops" }, { "Name": "Maria Santos", "Email": "maria@brightwave.com", "Title": "VP Marketing" }, { "Name": "Aiden Park", "Email": "aiden@meridian.com", "Title": "CEO" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Contact-medium","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Contact-medium","components":[{"id":"c1","component":"Text","text":"Contacts","variant":"h2"},{"id":"c2","component":"Text","text":"3","variant":"caption"},{"id":"c3","component":"Text","text":"Name","variant":"h5"},{"id":"c4","component":"Text","text":"Email","variant":"h5"},{"id":"c5","component":"Text","text":"Title","variant":"h5"},{"id":"c6","component":"Row","children":["c3","c4","c5"]},{"id":"c7","component":"Divider"},{"id":"c8","component":"Text","text":"Jordan Lee","variant":"body"},{"id":"c9","component":"Text","text":"jordan@acme.com","variant":"body"},{"id":"c10","component":"Text","text":"Director of Ops","variant":"body"},{"id":"c11","component":"Row","children":["c8","c9","c10"]},{"id":"c12","component":"Text","text":"Maria Santos","variant":"body"},{"id":"c13","component":"Text","text":"maria@brightwave.com","variant":"body"},{"id":"c14","component":"Text","text":"VP Marketing","variant":"body"},{"id":"c15","component":"Row","children":["c12","c13","c14"]},{"id":"c16","component":"Text","text":"Aiden Park","variant":"body"},{"id":"c17","component":"Text","text":"aiden@meridian.com","variant":"body"},{"id":"c18","component":"Text","text":"CEO","variant":"body"},{"id":"c19","component":"Row","children":["c16","c17","c18"]},{"id":"c20","component":"Column","children":["c6","c7","c11","c15","c19"]},{"id":"root","component":"Column","children":["c1","c2","c20"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Contact · medium</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#af52de 0%,#7e3fb1 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z"/> </svg></div> </div> <span class="ws-stack-title">Contacts</span> <span class="ws-stack-meta">3</span> </div><div class="ws-stack-body"><div class="ws-table"><table><thead><tr><th>Name</th><th>Email</th><th>Title</th></tr></thead><tbody><tr data-widget-anchor="row[0]"><td>Jordan Lee</td><td>jordan@acme.com</td><td>Director of Ops</td></tr><tr data-widget-anchor="row[1]"><td>Maria Santos</td><td>maria@brightwave.com</td><td>VP Marketing</td></tr><tr data-widget-anchor="row[2]"><td>Aiden Park</td><td>aiden@meridian.com</td><td>CEO</td></tr></tbody></table></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z\"/>\n </svg>","color":"purple","title":"Contacts","meta":"3"},"body":[{"type":"table","columns":["Name","Email","Title"],"rows":[{"Name":"Jordan Lee","Email":"jordan@acme.com","Title":"Director of Ops"},{"Name":"Maria Santos","Email":"maria@brightwave.com","Title":"VP Marketing"},{"Name":"Aiden Park","Email":"aiden@meridian.com","Title":"CEO"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
large ~84 tokens
3 contacts
NameEmailPhoneTitleCompany
Jordan Leejordan@acme.com+1-555-0101Director of OpsAcme
Maria Santosmaria@brightwave.com+1-555-0182VP MarketingBrightwave
Aiden Parkaiden@meridian.com+1-555-0301CEOMeridian
3 contacts
NameEmailPhoneTitleCompany
Jordan Leejordan@acme.com+1-555-0101Director of OpsAcme
Maria Santosmaria@brightwave.com+1-555-0182VP MarketingBrightwave
Aiden Parkaiden@meridian.com+1-555-0301CEOMeridian
{ "type": "table", "title": "3 contacts", "columns": [ "Name", "Email", "Phone", "Title", "Company" ], "rows": [ { "Name": "Jordan Lee", "Email": "jordan@acme.com", "Phone": "+1-555-0101", "Title": "Director of Ops", "Company": "Acme" }, { "Name": "Maria Santos", "Email": "maria@brightwave.com", "Phone": "+1-555-0182", "Title": "VP Marketing", "Company": "Brightwave" }, { "Name": "Aiden Park", "Email": "aiden@meridian.com", "Phone": "+1-555-0301", "Title": "CEO", "Company": "Meridian" } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Contact-large","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Contact-large","components":[{"id":"c1","component":"Text","text":"3 contacts","variant":"h2"},{"id":"c2","component":"Text","text":"Name","variant":"h5"},{"id":"c3","component":"Text","text":"Email","variant":"h5"},{"id":"c4","component":"Text","text":"Phone","variant":"h5"},{"id":"c5","component":"Text","text":"Title","variant":"h5"},{"id":"c6","component":"Text","text":"Company","variant":"h5"},{"id":"c7","component":"Row","children":["c2","c3","c4","c5","c6"]},{"id":"c8","component":"Divider"},{"id":"c9","component":"Text","text":"Jordan Lee","variant":"body"},{"id":"c10","component":"Text","text":"jordan@acme.com","variant":"body"},{"id":"c11","component":"Text","text":"+1-555-0101","variant":"body"},{"id":"c12","component":"Text","text":"Director of Ops","variant":"body"},{"id":"c13","component":"Text","text":"Acme","variant":"body"},{"id":"c14","component":"Row","children":["c9","c10","c11","c12","c13"]},{"id":"c15","component":"Text","text":"Maria Santos","variant":"body"},{"id":"c16","component":"Text","text":"maria@brightwave.com","variant":"body"},{"id":"c17","component":"Text","text":"+1-555-0182","variant":"body"},{"id":"c18","component":"Text","text":"VP Marketing","variant":"body"},{"id":"c19","component":"Text","text":"Brightwave","variant":"body"},{"id":"c20","component":"Row","children":["c15","c16","c17","c18","c19"]},{"id":"c21","component":"Text","text":"Aiden Park","variant":"body"},{"id":"c22","component":"Text","text":"aiden@meridian.com","variant":"body"},{"id":"c23","component":"Text","text":"+1-555-0301","variant":"body"},{"id":"c24","component":"Text","text":"CEO","variant":"body"},{"id":"c25","component":"Text","text":"Meridian","variant":"body"},{"id":"c26","component":"Row","children":["c21","c22","c23","c24","c25"]},{"id":"root","component":"Column","children":["c1","c7","c8","c14","c20","c26"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Contact · large</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-table"><div class="ws-title">3 contacts</div><table><thead><tr><th>Name</th><th>Email</th><th>Phone</th><th>Title</th><th>Company</th></tr></thead><tbody><tr data-widget-anchor="row[0]"><td>Jordan Lee</td><td>jordan@acme.com</td><td>+1-555-0101</td><td>Director of Ops</td><td>Acme</td></tr><tr data-widget-anchor="row[1]"><td>Maria Santos</td><td>maria@brightwave.com</td><td>+1-555-0182</td><td>VP Marketing</td><td>Brightwave</td></tr><tr data-widget-anchor="row[2]"><td>Aiden Park</td><td>aiden@meridian.com</td><td>+1-555-0301</td><td>CEO</td><td>Meridian</td></tr></tbody></table></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"table","title":"3 contacts","columns":["Name","Email","Phone","Title","Company"],"rows":[{"Name":"Jordan Lee","Email":"jordan@acme.com","Phone":"+1-555-0101","Title":"Director of Ops","Company":"Acme"},{"Name":"Maria Santos","Email":"maria@brightwave.com","Phone":"+1-555-0182","Title":"VP Marketing","Company":"Brightwave"},{"Name":"Aiden Park","Email":"aiden@meridian.com","Phone":"+1-555-0301","Title":"CEO","Company":"Meridian"}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
xlarge ~84 tokens
3 contacts
NameEmailPhoneTitleCompany
Jordan Leejordan@acme.com+1-555-0101Director of OpsAcme
Maria Santosmaria@brightwave.com+1-555-0182VP MarketingBrightwave
Aiden Parkaiden@meridian.com+1-555-0301CEOMeridian
3 contacts
NameEmailPhoneTitleCompany
Jordan Leejordan@acme.com+1-555-0101Director of OpsAcme
Maria Santosmaria@brightwave.com+1-555-0182VP MarketingBrightwave
Aiden Parkaiden@meridian.com+1-555-0301CEOMeridian
{ "type": "table", "title": "3 contacts", "columns": [ "Name", "Email", "Phone", "Title", "Company" ], "rows": [ { "Name": "Jordan Lee", "Email": "jordan@acme.com", "Phone": "+1-555-0101", "Title": "Director of Ops", "Company": "Acme" }, { "Name": "Maria Santos", "Email": "maria@brightwave.com", "Phone": "+1-555-0182", "Title": "VP Marketing", "Company": "Brightwave" }, { "Name": "Aiden Park", "Email": "aiden@meridian.com", "Phone": "+1-555-0301", "Title": "CEO", "Company": "Meridian" } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Contact-xlarge","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Contact-xlarge","components":[{"id":"c1","component":"Text","text":"3 contacts","variant":"h2"},{"id":"c2","component":"Text","text":"Name","variant":"h5"},{"id":"c3","component":"Text","text":"Email","variant":"h5"},{"id":"c4","component":"Text","text":"Phone","variant":"h5"},{"id":"c5","component":"Text","text":"Title","variant":"h5"},{"id":"c6","component":"Text","text":"Company","variant":"h5"},{"id":"c7","component":"Row","children":["c2","c3","c4","c5","c6"]},{"id":"c8","component":"Divider"},{"id":"c9","component":"Text","text":"Jordan Lee","variant":"body"},{"id":"c10","component":"Text","text":"jordan@acme.com","variant":"body"},{"id":"c11","component":"Text","text":"+1-555-0101","variant":"body"},{"id":"c12","component":"Text","text":"Director of Ops","variant":"body"},{"id":"c13","component":"Text","text":"Acme","variant":"body"},{"id":"c14","component":"Row","children":["c9","c10","c11","c12","c13"]},{"id":"c15","component":"Text","text":"Maria Santos","variant":"body"},{"id":"c16","component":"Text","text":"maria@brightwave.com","variant":"body"},{"id":"c17","component":"Text","text":"+1-555-0182","variant":"body"},{"id":"c18","component":"Text","text":"VP Marketing","variant":"body"},{"id":"c19","component":"Text","text":"Brightwave","variant":"body"},{"id":"c20","component":"Row","children":["c15","c16","c17","c18","c19"]},{"id":"c21","component":"Text","text":"Aiden Park","variant":"body"},{"id":"c22","component":"Text","text":"aiden@meridian.com","variant":"body"},{"id":"c23","component":"Text","text":"+1-555-0301","variant":"body"},{"id":"c24","component":"Text","text":"CEO","variant":"body"},{"id":"c25","component":"Text","text":"Meridian","variant":"body"},{"id":"c26","component":"Row","children":["c21","c22","c23","c24","c25"]},{"id":"root","component":"Column","children":["c1","c7","c8","c14","c20","c26"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Contact · xlarge</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-table"><div class="ws-title">3 contacts</div><table><thead><tr><th>Name</th><th>Email</th><th>Phone</th><th>Title</th><th>Company</th></tr></thead><tbody><tr data-widget-anchor="row[0]"><td>Jordan Lee</td><td>jordan@acme.com</td><td>+1-555-0101</td><td>Director of Ops</td><td>Acme</td></tr><tr data-widget-anchor="row[1]"><td>Maria Santos</td><td>maria@brightwave.com</td><td>+1-555-0182</td><td>VP Marketing</td><td>Brightwave</td></tr><tr data-widget-anchor="row[2]"><td>Aiden Park</td><td>aiden@meridian.com</td><td>+1-555-0301</td><td>CEO</td><td>Meridian</td></tr></tbody></table></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"table","title":"3 contacts","columns":["Name","Email","Phone","Title","Company"],"rows":[{"Name":"Jordan Lee","Email":"jordan@acme.com","Phone":"+1-555-0101","Title":"Director of Ops","Company":"Acme"},{"Name":"Maria Santos","Email":"maria@brightwave.com","Phone":"+1-555-0182","Title":"VP Marketing","Company":"Brightwave"},{"Name":"Aiden Park","Email":"aiden@meridian.com","Phone":"+1-555-0301","Title":"CEO","Company":"Meridian"}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
Event
event/calendar · view: UpcomingEvents
Canonical calendar events — what's scheduled.
A2UI Composer ↗ A2UI Theater ↗ OpenClaw Canvas ↗ ChatGPT Apps SDK ↗ MCP Apps in Claude ↗
HTML · medium
Upcoming 4 events
May 2, 10:00 AM → 10:15 AM
Daily standup
May 2, 1:00 PM → 2:00 PM
Sales review · Q2
📍 Conf Room 3
May 2, 3:30 PM → 4:00 PM
Customer call
📍 Zoom
May 4, 2026
Off-site
Markdown · medium ~55 tokens
Upcoming · 4 events

• May 2, 10:00 AM — Daily standup
• May 2, 1:00 PM — Sales review · Q2 · Conf Room 3
• May 2, 3:30 PM — Customer call · Zoom
• May 4 — Off-site
A2UI · medium · rendered by @a2ui/lit
live render via @a2ui/lit · catalog basic · v0.9
MCP Apps · medium · sandboxed iframe
how Claude/ChatGPT/VS Code render this · MIME text/html;profile=mcp-app
All sizes
icon ~5 tokens
4
Events
🔴 Events · 4
{ "type": "icon", "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5\"/>\n </svg>", "color": "red", "label": "Events", "badge": 4 }
{"version":"v0.9","createSurface":{"surfaceId":"Event-icon","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Event-icon","components":[{"id":"c1","component":"Text","text":"Events","variant":"h3"},{"id":"c2","component":"Text","text":"4","variant":"caption"},{"id":"c3","component":"Column","children":["c1","c2"]},{"id":"root","component":"Card","child":"c3"}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Event · icon</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-app-icon"> <div class="ws-app-tile" style="background:linear-gradient(160deg,#ff3b30 0%,#d92520 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5"/> </svg></div> <div class="ws-app-badge">4</div> </div> <div class="ws-app-name">Events</div> </div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"icon","glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5\"/>\n </svg>","color":"red","label":"Events","badge":4}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
small ~11 tokens
Next up
  • Daily standup
    10:00 AM
Next upDaily standup — 10:00 AM
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5\"/>\n </svg>", "color": "red", "title": "Next up" }, "body": [ { "type": "list", "items": [ { "id": "e1", "title": "Daily standup", "subtitle": "10:00 AM" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Event-small","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Event-small","components":[{"id":"c1","component":"Text","text":"Next up","variant":"h2"},{"id":"c2","component":"Text","text":"Daily standup","variant":"h4"},{"id":"c3","component":"Text","text":"10:00 AM","variant":"body"},{"id":"c4","component":"Column","children":["c2","c3"]},{"id":"c5","component":"Card","child":"c4"},{"id":"c6","component":"List","children":["c5"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c6"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Event · small</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#ff3b30 0%,#d92520 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5"/> </svg></div> </div> <span class="ws-stack-title">Next up</span> </div><div class="ws-stack-body"><div class="ws-list ws-list--vertical"><ul><li class="ws-li" data-widget-anchor="item[e1]"> <div class="ws-li-row"> <span class="ws-li-title">Daily standup</span> </div> <div class="ws-li-sub">10:00 AM</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5\"/>\n </svg>","color":"red","title":"Next up"},"body":[{"type":"list","items":[{"id":"e1","title":"Daily standup","subtitle":"10:00 AM"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
medium ~55 tokens
Upcoming 4 events
May 2, 10:00 AM → 10:15 AM
Daily standup
May 2, 1:00 PM → 2:00 PM
Sales review · Q2
📍 Conf Room 3
May 2, 3:30 PM → 4:00 PM
Customer call
📍 Zoom
May 4, 2026
Off-site
Upcoming · 4 events • May 2, 10:00 AM — Daily standup • May 2, 1:00 PM — Sales review · Q2 · Conf Room 3 • May 2, 3:30 PM — Customer call · Zoom • May 4 — Off-site
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5\"/>\n </svg>", "color": "red", "title": "Upcoming", "meta": "4 events" }, "body": [ { "type": "calendar", "events": [ { "id": "e1", "title": "Daily standup", "startsAt": "2026-05-02T10:00:00", "endsAt": "2026-05-02T10:15:00" }, { "id": "e2", "title": "Sales review · Q2", "startsAt": "2026-05-02T13:00:00", "endsAt": "2026-05-02T14:00:00", "location": "Conf Room 3" }, { "id": "e3", "title": "Customer call", "startsAt": "2026-05-02T15:30:00", "endsAt": "2026-05-02T16:00:00", "location": "Zoom" }, { "id": "e4", "title": "Off-site", "startsAt": "2026-05-04", "allDay": true } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Event-medium","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Event-medium","components":[{"id":"c1","component":"Text","text":"Upcoming","variant":"h2"},{"id":"c2","component":"Text","text":"4 events","variant":"caption"},{"id":"c3","component":"Text","text":"Daily standup","variant":"h4"},{"id":"c4","component":"Text","text":"2026-05-02T10:00:00","variant":"caption"},{"id":"c5","component":"Column","children":["c3","c4"]},{"id":"c6","component":"Card","child":"c5"},{"id":"c7","component":"Text","text":"Sales review · Q2","variant":"h4"},{"id":"c8","component":"Text","text":"2026-05-02T13:00:00","variant":"caption"},{"id":"c9","component":"Text","text":"Conf Room 3","variant":"caption"},{"id":"c10","component":"Column","children":["c7","c8","c9"]},{"id":"c11","component":"Card","child":"c10"},{"id":"c12","component":"Text","text":"Customer call","variant":"h4"},{"id":"c13","component":"Text","text":"2026-05-02T15:30:00","variant":"caption"},{"id":"c14","component":"Text","text":"Zoom","variant":"caption"},{"id":"c15","component":"Column","children":["c12","c13","c14"]},{"id":"c16","component":"Card","child":"c15"},{"id":"c17","component":"Text","text":"Off-site","variant":"h4"},{"id":"c18","component":"Text","text":"2026-05-04","variant":"caption"},{"id":"c19","component":"Column","children":["c17","c18"]},{"id":"c20","component":"Card","child":"c19"},{"id":"c21","component":"List","children":["c6","c11","c16","c20"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c2","c21"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Event · medium</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#ff3b30 0%,#d92520 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5"/> </svg></div> </div> <span class="ws-stack-title">Upcoming</span> <span class="ws-stack-meta">4 events</span> </div><div class="ws-stack-body"><div class="ws-cal"><div class="ws-cal-row" data-widget-anchor="item[e1]"> <div class="ws-cal-time">May 2, 10:00 AM → 10:15 AM</div> <div class="ws-cal-body"> <div class="ws-cal-title">Daily standup</div> </div> </div><div class="ws-cal-row" data-widget-anchor="item[e2]"> <div class="ws-cal-time">May 2, 1:00 PM → 2:00 PM</div> <div class="ws-cal-body"> <div class="ws-cal-title">Sales review · Q2</div> <div class="ws-cal-loc">📍 Conf Room 3</div> </div> </div><div class="ws-cal-row" data-widget-anchor="item[e3]"> <div class="ws-cal-time">May 2, 3:30 PM → 4:00 PM</div> <div class="ws-cal-body"> <div class="ws-cal-title">Customer call</div> <div class="ws-cal-loc">📍 Zoom</div> </div> </div><div class="ws-cal-row" data-widget-anchor="item[e4]"> <div class="ws-cal-time">May 4, 2026</div> <div class="ws-cal-body"> <div class="ws-cal-title">Off-site</div> </div> </div></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5\"/>\n </svg>","color":"red","title":"Upcoming","meta":"4 events"},"body":[{"type":"calendar","events":[{"id":"e1","title":"Daily standup","startsAt":"2026-05-02T10:00:00","endsAt":"2026-05-02T10:15:00"},{"id":"e2","title":"Sales review · Q2","startsAt":"2026-05-02T13:00:00","endsAt":"2026-05-02T14:00:00","location":"Conf Room 3"},{"id":"e3","title":"Customer call","startsAt":"2026-05-02T15:30:00","endsAt":"2026-05-02T16:00:00","location":"Zoom"},{"id":"e4","title":"Off-site","startsAt":"2026-05-04","allDay":true}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
large ~51 tokens
Upcoming
May 2, 10:00 AM → 10:15 AM
Daily standup
alice@team, bob@team
May 2, 1:00 PM → 2:00 PM
Sales review · Q2
📍 Conf Room 3
May 2, 3:30 PM → 4:00 PM
Customer call
📍 Zoom
May 4, 2026
Off-site
UpcomingMay 2, 10:00 AM — Daily standup • May 2, 1:00 PM — Sales review · Q2 · Conf Room 3 • May 2, 3:30 PM — Customer call · Zoom • May 4 — Off-site
{ "type": "calendar", "title": "Upcoming", "events": [ { "id": "e1", "title": "Daily standup", "startsAt": "2026-05-02T10:00:00", "endsAt": "2026-05-02T10:15:00", "attendees": [ "alice@team", "bob@team" ] }, { "id": "e2", "title": "Sales review · Q2", "startsAt": "2026-05-02T13:00:00", "endsAt": "2026-05-02T14:00:00", "location": "Conf Room 3" }, { "id": "e3", "title": "Customer call", "startsAt": "2026-05-02T15:30:00", "endsAt": "2026-05-02T16:00:00", "location": "Zoom" }, { "id": "e4", "title": "Off-site", "startsAt": "2026-05-04", "allDay": true } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Event-large","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Event-large","components":[{"id":"c1","component":"Text","text":"Upcoming","variant":"h2"},{"id":"c2","component":"Text","text":"Daily standup","variant":"h4"},{"id":"c3","component":"Text","text":"2026-05-02T10:00:00","variant":"caption"},{"id":"c4","component":"Column","children":["c2","c3"]},{"id":"c5","component":"Card","child":"c4"},{"id":"c6","component":"Text","text":"Sales review · Q2","variant":"h4"},{"id":"c7","component":"Text","text":"2026-05-02T13:00:00","variant":"caption"},{"id":"c8","component":"Text","text":"Conf Room 3","variant":"caption"},{"id":"c9","component":"Column","children":["c6","c7","c8"]},{"id":"c10","component":"Card","child":"c9"},{"id":"c11","component":"Text","text":"Customer call","variant":"h4"},{"id":"c12","component":"Text","text":"2026-05-02T15:30:00","variant":"caption"},{"id":"c13","component":"Text","text":"Zoom","variant":"caption"},{"id":"c14","component":"Column","children":["c11","c12","c13"]},{"id":"c15","component":"Card","child":"c14"},{"id":"c16","component":"Text","text":"Off-site","variant":"h4"},{"id":"c17","component":"Text","text":"2026-05-04","variant":"caption"},{"id":"c18","component":"Column","children":["c16","c17"]},{"id":"c19","component":"Card","child":"c18"},{"id":"root","component":"List","children":["c1","c5","c10","c15","c19"],"direction":"vertical"}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Event · large</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-cal"><div class="ws-title">Upcoming</div><div class="ws-cal-row" data-widget-anchor="item[e1]"> <div class="ws-cal-time">May 2, 10:00 AM → 10:15 AM</div> <div class="ws-cal-body"> <div class="ws-cal-title">Daily standup</div> <div class="ws-cal-att">alice@team, bob@team</div> </div> </div><div class="ws-cal-row" data-widget-anchor="item[e2]"> <div class="ws-cal-time">May 2, 1:00 PM → 2:00 PM</div> <div class="ws-cal-body"> <div class="ws-cal-title">Sales review · Q2</div> <div class="ws-cal-loc">📍 Conf Room 3</div> </div> </div><div class="ws-cal-row" data-widget-anchor="item[e3]"> <div class="ws-cal-time">May 2, 3:30 PM → 4:00 PM</div> <div class="ws-cal-body"> <div class="ws-cal-title">Customer call</div> <div class="ws-cal-loc">📍 Zoom</div> </div> </div><div class="ws-cal-row" data-widget-anchor="item[e4]"> <div class="ws-cal-time">May 4, 2026</div> <div class="ws-cal-body"> <div class="ws-cal-title">Off-site</div> </div> </div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"calendar","title":"Upcoming","events":[{"id":"e1","title":"Daily standup","startsAt":"2026-05-02T10:00:00","endsAt":"2026-05-02T10:15:00","attendees":["alice@team","bob@team"]},{"id":"e2","title":"Sales review · Q2","startsAt":"2026-05-02T13:00:00","endsAt":"2026-05-02T14:00:00","location":"Conf Room 3"},{"id":"e3","title":"Customer call","startsAt":"2026-05-02T15:30:00","endsAt":"2026-05-02T16:00:00","location":"Zoom"},{"id":"e4","title":"Off-site","startsAt":"2026-05-04","allDay":true}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
xlarge ~51 tokens
Upcoming
May 2, 10:00 AM → 10:15 AM
Daily standup
alice@team, bob@team
May 2, 1:00 PM → 2:00 PM
Sales review · Q2
📍 Conf Room 3
May 2, 3:30 PM → 4:00 PM
Customer call
📍 Zoom
May 4, 2026
Off-site
UpcomingMay 2, 10:00 AM — Daily standup • May 2, 1:00 PM — Sales review · Q2 · Conf Room 3 • May 2, 3:30 PM — Customer call · Zoom • May 4 — Off-site
{ "type": "calendar", "title": "Upcoming", "events": [ { "id": "e1", "title": "Daily standup", "startsAt": "2026-05-02T10:00:00", "endsAt": "2026-05-02T10:15:00", "attendees": [ "alice@team", "bob@team" ] }, { "id": "e2", "title": "Sales review · Q2", "startsAt": "2026-05-02T13:00:00", "endsAt": "2026-05-02T14:00:00", "location": "Conf Room 3" }, { "id": "e3", "title": "Customer call", "startsAt": "2026-05-02T15:30:00", "endsAt": "2026-05-02T16:00:00", "location": "Zoom" }, { "id": "e4", "title": "Off-site", "startsAt": "2026-05-04", "allDay": true } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Event-xlarge","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Event-xlarge","components":[{"id":"c1","component":"Text","text":"Upcoming","variant":"h2"},{"id":"c2","component":"Text","text":"Daily standup","variant":"h4"},{"id":"c3","component":"Text","text":"2026-05-02T10:00:00","variant":"caption"},{"id":"c4","component":"Column","children":["c2","c3"]},{"id":"c5","component":"Card","child":"c4"},{"id":"c6","component":"Text","text":"Sales review · Q2","variant":"h4"},{"id":"c7","component":"Text","text":"2026-05-02T13:00:00","variant":"caption"},{"id":"c8","component":"Text","text":"Conf Room 3","variant":"caption"},{"id":"c9","component":"Column","children":["c6","c7","c8"]},{"id":"c10","component":"Card","child":"c9"},{"id":"c11","component":"Text","text":"Customer call","variant":"h4"},{"id":"c12","component":"Text","text":"2026-05-02T15:30:00","variant":"caption"},{"id":"c13","component":"Text","text":"Zoom","variant":"caption"},{"id":"c14","component":"Column","children":["c11","c12","c13"]},{"id":"c15","component":"Card","child":"c14"},{"id":"c16","component":"Text","text":"Off-site","variant":"h4"},{"id":"c17","component":"Text","text":"2026-05-04","variant":"caption"},{"id":"c18","component":"Column","children":["c16","c17"]},{"id":"c19","component":"Card","child":"c18"},{"id":"root","component":"List","children":["c1","c5","c10","c15","c19"],"direction":"vertical"}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Event · xlarge</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-cal"><div class="ws-title">Upcoming</div><div class="ws-cal-row" data-widget-anchor="item[e1]"> <div class="ws-cal-time">May 2, 10:00 AM → 10:15 AM</div> <div class="ws-cal-body"> <div class="ws-cal-title">Daily standup</div> <div class="ws-cal-att">alice@team, bob@team</div> </div> </div><div class="ws-cal-row" data-widget-anchor="item[e2]"> <div class="ws-cal-time">May 2, 1:00 PM → 2:00 PM</div> <div class="ws-cal-body"> <div class="ws-cal-title">Sales review · Q2</div> <div class="ws-cal-loc">📍 Conf Room 3</div> </div> </div><div class="ws-cal-row" data-widget-anchor="item[e3]"> <div class="ws-cal-time">May 2, 3:30 PM → 4:00 PM</div> <div class="ws-cal-body"> <div class="ws-cal-title">Customer call</div> <div class="ws-cal-loc">📍 Zoom</div> </div> </div><div class="ws-cal-row" data-widget-anchor="item[e4]"> <div class="ws-cal-time">May 4, 2026</div> <div class="ws-cal-body"> <div class="ws-cal-title">Off-site</div> </div> </div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"calendar","title":"Upcoming","events":[{"id":"e1","title":"Daily standup","startsAt":"2026-05-02T10:00:00","endsAt":"2026-05-02T10:15:00","attendees":["alice@team","bob@team"]},{"id":"e2","title":"Sales review · Q2","startsAt":"2026-05-02T13:00:00","endsAt":"2026-05-02T14:00:00","location":"Conf Room 3"},{"id":"e3","title":"Customer call","startsAt":"2026-05-02T15:30:00","endsAt":"2026-05-02T16:00:00","location":"Zoom"},{"id":"e4","title":"Off-site","startsAt":"2026-05-04","allDay":true}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
Task
task/list · view: TaskBoard
Canonical task list — work items with status + assignee.
A2UI Composer ↗ A2UI Theater ↗ OpenClaw Canvas ↗ ChatGPT Apps SDK ↗ MCP Apps in Claude ↗
HTML · medium
Sprint board
1
In progress
1
Done
1
Blocked
TitleStatusAssignee
Implement OAuth2 PKCE flow for mobile clientsdonealice
Migrate user table to UUID primary keysin_progressbob
Add rate limiting to public API endpointstodoalice
Investigate race condition in payment webhookblockedcarol
Markdown · medium ~101 tokens
Sprint board

In progress: 1 · Done: 1 · Blocked: 1

TitleStatusAssignee
Implement OAuth2 PKCE flow for mobile clientsdonealice
Migrate user table to UUID primary keysin_progressbob
Add rate limiting to public API endpointstodoalice
Investigate race condition in payment webhookblockedcarol
A2UI · medium · rendered by @a2ui/lit
live render via @a2ui/lit · catalog basic · v0.9
MCP Apps · medium · sandboxed iframe
how Claude/ChatGPT/VS Code render this · MIME text/html;profile=mcp-app
All sizes
icon ~5 tokens
2
Tasks
🟠 Tasks · 2
{ "type": "icon", "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\"/>\n </svg>", "color": "orange", "label": "Tasks", "badge": 2 }
{"version":"v0.9","createSurface":{"surfaceId":"Task-icon","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Task-icon","components":[{"id":"c1","component":"Text","text":"Tasks","variant":"h3"},{"id":"c2","component":"Text","text":"2","variant":"caption"},{"id":"c3","component":"Column","children":["c1","c2"]},{"id":"root","component":"Card","child":"c3"}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Task · icon</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-app-icon"> <div class="ws-app-tile" style="background:linear-gradient(160deg,#ff9500 0%,#e07700 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/> </svg></div> <div class="ws-app-badge">2</div> </div> <div class="ws-app-name">Tasks</div> </div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"icon","glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\"/>\n </svg>","color":"orange","label":"Tasks","badge":2}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
small ~16 tokens
Tasks
  • 1 in progress · 1 done
    ⚠️ 1 blocked
Tasks1 in progress · 1 done — ⚠️ 1 blocked
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\"/>\n </svg>", "color": "orange", "title": "Tasks" }, "body": [ { "type": "list", "items": [ { "title": "1 in progress · 1 done", "subtitle": "⚠️ 1 blocked" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Task-small","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Task-small","components":[{"id":"c1","component":"Text","text":"Tasks","variant":"h2"},{"id":"c2","component":"Text","text":"1 in progress · 1 done","variant":"h4"},{"id":"c3","component":"Text","text":"⚠️ 1 blocked","variant":"body"},{"id":"c4","component":"Column","children":["c2","c3"]},{"id":"c5","component":"Card","child":"c4"},{"id":"c6","component":"List","children":["c5"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c6"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Task · small</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#ff9500 0%,#e07700 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/> </svg></div> </div> <span class="ws-stack-title">Tasks</span> </div><div class="ws-stack-body"><div class="ws-list ws-list--vertical"><ul><li class="ws-li" data-widget-anchor="row[0]"> <div class="ws-li-row"> <span class="ws-li-title">1 in progress · 1 done</span> </div> <div class="ws-li-sub">⚠️ 1 blocked</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\"/>\n </svg>","color":"orange","title":"Tasks"},"body":[{"type":"list","items":[{"title":"1 in progress · 1 done","subtitle":"⚠️ 1 blocked"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
medium ~101 tokens
Sprint board
1
In progress
1
Done
1
Blocked
TitleStatusAssignee
Implement OAuth2 PKCE flow for mobile clientsdonealice
Migrate user table to UUID primary keysin_progressbob
Add rate limiting to public API endpointstodoalice
Investigate race condition in payment webhookblockedcarol
Sprint board In progress: 1 · Done: 1 · Blocked: 1
TitleStatusAssignee
Implement OAuth2 PKCE flow for mobile clientsdonealice
Migrate user table to UUID primary keysin_progressbob
Add rate limiting to public API endpointstodoalice
Investigate race condition in payment webhookblockedcarol
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\"/>\n </svg>", "color": "orange", "title": "Sprint board" }, "body": [ { "type": "metric_grid", "metrics": [ { "type": "metric", "id": "in_progress", "value": 1, "label": "In progress" }, { "type": "metric", "id": "done", "value": 1, "label": "Done" }, { "type": "metric", "id": "blocked", "value": 1, "label": "Blocked", "trend": "down" } ] }, { "type": "table", "columns": [ "Title", "Status", "Assignee" ], "rows": [ { "Title": "Implement OAuth2 PKCE flow for mobile clients", "Status": "done", "Assignee": "alice" }, { "Title": "Migrate user table to UUID primary keys", "Status": "in_progress", "Assignee": "bob" }, { "Title": "Add rate limiting to public API endpoints", "Status": "todo", "Assignee": "alice" }, { "Title": "Investigate race condition in payment webhook", "Status": "blocked", "Assignee": "carol" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Task-medium","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Task-medium","components":[{"id":"c1","component":"Text","text":"Sprint board","variant":"h2"},{"id":"c2","component":"Text","text":"In progress","variant":"caption"},{"id":"c3","component":"Text","text":"1","variant":"h1"},{"id":"c4","component":"Column","children":["c2","c3"]},{"id":"c5","component":"Card","child":"c4"},{"id":"c6","component":"Text","text":"Done","variant":"caption"},{"id":"c7","component":"Text","text":"1","variant":"h1"},{"id":"c8","component":"Column","children":["c6","c7"]},{"id":"c9","component":"Card","child":"c8"},{"id":"c10","component":"Text","text":"Blocked","variant":"caption"},{"id":"c11","component":"Text","text":"1","variant":"h1"},{"id":"c12","component":"Column","children":["c10","c11"]},{"id":"c13","component":"Card","child":"c12"},{"id":"c14","component":"Row","children":["c5","c9","c13"],"justify":"spaceBetween"},{"id":"c15","component":"Text","text":"Title","variant":"h5"},{"id":"c16","component":"Text","text":"Status","variant":"h5"},{"id":"c17","component":"Text","text":"Assignee","variant":"h5"},{"id":"c18","component":"Row","children":["c15","c16","c17"]},{"id":"c19","component":"Divider"},{"id":"c20","component":"Text","text":"Implement OAuth2 PKCE flow for mobile clients","variant":"body"},{"id":"c21","component":"Text","text":"done","variant":"body"},{"id":"c22","component":"Text","text":"alice","variant":"body"},{"id":"c23","component":"Row","children":["c20","c21","c22"]},{"id":"c24","component":"Text","text":"Migrate user table to UUID primary keys","variant":"body"},{"id":"c25","component":"Text","text":"in_progress","variant":"body"},{"id":"c26","component":"Text","text":"bob","variant":"body"},{"id":"c27","component":"Row","children":["c24","c25","c26"]},{"id":"c28","component":"Text","text":"Add rate limiting to public API endpoints","variant":"body"},{"id":"c29","component":"Text","text":"todo","variant":"body"},{"id":"c30","component":"Text","text":"alice","variant":"body"},{"id":"c31","component":"Row","children":["c28","c29","c30"]},{"id":"c32","component":"Text","text":"Investigate race condition in payment webhook","variant":"body"},{"id":"c33","component":"Text","text":"blocked","variant":"body"},{"id":"c34","component":"Text","text":"carol","variant":"body"},{"id":"c35","component":"Row","children":["c32","c33","c34"]},{"id":"c36","component":"Column","children":["c18","c19","c23","c27","c31","c35"]},{"id":"root","component":"Column","children":["c1","c14","c36"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Task · medium</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#ff9500 0%,#e07700 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/> </svg></div> </div> <span class="ws-stack-title">Sprint board</span> </div><div class="ws-stack-body"><div class="ws-grid-3"><div class="ws-metric" data-widget-anchor="metric[in_progress]"> <div class="ws-metric-value">1</div> <div class="ws-metric-label">In progress</div> </div><div class="ws-metric" data-widget-anchor="metric[done]"> <div class="ws-metric-value">1</div> <div class="ws-metric-label">Done</div> </div><div class="ws-metric" data-widget-anchor="metric[blocked]"> <div class="ws-metric-value">1</div> <div class="ws-metric-label">Blocked</div> </div></div><div class="ws-table"><table><thead><tr><th>Title</th><th>Status</th><th>Assignee</th></tr></thead><tbody><tr data-widget-anchor="row[0]"><td>Implement OAuth2 PKCE flow for mobile clients</td><td>done</td><td>alice</td></tr><tr data-widget-anchor="row[1]"><td>Migrate user table to UUID primary keys</td><td>in_progress</td><td>bob</td></tr><tr data-widget-anchor="row[2]"><td>Add rate limiting to public API endpoints</td><td>todo</td><td>alice</td></tr><tr data-widget-anchor="row[3]"><td>Investigate race condition in payment webhook</td><td>blocked</td><td>carol</td></tr></tbody></table></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\"/>\n </svg>","color":"orange","title":"Sprint board"},"body":[{"type":"metric_grid","metrics":[{"type":"metric","id":"in_progress","value":1,"label":"In progress"},{"type":"metric","id":"done","value":1,"label":"Done"},{"type":"metric","id":"blocked","value":1,"label":"Blocked","trend":"down"}]},{"type":"table","columns":["Title","Status","Assignee"],"rows":[{"Title":"Implement OAuth2 PKCE flow for mobile clients","Status":"done","Assignee":"alice"},{"Title":"Migrate user table to UUID primary keys","Status":"in_progress","Assignee":"bob"},{"Title":"Add rate limiting to public API endpoints","Status":"todo","Assignee":"alice"},{"Title":"Investigate race condition in payment webhook","Status":"blocked","Assignee":"carol"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
large ~119 tokens
Sprint board
1
In progress
1
Done
1
Blocked
Tasks
TitleStatusAssigneePriority
Implement OAuth2 PKCE flow for mobile clientsdonealicehigh
Migrate user table to UUID primary keysin_progressbobhigh
Add rate limiting to public API endpointstodoalicemedium
Investigate race condition in payment webhookblockedcarolmedium
Sprint board In progress: 1 · Done: 1 · Blocked: 1 Tasks
TitleStatusAssigneePriority
Implement OAuth2 PKCE flow for mobile clientsdonealicehigh
Migrate user table to UUID primary keysin_progressbobhigh
Add rate limiting to public API endpointstodoalicemedium
Investigate race condition in payment webhookblockedcarolmedium
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\"/>\n </svg>", "color": "orange", "title": "Sprint board" }, "body": [ { "type": "metric_grid", "metrics": [ { "type": "metric", "id": "in_progress", "value": 1, "label": "In progress" }, { "type": "metric", "id": "done", "value": 1, "label": "Done" }, { "type": "metric", "id": "blocked", "value": 1, "label": "Blocked", "trend": "down" } ] }, { "type": "table", "title": "Tasks", "columns": [ "Title", "Status", "Assignee", "Priority" ], "rows": [ { "Title": "Implement OAuth2 PKCE flow for mobile clients", "Status": "done", "Assignee": "alice", "Priority": "high" }, { "Title": "Migrate user table to UUID primary keys", "Status": "in_progress", "Assignee": "bob", "Priority": "high" }, { "Title": "Add rate limiting to public API endpoints", "Status": "todo", "Assignee": "alice", "Priority": "medium" }, { "Title": "Investigate race condition in payment webhook", "Status": "blocked", "Assignee": "carol", "Priority": "medium" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Task-large","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Task-large","components":[{"id":"c1","component":"Text","text":"Sprint board","variant":"h2"},{"id":"c2","component":"Text","text":"In progress","variant":"caption"},{"id":"c3","component":"Text","text":"1","variant":"h1"},{"id":"c4","component":"Column","children":["c2","c3"]},{"id":"c5","component":"Card","child":"c4"},{"id":"c6","component":"Text","text":"Done","variant":"caption"},{"id":"c7","component":"Text","text":"1","variant":"h1"},{"id":"c8","component":"Column","children":["c6","c7"]},{"id":"c9","component":"Card","child":"c8"},{"id":"c10","component":"Text","text":"Blocked","variant":"caption"},{"id":"c11","component":"Text","text":"1","variant":"h1"},{"id":"c12","component":"Column","children":["c10","c11"]},{"id":"c13","component":"Card","child":"c12"},{"id":"c14","component":"Row","children":["c5","c9","c13"],"justify":"spaceBetween"},{"id":"c15","component":"Text","text":"Tasks","variant":"h2"},{"id":"c16","component":"Text","text":"Title","variant":"h5"},{"id":"c17","component":"Text","text":"Status","variant":"h5"},{"id":"c18","component":"Text","text":"Assignee","variant":"h5"},{"id":"c19","component":"Text","text":"Priority","variant":"h5"},{"id":"c20","component":"Row","children":["c16","c17","c18","c19"]},{"id":"c21","component":"Divider"},{"id":"c22","component":"Text","text":"Implement OAuth2 PKCE flow for mobile clients","variant":"body"},{"id":"c23","component":"Text","text":"done","variant":"body"},{"id":"c24","component":"Text","text":"alice","variant":"body"},{"id":"c25","component":"Text","text":"high","variant":"body"},{"id":"c26","component":"Row","children":["c22","c23","c24","c25"]},{"id":"c27","component":"Text","text":"Migrate user table to UUID primary keys","variant":"body"},{"id":"c28","component":"Text","text":"in_progress","variant":"body"},{"id":"c29","component":"Text","text":"bob","variant":"body"},{"id":"c30","component":"Text","text":"high","variant":"body"},{"id":"c31","component":"Row","children":["c27","c28","c29","c30"]},{"id":"c32","component":"Text","text":"Add rate limiting to public API endpoints","variant":"body"},{"id":"c33","component":"Text","text":"todo","variant":"body"},{"id":"c34","component":"Text","text":"alice","variant":"body"},{"id":"c35","component":"Text","text":"medium","variant":"body"},{"id":"c36","component":"Row","children":["c32","c33","c34","c35"]},{"id":"c37","component":"Text","text":"Investigate race condition in payment webhook","variant":"body"},{"id":"c38","component":"Text","text":"blocked","variant":"body"},{"id":"c39","component":"Text","text":"carol","variant":"body"},{"id":"c40","component":"Text","text":"medium","variant":"body"},{"id":"c41","component":"Row","children":["c37","c38","c39","c40"]},{"id":"c42","component":"Column","children":["c15","c20","c21","c26","c31","c36","c41"]},{"id":"root","component":"Column","children":["c1","c14","c42"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Task · large</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#ff9500 0%,#e07700 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/> </svg></div> </div> <span class="ws-stack-title">Sprint board</span> </div><div class="ws-stack-body"><div class="ws-grid-3"><div class="ws-metric" data-widget-anchor="metric[in_progress]"> <div class="ws-metric-value">1</div> <div class="ws-metric-label">In progress</div> </div><div class="ws-metric" data-widget-anchor="metric[done]"> <div class="ws-metric-value">1</div> <div class="ws-metric-label">Done</div> </div><div class="ws-metric" data-widget-anchor="metric[blocked]"> <div class="ws-metric-value">1</div> <div class="ws-metric-label">Blocked</div> </div></div><div class="ws-table"><div class="ws-title">Tasks</div><table><thead><tr><th>Title</th><th>Status</th><th>Assignee</th><th>Priority</th></tr></thead><tbody><tr data-widget-anchor="row[0]"><td>Implement OAuth2 PKCE flow for mobile clients</td><td>done</td><td>alice</td><td>high</td></tr><tr data-widget-anchor="row[1]"><td>Migrate user table to UUID primary keys</td><td>in_progress</td><td>bob</td><td>high</td></tr><tr data-widget-anchor="row[2]"><td>Add rate limiting to public API endpoints</td><td>todo</td><td>alice</td><td>medium</td></tr><tr data-widget-anchor="row[3]"><td>Investigate race condition in payment webhook</td><td>blocked</td><td>carol</td><td>medium</td></tr></tbody></table></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\"/>\n </svg>","color":"orange","title":"Sprint board"},"body":[{"type":"metric_grid","metrics":[{"type":"metric","id":"in_progress","value":1,"label":"In progress"},{"type":"metric","id":"done","value":1,"label":"Done"},{"type":"metric","id":"blocked","value":1,"label":"Blocked","trend":"down"}]},{"type":"table","title":"Tasks","columns":["Title","Status","Assignee","Priority"],"rows":[{"Title":"Implement OAuth2 PKCE flow for mobile clients","Status":"done","Assignee":"alice","Priority":"high"},{"Title":"Migrate user table to UUID primary keys","Status":"in_progress","Assignee":"bob","Priority":"high"},{"Title":"Add rate limiting to public API endpoints","Status":"todo","Assignee":"alice","Priority":"medium"},{"Title":"Investigate race condition in payment webhook","Status":"blocked","Assignee":"carol","Priority":"medium"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
xlarge ~119 tokens
Sprint board
1
In progress
1
Done
1
Blocked
Tasks
TitleStatusAssigneePriority
Implement OAuth2 PKCE flow for mobile clientsdonealicehigh
Migrate user table to UUID primary keysin_progressbobhigh
Add rate limiting to public API endpointstodoalicemedium
Investigate race condition in payment webhookblockedcarolmedium
Sprint board In progress: 1 · Done: 1 · Blocked: 1 Tasks
TitleStatusAssigneePriority
Implement OAuth2 PKCE flow for mobile clientsdonealicehigh
Migrate user table to UUID primary keysin_progressbobhigh
Add rate limiting to public API endpointstodoalicemedium
Investigate race condition in payment webhookblockedcarolmedium
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\"/>\n </svg>", "color": "orange", "title": "Sprint board" }, "body": [ { "type": "metric_grid", "metrics": [ { "type": "metric", "id": "in_progress", "value": 1, "label": "In progress" }, { "type": "metric", "id": "done", "value": 1, "label": "Done" }, { "type": "metric", "id": "blocked", "value": 1, "label": "Blocked", "trend": "down" } ] }, { "type": "table", "title": "Tasks", "columns": [ "Title", "Status", "Assignee", "Priority" ], "rows": [ { "Title": "Implement OAuth2 PKCE flow for mobile clients", "Status": "done", "Assignee": "alice", "Priority": "high" }, { "Title": "Migrate user table to UUID primary keys", "Status": "in_progress", "Assignee": "bob", "Priority": "high" }, { "Title": "Add rate limiting to public API endpoints", "Status": "todo", "Assignee": "alice", "Priority": "medium" }, { "Title": "Investigate race condition in payment webhook", "Status": "blocked", "Assignee": "carol", "Priority": "medium" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Task-xlarge","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Task-xlarge","components":[{"id":"c1","component":"Text","text":"Sprint board","variant":"h2"},{"id":"c2","component":"Text","text":"In progress","variant":"caption"},{"id":"c3","component":"Text","text":"1","variant":"h1"},{"id":"c4","component":"Column","children":["c2","c3"]},{"id":"c5","component":"Card","child":"c4"},{"id":"c6","component":"Text","text":"Done","variant":"caption"},{"id":"c7","component":"Text","text":"1","variant":"h1"},{"id":"c8","component":"Column","children":["c6","c7"]},{"id":"c9","component":"Card","child":"c8"},{"id":"c10","component":"Text","text":"Blocked","variant":"caption"},{"id":"c11","component":"Text","text":"1","variant":"h1"},{"id":"c12","component":"Column","children":["c10","c11"]},{"id":"c13","component":"Card","child":"c12"},{"id":"c14","component":"Row","children":["c5","c9","c13"],"justify":"spaceBetween"},{"id":"c15","component":"Text","text":"Tasks","variant":"h2"},{"id":"c16","component":"Text","text":"Title","variant":"h5"},{"id":"c17","component":"Text","text":"Status","variant":"h5"},{"id":"c18","component":"Text","text":"Assignee","variant":"h5"},{"id":"c19","component":"Text","text":"Priority","variant":"h5"},{"id":"c20","component":"Row","children":["c16","c17","c18","c19"]},{"id":"c21","component":"Divider"},{"id":"c22","component":"Text","text":"Implement OAuth2 PKCE flow for mobile clients","variant":"body"},{"id":"c23","component":"Text","text":"done","variant":"body"},{"id":"c24","component":"Text","text":"alice","variant":"body"},{"id":"c25","component":"Text","text":"high","variant":"body"},{"id":"c26","component":"Row","children":["c22","c23","c24","c25"]},{"id":"c27","component":"Text","text":"Migrate user table to UUID primary keys","variant":"body"},{"id":"c28","component":"Text","text":"in_progress","variant":"body"},{"id":"c29","component":"Text","text":"bob","variant":"body"},{"id":"c30","component":"Text","text":"high","variant":"body"},{"id":"c31","component":"Row","children":["c27","c28","c29","c30"]},{"id":"c32","component":"Text","text":"Add rate limiting to public API endpoints","variant":"body"},{"id":"c33","component":"Text","text":"todo","variant":"body"},{"id":"c34","component":"Text","text":"alice","variant":"body"},{"id":"c35","component":"Text","text":"medium","variant":"body"},{"id":"c36","component":"Row","children":["c32","c33","c34","c35"]},{"id":"c37","component":"Text","text":"Investigate race condition in payment webhook","variant":"body"},{"id":"c38","component":"Text","text":"blocked","variant":"body"},{"id":"c39","component":"Text","text":"carol","variant":"body"},{"id":"c40","component":"Text","text":"medium","variant":"body"},{"id":"c41","component":"Row","children":["c37","c38","c39","c40"]},{"id":"c42","component":"Column","children":["c15","c20","c21","c26","c31","c36","c41"]},{"id":"root","component":"Column","children":["c1","c14","c42"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Task · xlarge</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#ff9500 0%,#e07700 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/> </svg></div> </div> <span class="ws-stack-title">Sprint board</span> </div><div class="ws-stack-body"><div class="ws-grid-3"><div class="ws-metric" data-widget-anchor="metric[in_progress]"> <div class="ws-metric-value">1</div> <div class="ws-metric-label">In progress</div> </div><div class="ws-metric" data-widget-anchor="metric[done]"> <div class="ws-metric-value">1</div> <div class="ws-metric-label">Done</div> </div><div class="ws-metric" data-widget-anchor="metric[blocked]"> <div class="ws-metric-value">1</div> <div class="ws-metric-label">Blocked</div> </div></div><div class="ws-table"><div class="ws-title">Tasks</div><table><thead><tr><th>Title</th><th>Status</th><th>Assignee</th><th>Priority</th></tr></thead><tbody><tr data-widget-anchor="row[0]"><td>Implement OAuth2 PKCE flow for mobile clients</td><td>done</td><td>alice</td><td>high</td></tr><tr data-widget-anchor="row[1]"><td>Migrate user table to UUID primary keys</td><td>in_progress</td><td>bob</td><td>high</td></tr><tr data-widget-anchor="row[2]"><td>Add rate limiting to public API endpoints</td><td>todo</td><td>alice</td><td>medium</td></tr><tr data-widget-anchor="row[3]"><td>Investigate race condition in payment webhook</td><td>blocked</td><td>carol</td><td>medium</td></tr></tbody></table></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\"/>\n </svg>","color":"orange","title":"Sprint board"},"body":[{"type":"metric_grid","metrics":[{"type":"metric","id":"in_progress","value":1,"label":"In progress"},{"type":"metric","id":"done","value":1,"label":"Done"},{"type":"metric","id":"blocked","value":1,"label":"Blocked","trend":"down"}]},{"type":"table","title":"Tasks","columns":["Title","Status","Assignee","Priority"],"rows":[{"Title":"Implement OAuth2 PKCE flow for mobile clients","Status":"done","Assignee":"alice","Priority":"high"},{"Title":"Migrate user table to UUID primary keys","Status":"in_progress","Assignee":"bob","Priority":"high"},{"Title":"Add rate limiting to public API endpoints","Status":"todo","Assignee":"alice","Priority":"medium"},{"Title":"Investigate race condition in payment webhook","Status":"blocked","Assignee":"carol","Priority":"medium"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
Document
document/collection · view: FeaturedDocument
Canonical document collection — pages with title + body.
A2UI Composer ↗ A2UI Theater ↗ OpenClaw Canvas ↗ ChatGPT Apps SDK ↗ MCP Apps in Claude ↗
HTML · medium
Featured page
Q2 launch plan
modified 2026-04-30
Overview We're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.
39 words · ~1 min
Markdown · medium ~63 tokens
Featured page

### Q2 launch plan

_ops team_

Overview

We're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.
A2UI · medium · rendered by @a2ui/lit
live render via @a2ui/lit · catalog basic · v0.9
MCP Apps · medium · sandboxed iframe
how Claude/ChatGPT/VS Code render this · MIME text/html;profile=mcp-app
All sizes
icon ~5 tokens
3
Docs
🟡 Docs · 3
{ "type": "icon", "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z\"/>\n </svg>", "color": "yellow", "label": "Docs", "badge": 3 }
{"version":"v0.9","createSurface":{"surfaceId":"Document-icon","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Document-icon","components":[{"id":"c1","component":"Text","text":"Docs","variant":"h3"},{"id":"c2","component":"Text","text":"3","variant":"caption"},{"id":"c3","component":"Column","children":["c1","c2"]},{"id":"root","component":"Card","child":"c3"}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Document · icon</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-app-icon"> <div class="ws-app-tile" style="background:linear-gradient(160deg,#ffcc00 0%,#e0a800 100%);color:#3a2a00"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"/> </svg></div> <div class="ws-app-badge">3</div> </div> <div class="ws-app-name">Docs</div> </div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"icon","glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z\"/>\n </svg>","color":"yellow","label":"Docs","badge":3}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
small ~11 tokens
3 pages
  • Q2 launch plan
    2026-04-30
3 pagesQ2 launch plan — 2026-04-30
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z\"/>\n </svg>", "color": "yellow", "title": "3 pages" }, "body": [ { "type": "list", "items": [ { "id": "d1", "title": "Q2 launch plan", "subtitle": "2026-04-30" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Document-small","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Document-small","components":[{"id":"c1","component":"Text","text":"3 pages","variant":"h2"},{"id":"c2","component":"Text","text":"Q2 launch plan","variant":"h4"},{"id":"c3","component":"Text","text":"2026-04-30","variant":"body"},{"id":"c4","component":"Column","children":["c2","c3"]},{"id":"c5","component":"Card","child":"c4"},{"id":"c6","component":"List","children":["c5"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c6"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Document · small</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#ffcc00 0%,#e0a800 100%);color:#3a2a00"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"/> </svg></div> </div> <span class="ws-stack-title">3 pages</span> </div><div class="ws-stack-body"><div class="ws-list ws-list--vertical"><ul><li class="ws-li" data-widget-anchor="item[d1]"> <div class="ws-li-row"> <span class="ws-li-title">Q2 launch plan</span> </div> <div class="ws-li-sub">2026-04-30</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z\"/>\n </svg>","color":"yellow","title":"3 pages"},"body":[{"type":"list","items":[{"id":"d1","title":"Q2 launch plan","subtitle":"2026-04-30"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
medium ~63 tokens
Featured page
Q2 launch plan
modified 2026-04-30
Overview We're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.
39 words · ~1 min
Featured page ### Q2 launch plan _ops team_ Overview We're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z\"/>\n </svg>", "color": "yellow", "title": "Featured page" }, "body": [ { "type": "document", "title": "Q2 launch plan", "body": "Overview\n\nWe're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.", "byline": "ops team", "meta": "modified 2026-04-30" } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Document-medium","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Document-medium","components":[{"id":"c1","component":"Text","text":"Featured page","variant":"h2"},{"id":"c2","component":"Text","text":"Q2 launch plan","variant":"h1"},{"id":"c3","component":"Text","text":"ops team","variant":"caption"},{"id":"c4","component":"Text","text":"Overview\n\nWe're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.","variant":"body"},{"id":"c5","component":"Column","children":["c2","c3","c4"]},{"id":"c6","component":"Card","child":"c5"},{"id":"root","component":"Column","children":["c1","c6"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Document · medium</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#ffcc00 0%,#e0a800 100%);color:#3a2a00"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"/> </svg></div> </div> <span class="ws-stack-title">Featured page</span> </div><div class="ws-stack-body"><div class="ws-doc"> <div class="ws-doc-title">Q2 launch plan</div> <div class="ws-doc-byline">ops team</div> <div class="ws-doc-meta">modified 2026-04-30</div> <div class="ws-doc-body">Overview We&#39;re shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.</div> <div class="ws-doc-stats">39 words · ~1 min</div> </div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z\"/>\n </svg>","color":"yellow","title":"Featured page"},"body":[{"type":"document","title":"Q2 launch plan","body":"Overview\n\nWe're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.","byline":"ops team","meta":"modified 2026-04-30"}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
large ~81 tokens
Featured page
Q2 launch plan
modified 2026-04-30
Overview We're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.
39 words · ~1 min
More pages
  • On-call runbook
    2026-04-29
  • Customer feedback · April
    2026-04-28
Featured page ### Q2 launch plan _ops team_ Overview We're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring. More pagesOn-call runbook — 2026-04-29 • Customer feedback · April — 2026-04-28
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z\"/>\n </svg>", "color": "yellow", "title": "Featured page" }, "body": [ { "type": "document", "title": "Q2 launch plan", "body": "Overview\n\nWe're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.", "byline": "ops team", "meta": "modified 2026-04-30" }, { "type": "list", "title": "More pages", "items": [ { "id": "d2", "title": "On-call runbook", "subtitle": "2026-04-29" }, { "id": "d3", "title": "Customer feedback · April", "subtitle": "2026-04-28" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Document-large","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Document-large","components":[{"id":"c1","component":"Text","text":"Featured page","variant":"h2"},{"id":"c2","component":"Text","text":"Q2 launch plan","variant":"h1"},{"id":"c3","component":"Text","text":"ops team","variant":"caption"},{"id":"c4","component":"Text","text":"Overview\n\nWe're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.","variant":"body"},{"id":"c5","component":"Column","children":["c2","c3","c4"]},{"id":"c6","component":"Card","child":"c5"},{"id":"c7","component":"Text","text":"More pages","variant":"h2"},{"id":"c8","component":"Text","text":"On-call runbook","variant":"h4"},{"id":"c9","component":"Text","text":"2026-04-29","variant":"body"},{"id":"c10","component":"Column","children":["c8","c9"]},{"id":"c11","component":"Card","child":"c10"},{"id":"c12","component":"Text","text":"Customer feedback · April","variant":"h4"},{"id":"c13","component":"Text","text":"2026-04-28","variant":"body"},{"id":"c14","component":"Column","children":["c12","c13"]},{"id":"c15","component":"Card","child":"c14"},{"id":"c16","component":"List","children":["c7","c11","c15"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c6","c16"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Document · large</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#ffcc00 0%,#e0a800 100%);color:#3a2a00"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"/> </svg></div> </div> <span class="ws-stack-title">Featured page</span> </div><div class="ws-stack-body"><div class="ws-doc"> <div class="ws-doc-title">Q2 launch plan</div> <div class="ws-doc-byline">ops team</div> <div class="ws-doc-meta">modified 2026-04-30</div> <div class="ws-doc-body">Overview We&#39;re shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.</div> <div class="ws-doc-stats">39 words · ~1 min</div> </div><div class="ws-list ws-list--vertical"><div class="ws-title">More pages</div><ul><li class="ws-li" data-widget-anchor="item[d2]"> <div class="ws-li-row"> <span class="ws-li-title">On-call runbook</span> </div> <div class="ws-li-sub">2026-04-29</div> </li><li class="ws-li" data-widget-anchor="item[d3]"> <div class="ws-li-row"> <span class="ws-li-title">Customer feedback · April</span> </div> <div class="ws-li-sub">2026-04-28</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z\"/>\n </svg>","color":"yellow","title":"Featured page"},"body":[{"type":"document","title":"Q2 launch plan","body":"Overview\n\nWe're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.","byline":"ops team","meta":"modified 2026-04-30"},{"type":"list","title":"More pages","items":[{"id":"d2","title":"On-call runbook","subtitle":"2026-04-29"},{"id":"d3","title":"Customer feedback · April","subtitle":"2026-04-28"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
xlarge ~81 tokens
Featured page
Q2 launch plan
modified 2026-04-30
Overview We're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.
39 words · ~1 min
More pages
  • On-call runbook
    2026-04-29
  • Customer feedback · April
    2026-04-28
Featured page ### Q2 launch plan _ops team_ Overview We're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring. More pagesOn-call runbook — 2026-04-29 • Customer feedback · April — 2026-04-28
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z\"/>\n </svg>", "color": "yellow", "title": "Featured page" }, "body": [ { "type": "document", "title": "Q2 launch plan", "body": "Overview\n\nWe're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.", "byline": "ops team", "meta": "modified 2026-04-30" }, { "type": "list", "title": "More pages", "items": [ { "id": "d2", "title": "On-call runbook", "subtitle": "2026-04-29" }, { "id": "d3", "title": "Customer feedback · April", "subtitle": "2026-04-28" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Document-xlarge","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Document-xlarge","components":[{"id":"c1","component":"Text","text":"Featured page","variant":"h2"},{"id":"c2","component":"Text","text":"Q2 launch plan","variant":"h1"},{"id":"c3","component":"Text","text":"ops team","variant":"caption"},{"id":"c4","component":"Text","text":"Overview\n\nWe're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.","variant":"body"},{"id":"c5","component":"Column","children":["c2","c3","c4"]},{"id":"c6","component":"Card","child":"c5"},{"id":"c7","component":"Text","text":"More pages","variant":"h2"},{"id":"c8","component":"Text","text":"On-call runbook","variant":"h4"},{"id":"c9","component":"Text","text":"2026-04-29","variant":"body"},{"id":"c10","component":"Column","children":["c8","c9"]},{"id":"c11","component":"Card","child":"c10"},{"id":"c12","component":"Text","text":"Customer feedback · April","variant":"h4"},{"id":"c13","component":"Text","text":"2026-04-28","variant":"body"},{"id":"c14","component":"Column","children":["c12","c13"]},{"id":"c15","component":"Card","child":"c14"},{"id":"c16","component":"List","children":["c7","c11","c15"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c6","c16"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Document · xlarge</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#ffcc00 0%,#e0a800 100%);color:#3a2a00"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"/> </svg></div> </div> <span class="ws-stack-title">Featured page</span> </div><div class="ws-stack-body"><div class="ws-doc"> <div class="ws-doc-title">Q2 launch plan</div> <div class="ws-doc-byline">ops team</div> <div class="ws-doc-meta">modified 2026-04-30</div> <div class="ws-doc-body">Overview We&#39;re shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.</div> <div class="ws-doc-stats">39 words · ~1 min</div> </div><div class="ws-list ws-list--vertical"><div class="ws-title">More pages</div><ul><li class="ws-li" data-widget-anchor="item[d2]"> <div class="ws-li-row"> <span class="ws-li-title">On-call runbook</span> </div> <div class="ws-li-sub">2026-04-29</div> </li><li class="ws-li" data-widget-anchor="item[d3]"> <div class="ws-li-row"> <span class="ws-li-title">Customer feedback · April</span> </div> <div class="ws-li-sub">2026-04-28</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z\"/>\n </svg>","color":"yellow","title":"Featured page"},"body":[{"type":"document","title":"Q2 launch plan","body":"Overview\n\nWe're shipping the new agent runtime in three phases. Phase 1 (May 6) covers the core SDK; phase 2 (May 20) adds the visual scrubber; phase 3 (June 3) brings the AutomationBench integration to production with belief-vs-truth scoring.","byline":"ops team","meta":"modified 2026-04-30"},{"type":"list","title":"More pages","items":[{"id":"d2","title":"On-call runbook","subtitle":"2026-04-29"},{"id":"d3","title":"Customer feedback · April","subtitle":"2026-04-28"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
Mesh
mesh/file · view: MeshFile
Canonical 3D-file asset — format-discriminated, multi-target rendered.
A2UI Composer ↗ A2UI Theater ↗ OpenClaw Canvas ↗ ChatGPT Apps SDK ↗ MCP Apps in Claude ↗
HTML · medium
Damaged Helmet GLB · 14,556 verts · 1.70m × 1.70m × 1.70m
GLB · 14,556 verts · 1.70m × 1.70m × 1.70m
KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces.
19 words · ~1 min
Markdown · medium ~61 tokens
Damaged Helmet · GLB · 14,556 verts · 1.70m × 1.70m × 1.70m

🧊 Damaged Helmet — GLB · 14,556 verts · 1.70m × 1.70m × 1.70m

KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces.
A2UI · medium · rendered by @a2ui/lit
live render via @a2ui/lit · catalog basic · v0.9
MCP Apps · medium · sandboxed iframe
how Claude/ChatGPT/VS Code render this · MIME text/html;profile=mcp-app
All sizes
icon ~3 tokens
Model3D
🟣 Model3D
{ "type": "icon", "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9\"/>\n </svg>", "color": "indigo", "label": "Model3D" }
{"version":"v0.9","createSurface":{"surfaceId":"Mesh-icon","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Mesh-icon","components":[{"id":"c1","component":"Text","text":"Model3D","variant":"h3"},{"id":"c2","component":"Column","children":["c1"]},{"id":"root","component":"Card","child":"c2"}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Mesh · icon</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-app-icon"> <div class="ws-app-tile" style="background:linear-gradient(160deg,#5856d6 0%,#3f3eaf 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9"/> </svg></div> </div> <div class="ws-app-name">Model3D</div> </div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"icon","glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9\"/>\n </svg>","color":"indigo","label":"Model3D"}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
small ~20 tokens
Damaged Helmet GLB
  • GLB · 14,556 verts · 1.70m × 1.70m × 1.70m
Damaged Helmet · GLB • GLB · 14,556 verts · 1.70m × 1.70m × 1.70m
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9\"/>\n </svg>", "color": "indigo", "title": "Damaged Helmet", "meta": "GLB" }, "body": [ { "type": "list", "items": [ { "title": "GLB · 14,556 verts · 1.70m × 1.70m × 1.70m" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Mesh-small","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Mesh-small","components":[{"id":"c1","component":"Text","text":"Damaged Helmet","variant":"h2"},{"id":"c2","component":"Text","text":"GLB","variant":"caption"},{"id":"c3","component":"Text","text":"GLB · 14,556 verts · 1.70m × 1.70m × 1.70m","variant":"h4"},{"id":"c4","component":"Column","children":["c3"]},{"id":"c5","component":"Card","child":"c4"},{"id":"c6","component":"List","children":["c5"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c2","c6"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Mesh · small</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#5856d6 0%,#3f3eaf 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9"/> </svg></div> </div> <span class="ws-stack-title">Damaged Helmet</span> <span class="ws-stack-meta">GLB</span> </div><div class="ws-stack-body"><div class="ws-list ws-list--vertical"><ul><li class="ws-li" data-widget-anchor="row[0]"> <div class="ws-li-row"> <span class="ws-li-title">GLB · 14,556 verts · 1.70m × 1.70m × 1.70m</span> </div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9\"/>\n </svg>","color":"indigo","title":"Damaged Helmet","meta":"GLB"},"body":[{"type":"list","items":[{"title":"GLB · 14,556 verts · 1.70m × 1.70m × 1.70m"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
medium ~61 tokens
Damaged Helmet GLB · 14,556 verts · 1.70m × 1.70m × 1.70m
GLB · 14,556 verts · 1.70m × 1.70m × 1.70m
KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces.
19 words · ~1 min
Damaged Helmet · GLB · 14,556 verts · 1.70m × 1.70m × 1.70m 🧊 Damaged Helmet — GLB · 14,556 verts · 1.70m × 1.70m × 1.70m KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces.
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9\"/>\n </svg>", "color": "indigo", "title": "Damaged Helmet", "meta": "GLB · 14,556 verts · 1.70m × 1.70m × 1.70m" }, "body": [ { "type": "model_3d", "uri": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/DamagedHelmet/glTF-Binary/DamagedHelmet.glb", "format": "glb", "name": "Damaged Helmet", "bounds": { "width": 1.7, "height": 1.7, "depth": 1.7, "unit": "m" }, "vertexCount": 14556, "cameraOrbit": "30deg 75deg 105%", "autoRotate": true }, { "type": "document", "body": "KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces." } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Mesh-medium","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Mesh-medium","components":[{"id":"c1","component":"Text","text":"Damaged Helmet","variant":"h2"},{"id":"c2","component":"Text","text":"GLB · 14,556 verts · 1.70m × 1.70m × 1.70m","variant":"caption"},{"id":"c3","component":"Text","text":"Damaged Helmet","variant":"h4"},{"id":"c4","component":"Text","text":"GLB · 14,556 verts · 1.70m × 1.70m × 1.70m","variant":"caption"},{"id":"c5","component":"Column","children":["c3","c4"]},{"id":"c6","component":"Card","child":"c5"},{"id":"c7","component":"Text","text":"KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces.","variant":"body"},{"id":"c8","component":"Column","children":["c7"]},{"id":"c9","component":"Card","child":"c8"},{"id":"root","component":"Column","children":["c1","c2","c6","c9"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Mesh · medium</title> <script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js"></script> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#5856d6 0%,#3f3eaf 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9"/> </svg></div> </div> <span class="ws-stack-title">Damaged Helmet</span> <span class="ws-stack-meta">GLB · 14,556 verts · 1.70m × 1.70m × 1.70m</span> </div><div class="ws-stack-body"><div class="ws-model3d"> <model-viewer src="https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/DamagedHelmet/glTF-Binary/DamagedHelmet.glb" alt="Damaged Helmet" loading="lazy" reveal="auto" camera-controls touch-action="pan-y" auto-rotate camera-orbit="30deg 75deg 105%" style="width:100%;height:100%;min-height:240px;background:#f1f5f9;border-radius:8px"></model-viewer> <div class="ws-model3d-meta">GLB · 14,556 verts · 1.70m × 1.70m × 1.70m</div> </div><div class="ws-doc"> <div class="ws-doc-body">KhronosGroup&#39;s reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces.</div> <div class="ws-doc-stats">19 words · ~1 min</div> </div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9\"/>\n </svg>","color":"indigo","title":"Damaged Helmet","meta":"GLB · 14,556 verts · 1.70m × 1.70m × 1.70m"},"body":[{"type":"model_3d","uri":"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/DamagedHelmet/glTF-Binary/DamagedHelmet.glb","format":"glb","name":"Damaged Helmet","bounds":{"width":1.7,"height":1.7,"depth":1.7,"unit":"m"},"vertexCount":14556,"cameraOrbit":"30deg 75deg 105%","autoRotate":true},{"type":"document","body":"KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces."}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
large ~61 tokens
Damaged Helmet GLB · 14,556 verts · 1.70m × 1.70m × 1.70m
GLB · 14,556 verts · 1.70m × 1.70m × 1.70m
KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces.
19 words · ~1 min
Damaged Helmet · GLB · 14,556 verts · 1.70m × 1.70m × 1.70m 🧊 Damaged Helmet — GLB · 14,556 verts · 1.70m × 1.70m × 1.70m KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces.
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9\"/>\n </svg>", "color": "indigo", "title": "Damaged Helmet", "meta": "GLB · 14,556 verts · 1.70m × 1.70m × 1.70m" }, "body": [ { "type": "model_3d", "uri": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/DamagedHelmet/glTF-Binary/DamagedHelmet.glb", "format": "glb", "name": "Damaged Helmet", "bounds": { "width": 1.7, "height": 1.7, "depth": 1.7, "unit": "m" }, "vertexCount": 14556, "cameraOrbit": "30deg 75deg 105%", "autoRotate": true }, { "type": "document", "body": "KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces." } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Mesh-large","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Mesh-large","components":[{"id":"c1","component":"Text","text":"Damaged Helmet","variant":"h2"},{"id":"c2","component":"Text","text":"GLB · 14,556 verts · 1.70m × 1.70m × 1.70m","variant":"caption"},{"id":"c3","component":"Text","text":"Damaged Helmet","variant":"h4"},{"id":"c4","component":"Text","text":"GLB · 14,556 verts · 1.70m × 1.70m × 1.70m","variant":"caption"},{"id":"c5","component":"Column","children":["c3","c4"]},{"id":"c6","component":"Card","child":"c5"},{"id":"c7","component":"Text","text":"KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces.","variant":"body"},{"id":"c8","component":"Column","children":["c7"]},{"id":"c9","component":"Card","child":"c8"},{"id":"root","component":"Column","children":["c1","c2","c6","c9"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Mesh · large</title> <script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js"></script> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#5856d6 0%,#3f3eaf 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9"/> </svg></div> </div> <span class="ws-stack-title">Damaged Helmet</span> <span class="ws-stack-meta">GLB · 14,556 verts · 1.70m × 1.70m × 1.70m</span> </div><div class="ws-stack-body"><div class="ws-model3d"> <model-viewer src="https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/DamagedHelmet/glTF-Binary/DamagedHelmet.glb" alt="Damaged Helmet" loading="lazy" reveal="auto" camera-controls touch-action="pan-y" auto-rotate camera-orbit="30deg 75deg 105%" style="width:100%;height:100%;min-height:240px;background:#f1f5f9;border-radius:8px"></model-viewer> <div class="ws-model3d-meta">GLB · 14,556 verts · 1.70m × 1.70m × 1.70m</div> </div><div class="ws-doc"> <div class="ws-doc-body">KhronosGroup&#39;s reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces.</div> <div class="ws-doc-stats">19 words · ~1 min</div> </div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9\"/>\n </svg>","color":"indigo","title":"Damaged Helmet","meta":"GLB · 14,556 verts · 1.70m × 1.70m × 1.70m"},"body":[{"type":"model_3d","uri":"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/DamagedHelmet/glTF-Binary/DamagedHelmet.glb","format":"glb","name":"Damaged Helmet","bounds":{"width":1.7,"height":1.7,"depth":1.7,"unit":"m"},"vertexCount":14556,"cameraOrbit":"30deg 75deg 105%","autoRotate":true},{"type":"document","body":"KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces."}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
xlarge ~61 tokens
Damaged Helmet GLB · 14,556 verts · 1.70m × 1.70m × 1.70m
GLB · 14,556 verts · 1.70m × 1.70m × 1.70m
KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces.
19 words · ~1 min
Damaged Helmet · GLB · 14,556 verts · 1.70m × 1.70m × 1.70m 🧊 Damaged Helmet — GLB · 14,556 verts · 1.70m × 1.70m × 1.70m KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces.
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9\"/>\n </svg>", "color": "indigo", "title": "Damaged Helmet", "meta": "GLB · 14,556 verts · 1.70m × 1.70m × 1.70m" }, "body": [ { "type": "model_3d", "uri": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/DamagedHelmet/glTF-Binary/DamagedHelmet.glb", "format": "glb", "name": "Damaged Helmet", "bounds": { "width": 1.7, "height": 1.7, "depth": 1.7, "unit": "m" }, "vertexCount": 14556, "cameraOrbit": "30deg 75deg 105%", "autoRotate": true }, { "type": "document", "body": "KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces." } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Mesh-xlarge","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Mesh-xlarge","components":[{"id":"c1","component":"Text","text":"Damaged Helmet","variant":"h2"},{"id":"c2","component":"Text","text":"GLB · 14,556 verts · 1.70m × 1.70m × 1.70m","variant":"caption"},{"id":"c3","component":"Text","text":"Damaged Helmet","variant":"h4"},{"id":"c4","component":"Text","text":"GLB · 14,556 verts · 1.70m × 1.70m × 1.70m","variant":"caption"},{"id":"c5","component":"Column","children":["c3","c4"]},{"id":"c6","component":"Card","child":"c5"},{"id":"c7","component":"Text","text":"KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces.","variant":"body"},{"id":"c8","component":"Column","children":["c7"]},{"id":"c9","component":"Card","child":"c8"},{"id":"root","component":"Column","children":["c1","c2","c6","c9"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Mesh · xlarge</title> <script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js"></script> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#5856d6 0%,#3f3eaf 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9"/> </svg></div> </div> <span class="ws-stack-title">Damaged Helmet</span> <span class="ws-stack-meta">GLB · 14,556 verts · 1.70m × 1.70m × 1.70m</span> </div><div class="ws-stack-body"><div class="ws-model3d"> <model-viewer src="https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/DamagedHelmet/glTF-Binary/DamagedHelmet.glb" alt="Damaged Helmet" loading="lazy" reveal="auto" camera-controls touch-action="pan-y" auto-rotate camera-orbit="30deg 75deg 105%" style="width:100%;height:100%;min-height:240px;background:#f1f5f9;border-radius:8px"></model-viewer> <div class="ws-model3d-meta">GLB · 14,556 verts · 1.70m × 1.70m × 1.70m</div> </div><div class="ws-doc"> <div class="ws-doc-body">KhronosGroup&#39;s reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces.</div> <div class="ws-doc-stats">19 words · ~1 min</div> </div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9\"/>\n </svg>","color":"indigo","title":"Damaged Helmet","meta":"GLB · 14,556 verts · 1.70m × 1.70m × 1.70m"},"body":[{"type":"model_3d","uri":"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/DamagedHelmet/glTF-Binary/DamagedHelmet.glb","format":"glb","name":"Damaged Helmet","bounds":{"width":1.7,"height":1.7,"depth":1.7,"unit":"m"},"vertexCount":14556,"cameraOrbit":"30deg 75deg 105%","autoRotate":true},{"type":"document","body":"KhronosGroup's reference glTF model — battle-tested across every glTF renderer, CC-BY-4.0. Demonstrates PBR materials, normal maps, and emissive surfaces."}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
Feed
feed/social · view: Feed
Canonical Feed — time-ordered stream of source-attributed items. Items sharing cluster_id are the same event from different sources (techmeme's lead-headline-plus-secondaries pattern, flat).
A2UI Composer ↗ A2UI Theater ↗ OpenClaw Canvas ↗ ChatGPT Apps SDK ↗ MCP Apps in Claude ↗
HTML · medium
Latest 3 stories
  • Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital
    Example Daily · +4 more · 5 reactions
  • ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level
    Example Research Lab · +1 more · 2 reactions · 4 math-olympiad-2024 · SOTA
  • Show HN: A tiny Lisp implementation in 500 lines of Rust
    Hacker News
Markdown · medium ~92 tokens
Latest · 3 stories

• Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital — Example Daily · +4 more · 5 reactions
• ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level — Example Research Lab · +1 more · 2 reactions · 4 math-olympiad-2024 · SOTA
• Show HN: A tiny Lisp implementation in 500 lines of Rust — Hacker News
A2UI · medium · rendered by @a2ui/lit
live render via @a2ui/lit · catalog basic · v0.9
MCP Apps · medium · sandboxed iframe
how Claude/ChatGPT/VS Code render this · MIME text/html;profile=mcp-app
All sizes
icon ~5 tokens
3
Feed
🟣 Feed · 3
{ "type": "icon", "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z\"/>\n </svg>", "color": "indigo", "label": "Feed", "badge": 3 }
{"version":"v0.9","createSurface":{"surfaceId":"Feed-icon","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Feed-icon","components":[{"id":"c1","component":"Text","text":"Feed","variant":"h3"},{"id":"c2","component":"Text","text":"3","variant":"caption"},{"id":"c3","component":"Column","children":["c1","c2"]},{"id":"root","component":"Card","child":"c3"}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Feed · icon</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-app-icon"> <div class="ws-app-tile" style="background:linear-gradient(160deg,#5856d6 0%,#3f3eaf 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z"/> </svg></div> <div class="ws-app-badge">3</div> </div> <div class="ws-app-name">Feed</div> </div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"icon","glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z\"/>\n </svg>","color":"indigo","label":"Feed","badge":3}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
small ~35 tokens
Latest 1 SOTA
  • Acme AI raises $500M Series C at $5B valuation, led by Atlas…
    Example Daily · +4 more · 5 reactions
Latest · 1 SOTA • Acme AI raises $500M Series C at $5B valuation, led by Atlas… — Example Daily · +4 more · 5 reactions
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z\"/>\n </svg>", "color": "indigo", "title": "Latest", "meta": "1 SOTA" }, "body": [ { "type": "list", "items": [ { "id": "i1", "title": "Acme AI raises $500M Series C at $5B valuation, led by Atlas…", "subtitle": "Example Daily · +4 more · 5 reactions" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Feed-small","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Feed-small","components":[{"id":"c1","component":"Text","text":"Latest","variant":"h2"},{"id":"c2","component":"Text","text":"1 SOTA","variant":"caption"},{"id":"c3","component":"Text","text":"Acme AI raises $500M Series C at $5B valuation, led by Atlas…","variant":"h4"},{"id":"c4","component":"Text","text":"Example Daily · +4 more · 5 reactions","variant":"body"},{"id":"c5","component":"Column","children":["c3","c4"]},{"id":"c6","component":"Card","child":"c5"},{"id":"c7","component":"List","children":["c6"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c2","c7"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Feed · small</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#5856d6 0%,#3f3eaf 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z"/> </svg></div> </div> <span class="ws-stack-title">Latest</span> <span class="ws-stack-meta">1 SOTA</span> </div><div class="ws-stack-body"><div class="ws-list ws-list--vertical"><ul><li class="ws-li" data-widget-anchor="item[i1]"> <div class="ws-li-row"> <span class="ws-li-title">Acme AI raises $500M Series C at $5B valuation, led by Atlas…</span> </div> <div class="ws-li-sub">Example Daily · +4 more · 5 reactions</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z\"/>\n </svg>","color":"indigo","title":"Latest","meta":"1 SOTA"},"body":[{"type":"list","items":[{"id":"i1","title":"Acme AI raises $500M Series C at $5B valuation, led by Atlas…","subtitle":"Example Daily · +4 more · 5 reactions"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
medium ~92 tokens
Latest 3 stories
  • Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital
    Example Daily · +4 more · 5 reactions
  • ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level
    Example Research Lab · +1 more · 2 reactions · 4 math-olympiad-2024 · SOTA
  • Show HN: A tiny Lisp implementation in 500 lines of Rust
    Hacker News
Latest · 3 stories • Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital — Example Daily · +4 more · 5 reactions • ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level — Example Research Lab · +1 more · 2 reactions · 4 math-olympiad-2024 · SOTA • Show HN: A tiny Lisp implementation in 500 lines of Rust — Hacker News
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z\"/>\n </svg>", "color": "indigo", "title": "Latest", "meta": "3 stories" }, "body": [ { "type": "list", "items": [ { "id": "i1", "title": "Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital", "subtitle": "Example Daily · +4 more · 5 reactions" }, { "id": "i11", "title": "ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level", "subtitle": "Example Research Lab · +1 more · 2 reactions · 4 math-olympiad-2024 · SOTA" }, { "id": "i15", "title": "Show HN: A tiny Lisp implementation in 500 lines of Rust", "subtitle": "Hacker News" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Feed-medium","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Feed-medium","components":[{"id":"c1","component":"Text","text":"Latest","variant":"h2"},{"id":"c2","component":"Text","text":"3 stories","variant":"caption"},{"id":"c3","component":"Text","text":"Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital","variant":"h4"},{"id":"c4","component":"Text","text":"Example Daily · +4 more · 5 reactions","variant":"body"},{"id":"c5","component":"Column","children":["c3","c4"]},{"id":"c6","component":"Card","child":"c5"},{"id":"c7","component":"Text","text":"ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level","variant":"h4"},{"id":"c8","component":"Text","text":"Example Research Lab · +1 more · 2 reactions · 4 math-olympiad-2024 · SOTA","variant":"body"},{"id":"c9","component":"Column","children":["c7","c8"]},{"id":"c10","component":"Card","child":"c9"},{"id":"c11","component":"Text","text":"Show HN: A tiny Lisp implementation in 500 lines of Rust","variant":"h4"},{"id":"c12","component":"Text","text":"Hacker News","variant":"body"},{"id":"c13","component":"Column","children":["c11","c12"]},{"id":"c14","component":"Card","child":"c13"},{"id":"c15","component":"List","children":["c6","c10","c14"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c2","c15"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Feed · medium</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#5856d6 0%,#3f3eaf 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z"/> </svg></div> </div> <span class="ws-stack-title">Latest</span> <span class="ws-stack-meta">3 stories</span> </div><div class="ws-stack-body"><div class="ws-list ws-list--vertical"><ul><li class="ws-li" data-widget-anchor="item[i1]"> <div class="ws-li-row"> <span class="ws-li-title">Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital</span> </div> <div class="ws-li-sub">Example Daily · +4 more · 5 reactions</div> </li><li class="ws-li" data-widget-anchor="item[i11]"> <div class="ws-li-row"> <span class="ws-li-title">ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level</span> </div> <div class="ws-li-sub">Example Research Lab · +1 more · 2 reactions · 4 math-olympiad-2024 · SOTA</div> </li><li class="ws-li" data-widget-anchor="item[i15]"> <div class="ws-li-row"> <span class="ws-li-title">Show HN: A tiny Lisp implementation in 500 lines of Rust</span> </div> <div class="ws-li-sub">Hacker News</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z\"/>\n </svg>","color":"indigo","title":"Latest","meta":"3 stories"},"body":[{"type":"list","items":[{"id":"i1","title":"Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital","subtitle":"Example Daily · +4 more · 5 reactions"},{"id":"i11","title":"ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level","subtitle":"Example Research Lab · +1 more · 2 reactions · 4 math-olympiad-2024 · SOTA"},{"id":"i15","title":"Show HN: A tiny Lisp implementation in 500 lines of Rust","subtitle":"Hacker News"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
large ~525 tokens
Feed 2026-05-10T09:00:00Z
Example Daily
  • Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital
    The round, led by Atlas Capital with participation from existing investors, brings total funding to $750M. Acme AI plans to expand its inference infrastructure.
More
  • Acme AI closes Series C, eyeing $5B valuation
    Example Tech
  • Atlas Capital Leads $500M Round in Acme AI
    Example Wire
  • Acme AI raises $500M Series C (example.com)
    Hacker News
  • Inside Acme AI's Series C: The Cap Table That Took Shape
    Example Newsletter
X
  • @ai_capital
    Acme AI at $5B is the cleanest pure-play AI capital story of the year. Most of the rest is bundled into bigger platform bets.
  • @enterprise_signal
    Worth noting: Atlas Capital leading a Series C is a different signal than a growth fund. Enterprise channel suddenly matters in a way it didn't 12 months ago.
  • @ai_economist
    Valuation reflects narrative, not revenue. The interesting number is unit economics on API calls — which nobody's publishing.
Bluesky
  • @ml_curious.bsky.social
    Curious whether the round was raised primarily to fund inference compute or to fund a training run bigger than anyone has run.
LinkedIn
  • A. Investor
    Notable that this round was led by a tier-one fund rather than a corporate strategic. That structure is becoming the default for late-stage AI rounds — the deep pockets and distribution channels matter more than the financing mechanics at this scale.
Example Research Lab
  • ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level
    Combining symbolic search with neural reasoning, the system solves 4 of 6 olympiad problems in under three days — first system to reach silver-medal performance on this benchmark.
More
  • Hybrid symbolic-neural system reaches silver-medal performance on math olympiad benchmark
    R. Researcher et al. · Example Journal
X
  • @example_lab
    ProofBot + GeoSolver 2 just reached silver-medal level — solving 4 out of 6 problems. Combining symbolic search with neural reasoning is the unlock.
  • @lean_prover
    What's interesting in the ProofBot result isn't the score — it's that the model is searching over a formal language where verification is free. That's the part transferring to other domains is hard.
anon_hacker / Hacker News
  • Show HN: A tiny Lisp implementation in 500 lines of Rust
    Hacker News
Feed · 2026-05-10T09:00:00Z Example DailyAcme AI raises $500M Series C at $5B valuation, led by Atlas Capital — The round, led by Atlas Capital with participation from existing investors, brings total funding to $750M. Acme AI plans to expand its inference infrastructure. MoreAcme AI closes Series C, eyeing $5B valuation — Example Tech • Atlas Capital Leads $500M Round in Acme AI — Example Wire • Acme AI raises $500M Series C (example.com) — Hacker News • Inside Acme AI's Series C: The Cap Table That Took Shape — Example Newsletter X@ai_capital — Acme AI at $5B is the cleanest pure-play AI capital story of the year. Most of the rest is bundled into bigger platform bets. • @enterprise_signal — Worth noting: Atlas Capital leading a Series C is a different signal than a growth fund. Enterprise channel suddenly matters in a way it didn't 12 months ago. • @ai_economist — Valuation reflects narrative, not revenue. The interesting number is unit economics on API calls — which nobody's publishing. Bluesky@ml_curious.bsky.social — Curious whether the round was raised primarily to fund inference compute or to fund a training run bigger than anyone has run. LinkedInA. Investor — Notable that this round was led by a tier-one fund rather than a corporate strategic. That structure is becoming the default for late-stage AI rounds — the deep pockets and distribution channels matter more than the financing mechanics at this scale. Example Research LabProofBot and GeoSolver 2 solve advanced math problems at silver-medal level — Combining symbolic search with neural reasoning, the system solves 4 of 6 olympiad problems in under three days — first system to reach silver-medal performance on this benchmark. MoreHybrid symbolic-neural system reaches silver-medal performance on math olympiad benchmark — R. Researcher et al. · Example Journal X@example_lab — ProofBot + GeoSolver 2 just reached silver-medal level — solving 4 out of 6 problems. Combining symbolic search with neural reasoning is the unlock. • @lean_prover — What's interesting in the ProofBot result isn't the score — it's that the model is searching over a formal language where verification is free. That's the part transferring to other domains is hard. anon_hacker / Hacker NewsShow HN: A tiny Lisp implementation in 500 lines of Rust — Hacker News
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z\"/>\n </svg>", "color": "indigo", "title": "Feed", "meta": "2026-05-10T09:00:00Z" }, "body": [ { "type": "list", "title": "Example Daily", "items": [ { "id": "i1", "title": "Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital", "subtitle": "The round, led by Atlas Capital with participation from existing investors, brings total funding to $750M. Acme AI plans to expand its inference infrastructure." } ] }, { "type": "list", "title": "More", "items": [ { "id": "i2", "title": "Acme AI closes Series C, eyeing $5B valuation", "subtitle": "Example Tech" }, { "id": "i3", "title": "Atlas Capital Leads $500M Round in Acme AI", "subtitle": "Example Wire" }, { "id": "i4", "title": "Acme AI raises $500M Series C (example.com)", "subtitle": "Hacker News" }, { "id": "i5", "title": "Inside Acme AI's Series C: The Cap Table That Took Shape", "subtitle": "Example Newsletter" } ] }, { "type": "list", "title": "X", "items": [ { "id": "i6", "title": "@ai_capital", "subtitle": "Acme AI at $5B is the cleanest pure-play AI capital story of the year. Most of the rest is bundled into bigger platform bets." }, { "id": "i7", "title": "@enterprise_signal", "subtitle": "Worth noting: Atlas Capital leading a Series C is a different signal than a growth fund. Enterprise channel suddenly matters in a way it didn't 12 months ago." }, { "id": "i8", "title": "@ai_economist", "subtitle": "Valuation reflects narrative, not revenue. The interesting number is unit economics on API calls — which nobody's publishing." } ] }, { "type": "list", "title": "Bluesky", "items": [ { "id": "i9", "title": "@ml_curious.bsky.social", "subtitle": "Curious whether the round was raised primarily to fund inference compute or to fund a training run bigger than anyone has run." } ] }, { "type": "list", "title": "LinkedIn", "items": [ { "id": "i10", "title": "A. Investor", "subtitle": "Notable that this round was led by a tier-one fund rather than a corporate strategic. That structure is becoming the default for late-stage AI rounds — the deep pockets and distribution channels matter more than the financing mechanics at this scale." } ] }, { "type": "list", "title": "Example Research Lab", "items": [ { "id": "i11", "title": "ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level", "subtitle": "Combining symbolic search with neural reasoning, the system solves 4 of 6 olympiad problems in under three days — first system to reach silver-medal performance on this benchmark." } ] }, { "type": "list", "title": "More", "items": [ { "id": "i12", "title": "Hybrid symbolic-neural system reaches silver-medal performance on math olympiad benchmark", "subtitle": "R. Researcher et al. · Example Journal" } ] }, { "type": "list", "title": "X", "items": [ { "id": "i13", "title": "@example_lab", "subtitle": "ProofBot + GeoSolver 2 just reached silver-medal level — solving 4 out of 6 problems. Combining symbolic search with neural reasoning is the unlock." }, { "id": "i14", "title": "@lean_prover", "subtitle": "What's interesting in the ProofBot result isn't the score — it's that the model is searching over a formal language where verification is free. That's the part transferring to other domains is hard." } ] }, { "type": "list", "title": "anon_hacker / Hacker News", "items": [ { "id": "i15", "title": "Show HN: A tiny Lisp implementation in 500 lines of Rust", "subtitle": "Hacker News" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Feed-large","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Feed-large","components":[{"id":"c1","component":"Text","text":"Feed","variant":"h2"},{"id":"c2","component":"Text","text":"2026-05-10T09:00:00Z","variant":"caption"},{"id":"c3","component":"Text","text":"Example Daily","variant":"h2"},{"id":"c4","component":"Text","text":"Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital","variant":"h4"},{"id":"c5","component":"Text","text":"The round, led by Atlas Capital with participation from existing investors, brings total funding to $750M. Acme AI plans to expand its inference infrastructure.","variant":"body"},{"id":"c6","component":"Column","children":["c4","c5"]},{"id":"c7","component":"Card","child":"c6"},{"id":"c8","component":"List","children":["c3","c7"],"direction":"vertical"},{"id":"c9","component":"Text","text":"More","variant":"h2"},{"id":"c10","component":"Text","text":"Acme AI closes Series C, eyeing $5B valuation","variant":"h4"},{"id":"c11","component":"Text","text":"Example Tech","variant":"body"},{"id":"c12","component":"Column","children":["c10","c11"]},{"id":"c13","component":"Card","child":"c12"},{"id":"c14","component":"Text","text":"Atlas Capital Leads $500M Round in Acme AI","variant":"h4"},{"id":"c15","component":"Text","text":"Example Wire","variant":"body"},{"id":"c16","component":"Column","children":["c14","c15"]},{"id":"c17","component":"Card","child":"c16"},{"id":"c18","component":"Text","text":"Acme AI raises $500M Series C (example.com)","variant":"h4"},{"id":"c19","component":"Text","text":"Hacker News","variant":"body"},{"id":"c20","component":"Column","children":["c18","c19"]},{"id":"c21","component":"Card","child":"c20"},{"id":"c22","component":"Text","text":"Inside Acme AI's Series C: The Cap Table That Took Shape","variant":"h4"},{"id":"c23","component":"Text","text":"Example Newsletter","variant":"body"},{"id":"c24","component":"Column","children":["c22","c23"]},{"id":"c25","component":"Card","child":"c24"},{"id":"c26","component":"List","children":["c9","c13","c17","c21","c25"],"direction":"vertical"},{"id":"c27","component":"Text","text":"X","variant":"h2"},{"id":"c28","component":"Text","text":"@ai_capital","variant":"h4"},{"id":"c29","component":"Text","text":"Acme AI at $5B is the cleanest pure-play AI capital story of the year. Most of the rest is bundled into bigger platform bets.","variant":"body"},{"id":"c30","component":"Column","children":["c28","c29"]},{"id":"c31","component":"Card","child":"c30"},{"id":"c32","component":"Text","text":"@enterprise_signal","variant":"h4"},{"id":"c33","component":"Text","text":"Worth noting: Atlas Capital leading a Series C is a different signal than a growth fund. Enterprise channel suddenly matters in a way it didn't 12 months ago.","variant":"body"},{"id":"c34","component":"Column","children":["c32","c33"]},{"id":"c35","component":"Card","child":"c34"},{"id":"c36","component":"Text","text":"@ai_economist","variant":"h4"},{"id":"c37","component":"Text","text":"Valuation reflects narrative, not revenue. The interesting number is unit economics on API calls — which nobody's publishing.","variant":"body"},{"id":"c38","component":"Column","children":["c36","c37"]},{"id":"c39","component":"Card","child":"c38"},{"id":"c40","component":"List","children":["c27","c31","c35","c39"],"direction":"vertical"},{"id":"c41","component":"Text","text":"Bluesky","variant":"h2"},{"id":"c42","component":"Text","text":"@ml_curious.bsky.social","variant":"h4"},{"id":"c43","component":"Text","text":"Curious whether the round was raised primarily to fund inference compute or to fund a training run bigger than anyone has run.","variant":"body"},{"id":"c44","component":"Column","children":["c42","c43"]},{"id":"c45","component":"Card","child":"c44"},{"id":"c46","component":"List","children":["c41","c45"],"direction":"vertical"},{"id":"c47","component":"Text","text":"LinkedIn","variant":"h2"},{"id":"c48","component":"Text","text":"A. Investor","variant":"h4"},{"id":"c49","component":"Text","text":"Notable that this round was led by a tier-one fund rather than a corporate strategic. That structure is becoming the default for late-stage AI rounds — the deep pockets and distribution channels matter more than the financing mechanics at this scale.","variant":"body"},{"id":"c50","component":"Column","children":["c48","c49"]},{"id":"c51","component":"Card","child":"c50"},{"id":"c52","component":"List","children":["c47","c51"],"direction":"vertical"},{"id":"c53","component":"Text","text":"Example Research Lab","variant":"h2"},{"id":"c54","component":"Text","text":"ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level","variant":"h4"},{"id":"c55","component":"Text","text":"Combining symbolic search with neural reasoning, the system solves 4 of 6 olympiad problems in under three days — first system to reach silver-medal performance on this benchmark.","variant":"body"},{"id":"c56","component":"Column","children":["c54","c55"]},{"id":"c57","component":"Card","child":"c56"},{"id":"c58","component":"List","children":["c53","c57"],"direction":"vertical"},{"id":"c59","component":"Text","text":"More","variant":"h2"},{"id":"c60","component":"Text","text":"Hybrid symbolic-neural system reaches silver-medal performance on math olympiad benchmark","variant":"h4"},{"id":"c61","component":"Text","text":"R. Researcher et al. · Example Journal","variant":"body"},{"id":"c62","component":"Column","children":["c60","c61"]},{"id":"c63","component":"Card","child":"c62"},{"id":"c64","component":"List","children":["c59","c63"],"direction":"vertical"},{"id":"c65","component":"Text","text":"X","variant":"h2"},{"id":"c66","component":"Text","text":"@example_lab","variant":"h4"},{"id":"c67","component":"Text","text":"ProofBot + GeoSolver 2 just reached silver-medal level — solving 4 out of 6 problems. Combining symbolic search with neural reasoning is the unlock.","variant":"body"},{"id":"c68","component":"Column","children":["c66","c67"]},{"id":"c69","component":"Card","child":"c68"},{"id":"c70","component":"Text","text":"@lean_prover","variant":"h4"},{"id":"c71","component":"Text","text":"What's interesting in the ProofBot result isn't the score — it's that the model is searching over a formal language where verification is free. That's the part transferring to other domains is hard.","variant":"body"},{"id":"c72","component":"Column","children":["c70","c71"]},{"id":"c73","component":"Card","child":"c72"},{"id":"c74","component":"List","children":["c65","c69","c73"],"direction":"vertical"},{"id":"c75","component":"Text","text":"anon_hacker / Hacker News","variant":"h2"},{"id":"c76","component":"Text","text":"Show HN: A tiny Lisp implementation in 500 lines of Rust","variant":"h4"},{"id":"c77","component":"Text","text":"Hacker News","variant":"body"},{"id":"c78","component":"Column","children":["c76","c77"]},{"id":"c79","component":"Card","child":"c78"},{"id":"c80","component":"List","children":["c75","c79"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c2","c8","c26","c40","c46","c52","c58","c64","c74","c80"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Feed · large</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#5856d6 0%,#3f3eaf 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z"/> </svg></div> </div> <span class="ws-stack-title">Feed</span> <span class="ws-stack-meta">2026-05-10T09:00:00Z</span> </div><div class="ws-stack-body"><div class="ws-list ws-list--vertical"><div class="ws-title">Example Daily</div><ul><li class="ws-li" data-widget-anchor="item[i1]"> <div class="ws-li-row"> <span class="ws-li-title">Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital</span> </div> <div class="ws-li-sub">The round, led by Atlas Capital with participation from existing investors, brings total funding to $750M. Acme AI plans to expand its inference infrastructure.</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">More</div><ul><li class="ws-li" data-widget-anchor="item[i2]"> <div class="ws-li-row"> <span class="ws-li-title">Acme AI closes Series C, eyeing $5B valuation</span> </div> <div class="ws-li-sub">Example Tech</div> </li><li class="ws-li" data-widget-anchor="item[i3]"> <div class="ws-li-row"> <span class="ws-li-title">Atlas Capital Leads $500M Round in Acme AI</span> </div> <div class="ws-li-sub">Example Wire</div> </li><li class="ws-li" data-widget-anchor="item[i4]"> <div class="ws-li-row"> <span class="ws-li-title">Acme AI raises $500M Series C (example.com)</span> </div> <div class="ws-li-sub">Hacker News</div> </li><li class="ws-li" data-widget-anchor="item[i5]"> <div class="ws-li-row"> <span class="ws-li-title">Inside Acme AI&#39;s Series C: The Cap Table That Took Shape</span> </div> <div class="ws-li-sub">Example Newsletter</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">X</div><ul><li class="ws-li" data-widget-anchor="item[i6]"> <div class="ws-li-row"> <span class="ws-li-title">@ai_capital</span> </div> <div class="ws-li-sub">Acme AI at $5B is the cleanest pure-play AI capital story of the year. Most of the rest is bundled into bigger platform bets.</div> </li><li class="ws-li" data-widget-anchor="item[i7]"> <div class="ws-li-row"> <span class="ws-li-title">@enterprise_signal</span> </div> <div class="ws-li-sub">Worth noting: Atlas Capital leading a Series C is a different signal than a growth fund. Enterprise channel suddenly matters in a way it didn&#39;t 12 months ago.</div> </li><li class="ws-li" data-widget-anchor="item[i8]"> <div class="ws-li-row"> <span class="ws-li-title">@ai_economist</span> </div> <div class="ws-li-sub">Valuation reflects narrative, not revenue. The interesting number is unit economics on API calls — which nobody&#39;s publishing.</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">Bluesky</div><ul><li class="ws-li" data-widget-anchor="item[i9]"> <div class="ws-li-row"> <span class="ws-li-title">@ml_curious.bsky.social</span> </div> <div class="ws-li-sub">Curious whether the round was raised primarily to fund inference compute or to fund a training run bigger than anyone has run.</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">LinkedIn</div><ul><li class="ws-li" data-widget-anchor="item[i10]"> <div class="ws-li-row"> <span class="ws-li-title">A. Investor</span> </div> <div class="ws-li-sub">Notable that this round was led by a tier-one fund rather than a corporate strategic. That structure is becoming the default for late-stage AI rounds — the deep pockets and distribution channels matter more than the financing mechanics at this scale.</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">Example Research Lab</div><ul><li class="ws-li" data-widget-anchor="item[i11]"> <div class="ws-li-row"> <span class="ws-li-title">ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level</span> </div> <div class="ws-li-sub">Combining symbolic search with neural reasoning, the system solves 4 of 6 olympiad problems in under three days — first system to reach silver-medal performance on this benchmark.</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">More</div><ul><li class="ws-li" data-widget-anchor="item[i12]"> <div class="ws-li-row"> <span class="ws-li-title">Hybrid symbolic-neural system reaches silver-medal performance on math olympiad benchmark</span> </div> <div class="ws-li-sub">R. Researcher et al. · Example Journal</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">X</div><ul><li class="ws-li" data-widget-anchor="item[i13]"> <div class="ws-li-row"> <span class="ws-li-title">@example_lab</span> </div> <div class="ws-li-sub">ProofBot + GeoSolver 2 just reached silver-medal level — solving 4 out of 6 problems. Combining symbolic search with neural reasoning is the unlock.</div> </li><li class="ws-li" data-widget-anchor="item[i14]"> <div class="ws-li-row"> <span class="ws-li-title">@lean_prover</span> </div> <div class="ws-li-sub">What&#39;s interesting in the ProofBot result isn&#39;t the score — it&#39;s that the model is searching over a formal language where verification is free. That&#39;s the part transferring to other domains is hard.</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">anon_hacker / Hacker News</div><ul><li class="ws-li" data-widget-anchor="item[i15]"> <div class="ws-li-row"> <span class="ws-li-title">Show HN: A tiny Lisp implementation in 500 lines of Rust</span> </div> <div class="ws-li-sub">Hacker News</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z\"/>\n </svg>","color":"indigo","title":"Feed","meta":"2026-05-10T09:00:00Z"},"body":[{"type":"list","title":"Example Daily","items":[{"id":"i1","title":"Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital","subtitle":"The round, led by Atlas Capital with participation from existing investors, brings total funding to $750M. Acme AI plans to expand its inference infrastructure."}]},{"type":"list","title":"More","items":[{"id":"i2","title":"Acme AI closes Series C, eyeing $5B valuation","subtitle":"Example Tech"},{"id":"i3","title":"Atlas Capital Leads $500M Round in Acme AI","subtitle":"Example Wire"},{"id":"i4","title":"Acme AI raises $500M Series C (example.com)","subtitle":"Hacker News"},{"id":"i5","title":"Inside Acme AI's Series C: The Cap Table That Took Shape","subtitle":"Example Newsletter"}]},{"type":"list","title":"X","items":[{"id":"i6","title":"@ai_capital","subtitle":"Acme AI at $5B is the cleanest pure-play AI capital story of the year. Most of the rest is bundled into bigger platform bets."},{"id":"i7","title":"@enterprise_signal","subtitle":"Worth noting: Atlas Capital leading a Series C is a different signal than a growth fund. Enterprise channel suddenly matters in a way it didn't 12 months ago."},{"id":"i8","title":"@ai_economist","subtitle":"Valuation reflects narrative, not revenue. The interesting number is unit economics on API calls — which nobody's publishing."}]},{"type":"list","title":"Bluesky","items":[{"id":"i9","title":"@ml_curious.bsky.social","subtitle":"Curious whether the round was raised primarily to fund inference compute or to fund a training run bigger than anyone has run."}]},{"type":"list","title":"LinkedIn","items":[{"id":"i10","title":"A. Investor","subtitle":"Notable that this round was led by a tier-one fund rather than a corporate strategic. That structure is becoming the default for late-stage AI rounds — the deep pockets and distribution channels matter more than the financing mechanics at this scale."}]},{"type":"list","title":"Example Research Lab","items":[{"id":"i11","title":"ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level","subtitle":"Combining symbolic search with neural reasoning, the system solves 4 of 6 olympiad problems in under three days — first system to reach silver-medal performance on this benchmark."}]},{"type":"list","title":"More","items":[{"id":"i12","title":"Hybrid symbolic-neural system reaches silver-medal performance on math olympiad benchmark","subtitle":"R. Researcher et al. · Example Journal"}]},{"type":"list","title":"X","items":[{"id":"i13","title":"@example_lab","subtitle":"ProofBot + GeoSolver 2 just reached silver-medal level — solving 4 out of 6 problems. Combining symbolic search with neural reasoning is the unlock."},{"id":"i14","title":"@lean_prover","subtitle":"What's interesting in the ProofBot result isn't the score — it's that the model is searching over a formal language where verification is free. That's the part transferring to other domains is hard."}]},{"type":"list","title":"anon_hacker / Hacker News","items":[{"id":"i15","title":"Show HN: A tiny Lisp implementation in 500 lines of Rust","subtitle":"Hacker News"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>
xlarge ~525 tokens
Feed 2026-05-10T09:00:00Z
Example Daily
  • Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital
    The round, led by Atlas Capital with participation from existing investors, brings total funding to $750M. Acme AI plans to expand its inference infrastructure.
More
  • Acme AI closes Series C, eyeing $5B valuation
    Example Tech
  • Atlas Capital Leads $500M Round in Acme AI
    Example Wire
  • Acme AI raises $500M Series C (example.com)
    Hacker News
  • Inside Acme AI's Series C: The Cap Table That Took Shape
    Example Newsletter
X
  • @ai_capital
    Acme AI at $5B is the cleanest pure-play AI capital story of the year. Most of the rest is bundled into bigger platform bets.
  • @enterprise_signal
    Worth noting: Atlas Capital leading a Series C is a different signal than a growth fund. Enterprise channel suddenly matters in a way it didn't 12 months ago.
  • @ai_economist
    Valuation reflects narrative, not revenue. The interesting number is unit economics on API calls — which nobody's publishing.
Bluesky
  • @ml_curious.bsky.social
    Curious whether the round was raised primarily to fund inference compute or to fund a training run bigger than anyone has run.
LinkedIn
  • A. Investor
    Notable that this round was led by a tier-one fund rather than a corporate strategic. That structure is becoming the default for late-stage AI rounds — the deep pockets and distribution channels matter more than the financing mechanics at this scale.
Example Research Lab
  • ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level
    Combining symbolic search with neural reasoning, the system solves 4 of 6 olympiad problems in under three days — first system to reach silver-medal performance on this benchmark.
More
  • Hybrid symbolic-neural system reaches silver-medal performance on math olympiad benchmark
    R. Researcher et al. · Example Journal
X
  • @example_lab
    ProofBot + GeoSolver 2 just reached silver-medal level — solving 4 out of 6 problems. Combining symbolic search with neural reasoning is the unlock.
  • @lean_prover
    What's interesting in the ProofBot result isn't the score — it's that the model is searching over a formal language where verification is free. That's the part transferring to other domains is hard.
anon_hacker / Hacker News
  • Show HN: A tiny Lisp implementation in 500 lines of Rust
    Hacker News
Feed · 2026-05-10T09:00:00Z Example DailyAcme AI raises $500M Series C at $5B valuation, led by Atlas Capital — The round, led by Atlas Capital with participation from existing investors, brings total funding to $750M. Acme AI plans to expand its inference infrastructure. MoreAcme AI closes Series C, eyeing $5B valuation — Example Tech • Atlas Capital Leads $500M Round in Acme AI — Example Wire • Acme AI raises $500M Series C (example.com) — Hacker News • Inside Acme AI's Series C: The Cap Table That Took Shape — Example Newsletter X@ai_capital — Acme AI at $5B is the cleanest pure-play AI capital story of the year. Most of the rest is bundled into bigger platform bets. • @enterprise_signal — Worth noting: Atlas Capital leading a Series C is a different signal than a growth fund. Enterprise channel suddenly matters in a way it didn't 12 months ago. • @ai_economist — Valuation reflects narrative, not revenue. The interesting number is unit economics on API calls — which nobody's publishing. Bluesky@ml_curious.bsky.social — Curious whether the round was raised primarily to fund inference compute or to fund a training run bigger than anyone has run. LinkedInA. Investor — Notable that this round was led by a tier-one fund rather than a corporate strategic. That structure is becoming the default for late-stage AI rounds — the deep pockets and distribution channels matter more than the financing mechanics at this scale. Example Research LabProofBot and GeoSolver 2 solve advanced math problems at silver-medal level — Combining symbolic search with neural reasoning, the system solves 4 of 6 olympiad problems in under three days — first system to reach silver-medal performance on this benchmark. MoreHybrid symbolic-neural system reaches silver-medal performance on math olympiad benchmark — R. Researcher et al. · Example Journal X@example_lab — ProofBot + GeoSolver 2 just reached silver-medal level — solving 4 out of 6 problems. Combining symbolic search with neural reasoning is the unlock. • @lean_prover — What's interesting in the ProofBot result isn't the score — it's that the model is searching over a formal language where verification is free. That's the part transferring to other domains is hard. anon_hacker / Hacker NewsShow HN: A tiny Lisp implementation in 500 lines of Rust — Hacker News
{ "type": "stack", "header": { "glyph": "<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z\"/>\n </svg>", "color": "indigo", "title": "Feed", "meta": "2026-05-10T09:00:00Z" }, "body": [ { "type": "list", "title": "Example Daily", "items": [ { "id": "i1", "title": "Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital", "subtitle": "The round, led by Atlas Capital with participation from existing investors, brings total funding to $750M. Acme AI plans to expand its inference infrastructure." } ] }, { "type": "list", "title": "More", "items": [ { "id": "i2", "title": "Acme AI closes Series C, eyeing $5B valuation", "subtitle": "Example Tech" }, { "id": "i3", "title": "Atlas Capital Leads $500M Round in Acme AI", "subtitle": "Example Wire" }, { "id": "i4", "title": "Acme AI raises $500M Series C (example.com)", "subtitle": "Hacker News" }, { "id": "i5", "title": "Inside Acme AI's Series C: The Cap Table That Took Shape", "subtitle": "Example Newsletter" } ] }, { "type": "list", "title": "X", "items": [ { "id": "i6", "title": "@ai_capital", "subtitle": "Acme AI at $5B is the cleanest pure-play AI capital story of the year. Most of the rest is bundled into bigger platform bets." }, { "id": "i7", "title": "@enterprise_signal", "subtitle": "Worth noting: Atlas Capital leading a Series C is a different signal than a growth fund. Enterprise channel suddenly matters in a way it didn't 12 months ago." }, { "id": "i8", "title": "@ai_economist", "subtitle": "Valuation reflects narrative, not revenue. The interesting number is unit economics on API calls — which nobody's publishing." } ] }, { "type": "list", "title": "Bluesky", "items": [ { "id": "i9", "title": "@ml_curious.bsky.social", "subtitle": "Curious whether the round was raised primarily to fund inference compute or to fund a training run bigger than anyone has run." } ] }, { "type": "list", "title": "LinkedIn", "items": [ { "id": "i10", "title": "A. Investor", "subtitle": "Notable that this round was led by a tier-one fund rather than a corporate strategic. That structure is becoming the default for late-stage AI rounds — the deep pockets and distribution channels matter more than the financing mechanics at this scale." } ] }, { "type": "list", "title": "Example Research Lab", "items": [ { "id": "i11", "title": "ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level", "subtitle": "Combining symbolic search with neural reasoning, the system solves 4 of 6 olympiad problems in under three days — first system to reach silver-medal performance on this benchmark." } ] }, { "type": "list", "title": "More", "items": [ { "id": "i12", "title": "Hybrid symbolic-neural system reaches silver-medal performance on math olympiad benchmark", "subtitle": "R. Researcher et al. · Example Journal" } ] }, { "type": "list", "title": "X", "items": [ { "id": "i13", "title": "@example_lab", "subtitle": "ProofBot + GeoSolver 2 just reached silver-medal level — solving 4 out of 6 problems. Combining symbolic search with neural reasoning is the unlock." }, { "id": "i14", "title": "@lean_prover", "subtitle": "What's interesting in the ProofBot result isn't the score — it's that the model is searching over a formal language where verification is free. That's the part transferring to other domains is hard." } ] }, { "type": "list", "title": "anon_hacker / Hacker News", "items": [ { "id": "i15", "title": "Show HN: A tiny Lisp implementation in 500 lines of Rust", "subtitle": "Hacker News" } ] } ] }
{"version":"v0.9","createSurface":{"surfaceId":"Feed-xlarge","catalogId":"https://a2ui.org/specification/v0_9/basic_catalog.json"}} {"version":"v0.9","updateComponents":{"surfaceId":"Feed-xlarge","components":[{"id":"c1","component":"Text","text":"Feed","variant":"h2"},{"id":"c2","component":"Text","text":"2026-05-10T09:00:00Z","variant":"caption"},{"id":"c3","component":"Text","text":"Example Daily","variant":"h2"},{"id":"c4","component":"Text","text":"Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital","variant":"h4"},{"id":"c5","component":"Text","text":"The round, led by Atlas Capital with participation from existing investors, brings total funding to $750M. Acme AI plans to expand its inference infrastructure.","variant":"body"},{"id":"c6","component":"Column","children":["c4","c5"]},{"id":"c7","component":"Card","child":"c6"},{"id":"c8","component":"List","children":["c3","c7"],"direction":"vertical"},{"id":"c9","component":"Text","text":"More","variant":"h2"},{"id":"c10","component":"Text","text":"Acme AI closes Series C, eyeing $5B valuation","variant":"h4"},{"id":"c11","component":"Text","text":"Example Tech","variant":"body"},{"id":"c12","component":"Column","children":["c10","c11"]},{"id":"c13","component":"Card","child":"c12"},{"id":"c14","component":"Text","text":"Atlas Capital Leads $500M Round in Acme AI","variant":"h4"},{"id":"c15","component":"Text","text":"Example Wire","variant":"body"},{"id":"c16","component":"Column","children":["c14","c15"]},{"id":"c17","component":"Card","child":"c16"},{"id":"c18","component":"Text","text":"Acme AI raises $500M Series C (example.com)","variant":"h4"},{"id":"c19","component":"Text","text":"Hacker News","variant":"body"},{"id":"c20","component":"Column","children":["c18","c19"]},{"id":"c21","component":"Card","child":"c20"},{"id":"c22","component":"Text","text":"Inside Acme AI's Series C: The Cap Table That Took Shape","variant":"h4"},{"id":"c23","component":"Text","text":"Example Newsletter","variant":"body"},{"id":"c24","component":"Column","children":["c22","c23"]},{"id":"c25","component":"Card","child":"c24"},{"id":"c26","component":"List","children":["c9","c13","c17","c21","c25"],"direction":"vertical"},{"id":"c27","component":"Text","text":"X","variant":"h2"},{"id":"c28","component":"Text","text":"@ai_capital","variant":"h4"},{"id":"c29","component":"Text","text":"Acme AI at $5B is the cleanest pure-play AI capital story of the year. Most of the rest is bundled into bigger platform bets.","variant":"body"},{"id":"c30","component":"Column","children":["c28","c29"]},{"id":"c31","component":"Card","child":"c30"},{"id":"c32","component":"Text","text":"@enterprise_signal","variant":"h4"},{"id":"c33","component":"Text","text":"Worth noting: Atlas Capital leading a Series C is a different signal than a growth fund. Enterprise channel suddenly matters in a way it didn't 12 months ago.","variant":"body"},{"id":"c34","component":"Column","children":["c32","c33"]},{"id":"c35","component":"Card","child":"c34"},{"id":"c36","component":"Text","text":"@ai_economist","variant":"h4"},{"id":"c37","component":"Text","text":"Valuation reflects narrative, not revenue. The interesting number is unit economics on API calls — which nobody's publishing.","variant":"body"},{"id":"c38","component":"Column","children":["c36","c37"]},{"id":"c39","component":"Card","child":"c38"},{"id":"c40","component":"List","children":["c27","c31","c35","c39"],"direction":"vertical"},{"id":"c41","component":"Text","text":"Bluesky","variant":"h2"},{"id":"c42","component":"Text","text":"@ml_curious.bsky.social","variant":"h4"},{"id":"c43","component":"Text","text":"Curious whether the round was raised primarily to fund inference compute or to fund a training run bigger than anyone has run.","variant":"body"},{"id":"c44","component":"Column","children":["c42","c43"]},{"id":"c45","component":"Card","child":"c44"},{"id":"c46","component":"List","children":["c41","c45"],"direction":"vertical"},{"id":"c47","component":"Text","text":"LinkedIn","variant":"h2"},{"id":"c48","component":"Text","text":"A. Investor","variant":"h4"},{"id":"c49","component":"Text","text":"Notable that this round was led by a tier-one fund rather than a corporate strategic. That structure is becoming the default for late-stage AI rounds — the deep pockets and distribution channels matter more than the financing mechanics at this scale.","variant":"body"},{"id":"c50","component":"Column","children":["c48","c49"]},{"id":"c51","component":"Card","child":"c50"},{"id":"c52","component":"List","children":["c47","c51"],"direction":"vertical"},{"id":"c53","component":"Text","text":"Example Research Lab","variant":"h2"},{"id":"c54","component":"Text","text":"ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level","variant":"h4"},{"id":"c55","component":"Text","text":"Combining symbolic search with neural reasoning, the system solves 4 of 6 olympiad problems in under three days — first system to reach silver-medal performance on this benchmark.","variant":"body"},{"id":"c56","component":"Column","children":["c54","c55"]},{"id":"c57","component":"Card","child":"c56"},{"id":"c58","component":"List","children":["c53","c57"],"direction":"vertical"},{"id":"c59","component":"Text","text":"More","variant":"h2"},{"id":"c60","component":"Text","text":"Hybrid symbolic-neural system reaches silver-medal performance on math olympiad benchmark","variant":"h4"},{"id":"c61","component":"Text","text":"R. Researcher et al. · Example Journal","variant":"body"},{"id":"c62","component":"Column","children":["c60","c61"]},{"id":"c63","component":"Card","child":"c62"},{"id":"c64","component":"List","children":["c59","c63"],"direction":"vertical"},{"id":"c65","component":"Text","text":"X","variant":"h2"},{"id":"c66","component":"Text","text":"@example_lab","variant":"h4"},{"id":"c67","component":"Text","text":"ProofBot + GeoSolver 2 just reached silver-medal level — solving 4 out of 6 problems. Combining symbolic search with neural reasoning is the unlock.","variant":"body"},{"id":"c68","component":"Column","children":["c66","c67"]},{"id":"c69","component":"Card","child":"c68"},{"id":"c70","component":"Text","text":"@lean_prover","variant":"h4"},{"id":"c71","component":"Text","text":"What's interesting in the ProofBot result isn't the score — it's that the model is searching over a formal language where verification is free. That's the part transferring to other domains is hard.","variant":"body"},{"id":"c72","component":"Column","children":["c70","c71"]},{"id":"c73","component":"Card","child":"c72"},{"id":"c74","component":"List","children":["c65","c69","c73"],"direction":"vertical"},{"id":"c75","component":"Text","text":"anon_hacker / Hacker News","variant":"h2"},{"id":"c76","component":"Text","text":"Show HN: A tiny Lisp implementation in 500 lines of Rust","variant":"h4"},{"id":"c77","component":"Text","text":"Hacker News","variant":"body"},{"id":"c78","component":"Column","children":["c76","c77"]},{"id":"c79","component":"Card","child":"c78"},{"id":"c80","component":"List","children":["c75","c79"],"direction":"vertical"},{"id":"root","component":"Column","children":["c1","c2","c8","c26","c40","c46","c52","c58","c64","c74","c80"]}]}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Feed · xlarge</title> <style> :root { color-scheme: light dark; /* CSS variables that widgets.css consumes. light-dark() resolves * to the first arg when color-scheme is light, second when dark, so * the same declaration adapts to whichever mode the host applies. * Hosts can override these by injecting their own :root rule. */ --fg: light-dark(#0f172a, #e2e8f0); --muted: light-dark(#64748b, #94a3b8); --border: light-dark(#e2e8f0, #334155); --bg: light-dark(#f8fafc, #020617); --accent: #6366f1; --green: light-dark(#10b981, #34d399); --red: light-dark(#ef4444, #f87171); } /* Explicit overrides — used when the embedding page postMessages a theme. */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { margin: 0; font: 14px/1.5 ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif; background: light-dark(#ffffff, #0f172a); color: var(--fg); } #scenecast-root { padding: 16px; } /** * scenecast/styles/widgets.css * * Stylesheet for the .ws-* CSS classes the WidgetData renderers emit. * Embed this once per page to render scenecast's HTML output correctly. * * Consumers: * - scenecast's own gallery reads this file at build time * - arch-bench, future benches, third-party consumers all import from here * * Variables it expects (set on :root or a parent): * --fg, --muted, --border, --bg, --accent, --green, --red * * Dark mode: this stylesheet uses the CSS light-dark() function for any * non-variable color literal, so a consumer that declares * :root { color-scheme: light dark; } * gets correct rendering in both light and dark mode automatically. * Consumers that don't declare color-scheme effectively get light mode * (which is light-dark()'s default). */ /* --------------------------------------------------------------------------- * App icon (size=icon) * --------------------------------------------------------------------------- */ .ws-app-icon { display: flex; flex-direction: column; align-items: center; gap: 6px; } .ws-app-tile { position: relative; width: 64px; height: 64px; flex-shrink: 0; border-radius: 18px; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,0,0,0.25), 0 1px 2px rgba(255,255,255,0.15) inset; transition: transform 0.12s ease; } .ws-app-tile--chip { width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15); } .ws-app-glyph { width: 50%; height: 50%; display: flex; align-items: center; justify-content: center; } .ws-app-glyph svg { width: 100%; height: 100%; } .ws-app-tile--chip .ws-app-glyph { width: 60%; height: 60%; } .ws-app-name { font-size: 11px; color: var(--fg); font-weight: 500; line-height: 1.2; flex-shrink: 0; } .ws-app-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px; background: #ff3b30; color: white; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 2px solid light-dark(#fff, #0f172a); box-shadow: 0 1px 3px rgba(0,0,0,0.25); } /* --------------------------------------------------------------------------- * Stack widget — header + body * --------------------------------------------------------------------------- */ .ws-stack { display: flex; flex-direction: column; gap: 10px; } .ws-stack-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; } .ws-stack-head .ws-app-tile--chip { flex-shrink: 0; } .ws-stack-title { font-weight: 600; } .ws-stack-meta { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: auto; } .ws-stack--grid-2 .ws-stack-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* --------------------------------------------------------------------------- * List widget * --------------------------------------------------------------------------- */ .ws-list ul { margin: 0; padding: 0; list-style: none; } .ws-list--grid-2 ul { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; } .ws-list--grid-2 .ws-li { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: light-dark(#fff, #0f172a); } .ws-li { padding: 10px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-li:last-child { border-bottom: none; } .ws-li-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .ws-li-title { font-size: 14px; font-weight: 500; } .ws-li-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; } .ws-li-detail { font-size: 12.5px; color: light-dark(#475569, #cbd5e1); margin-top: 4px; } .ws-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--accent); color: white; padding: 2px 8px; border-radius: 999px; } .ws-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; } .ws-empty { color: var(--muted); font-style: italic; padding: 12px; } .ws-more { color: var(--muted); font-style: italic; font-size: 12px; padding: 6px 0; } /* --------------------------------------------------------------------------- * Table widget * --------------------------------------------------------------------------- */ .ws-table table { width: 100%; border-collapse: collapse; font-size: 13px; } .ws-table th { text-align: left; padding: 8px 10px; background: light-dark(#f8fafc, #1e293b); border-bottom: 1px solid var(--border); font-weight: 500; color: var(--muted); font-size: 12px; } .ws-table td { padding: 8px 10px; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); vertical-align: top; } .ws-table tr:last-child td { border-bottom: none; } /* --------------------------------------------------------------------------- * Metric widget * --------------------------------------------------------------------------- */ .ws-metric { text-align: left; padding: 14px; background: light-dark(#f8fafc, #1e293b); border-radius: 8px; } .ws-metric-value { font-size: 26px; font-weight: 700; line-height: 1.1; } .ws-metric-value .ws-unit { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 4px; } .ws-metric-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; } .ws-delta { font-size: 12px; margin-top: 6px; } .ws-up { color: var(--green); } .ws-down { color: var(--red); } .ws-flat { color: var(--muted); } .ws-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; } .ws-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; } /* --------------------------------------------------------------------------- * KeyValue widget * --------------------------------------------------------------------------- */ .ws-kv-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); font-size: 13px; gap: 12px; } .ws-kv-row:last-child { border-bottom: none; } .ws-kv-key { color: var(--muted); } .ws-kv-val { font-weight: 500; text-align: right; } /* --------------------------------------------------------------------------- * Status widget * --------------------------------------------------------------------------- */ .ws-status { display: flex; align-items: flex-start; gap: 12px; padding: 14px; border-radius: 8px; } .ws-status-ok { background: light-dark(#ecfdf5, rgba(16,185,129,0.15)); color: light-dark(#065f46, #6ee7b7); } .ws-status-warn { background: light-dark(#fffbeb, rgba(245,158,11,0.15)); color: light-dark(#78350f, #fcd34d); } .ws-status-fail { background: light-dark(#fef2f2, rgba(239,68,68,0.15)); color: light-dark(#7f1d1d, #fca5a5); } .ws-status-icon { font-size: 22px; font-weight: 700; } .ws-status-msg { font-weight: 500; font-size: 14px; } .ws-status-details { font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Document widget * --------------------------------------------------------------------------- */ .ws-doc-title { font-size: 18px; font-weight: 600; margin-bottom: 4px; } .ws-doc-byline, .ws-doc-meta { color: var(--muted); font-size: 12.5px; } .ws-doc-body { margin-top: 10px; font-size: 14px; line-height: 1.6; white-space: pre-wrap; } .ws-doc-stats { color: var(--muted); font-size: 11px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.05em; } /* --------------------------------------------------------------------------- * Calendar widget * --------------------------------------------------------------------------- */ .ws-cal { display: flex; flex-direction: column; gap: 8px; } .ws-cal-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 8px 0; border-bottom: 1px solid light-dark(#f1f5f9, #1e293b); } .ws-cal-row:last-child { border-bottom: none; } .ws-cal-time { color: var(--muted); font-size: 12.5px; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-cal-title { font-size: 14px; font-weight: 500; } .ws-cal-loc, .ws-cal-att { font-size: 12px; color: var(--muted); margin-top: 2px; } /* --------------------------------------------------------------------------- * Plan widget * --------------------------------------------------------------------------- */ .ws-plan-row { display: grid; grid-template-columns: 24px 1fr; gap: 8px; padding: 4px 0; } .ws-plan-mark { color: var(--muted); font-size: 16px; } .ws-plan-completed .ws-plan-mark { color: var(--green); } .ws-plan-in_progress .ws-plan-mark { color: var(--accent); } .ws-plan-failed .ws-plan-mark { color: var(--red); } .ws-plan-label { font-size: 13px; } .ws-plan-detail { font-size: 12px; color: var(--muted); } /* --------------------------------------------------------------------------- * Image widget * --------------------------------------------------------------------------- */ .ws-img img { max-width: 100%; border-radius: 6px; border: 1px solid var(--border); } .ws-img figcaption { color: var(--muted); font-size: 12px; margin-top: 6px; } /* --------------------------------------------------------------------------- * Model3D widget — needs Google's <model-viewer> custom element loaded * separately (e.g. https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js) * --------------------------------------------------------------------------- */ .ws-model3d { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; min-height: 200px; } .ws-model3d model-viewer { flex: 1; min-height: 200px; width: 100%; background: light-dark(#f1f5f9, #1e293b); border-radius: 8px; } .ws-model3d-meta { font-size: 11px; color: var(--muted); text-align: center; font-family: ui-monospace, "SF Mono", Menlo, monospace; } .ws-model3d-fallback { display: grid; grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; background: light-dark(#f8fafc, #1e293b); border: 1px solid var(--border); border-radius: 8px; } .ws-model3d-poster { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: light-dark(#e2e8f0, #334155); border-radius: 8px; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; font-weight: 700; color: light-dark(#475569, #cbd5e1); letter-spacing: 0.04em; } .ws-model3d-poster img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; } .ws-model3d-name { font-size: 14px; font-weight: 600; } .ws-model3d-link { font-size: 11px; color: var(--accent); text-decoration: none; margin-top: 4px; display: inline-block; } .ws-model3d-link:hover { text-decoration: underline; } </style> </head> <body> <div id="scenecast-root"><div class="ws-stack ws-stack--vertical"> <div class="ws-stack-head"> <div class="ws-app-tile ws-app-tile--chip" style="background:linear-gradient(160deg,#5856d6 0%,#3f3eaf 100%);color:#fff"> <div class="ws-app-glyph"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z"/> </svg></div> </div> <span class="ws-stack-title">Feed</span> <span class="ws-stack-meta">2026-05-10T09:00:00Z</span> </div><div class="ws-stack-body"><div class="ws-list ws-list--vertical"><div class="ws-title">Example Daily</div><ul><li class="ws-li" data-widget-anchor="item[i1]"> <div class="ws-li-row"> <span class="ws-li-title">Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital</span> </div> <div class="ws-li-sub">The round, led by Atlas Capital with participation from existing investors, brings total funding to $750M. Acme AI plans to expand its inference infrastructure.</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">More</div><ul><li class="ws-li" data-widget-anchor="item[i2]"> <div class="ws-li-row"> <span class="ws-li-title">Acme AI closes Series C, eyeing $5B valuation</span> </div> <div class="ws-li-sub">Example Tech</div> </li><li class="ws-li" data-widget-anchor="item[i3]"> <div class="ws-li-row"> <span class="ws-li-title">Atlas Capital Leads $500M Round in Acme AI</span> </div> <div class="ws-li-sub">Example Wire</div> </li><li class="ws-li" data-widget-anchor="item[i4]"> <div class="ws-li-row"> <span class="ws-li-title">Acme AI raises $500M Series C (example.com)</span> </div> <div class="ws-li-sub">Hacker News</div> </li><li class="ws-li" data-widget-anchor="item[i5]"> <div class="ws-li-row"> <span class="ws-li-title">Inside Acme AI&#39;s Series C: The Cap Table That Took Shape</span> </div> <div class="ws-li-sub">Example Newsletter</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">X</div><ul><li class="ws-li" data-widget-anchor="item[i6]"> <div class="ws-li-row"> <span class="ws-li-title">@ai_capital</span> </div> <div class="ws-li-sub">Acme AI at $5B is the cleanest pure-play AI capital story of the year. Most of the rest is bundled into bigger platform bets.</div> </li><li class="ws-li" data-widget-anchor="item[i7]"> <div class="ws-li-row"> <span class="ws-li-title">@enterprise_signal</span> </div> <div class="ws-li-sub">Worth noting: Atlas Capital leading a Series C is a different signal than a growth fund. Enterprise channel suddenly matters in a way it didn&#39;t 12 months ago.</div> </li><li class="ws-li" data-widget-anchor="item[i8]"> <div class="ws-li-row"> <span class="ws-li-title">@ai_economist</span> </div> <div class="ws-li-sub">Valuation reflects narrative, not revenue. The interesting number is unit economics on API calls — which nobody&#39;s publishing.</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">Bluesky</div><ul><li class="ws-li" data-widget-anchor="item[i9]"> <div class="ws-li-row"> <span class="ws-li-title">@ml_curious.bsky.social</span> </div> <div class="ws-li-sub">Curious whether the round was raised primarily to fund inference compute or to fund a training run bigger than anyone has run.</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">LinkedIn</div><ul><li class="ws-li" data-widget-anchor="item[i10]"> <div class="ws-li-row"> <span class="ws-li-title">A. Investor</span> </div> <div class="ws-li-sub">Notable that this round was led by a tier-one fund rather than a corporate strategic. That structure is becoming the default for late-stage AI rounds — the deep pockets and distribution channels matter more than the financing mechanics at this scale.</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">Example Research Lab</div><ul><li class="ws-li" data-widget-anchor="item[i11]"> <div class="ws-li-row"> <span class="ws-li-title">ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level</span> </div> <div class="ws-li-sub">Combining symbolic search with neural reasoning, the system solves 4 of 6 olympiad problems in under three days — first system to reach silver-medal performance on this benchmark.</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">More</div><ul><li class="ws-li" data-widget-anchor="item[i12]"> <div class="ws-li-row"> <span class="ws-li-title">Hybrid symbolic-neural system reaches silver-medal performance on math olympiad benchmark</span> </div> <div class="ws-li-sub">R. Researcher et al. · Example Journal</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">X</div><ul><li class="ws-li" data-widget-anchor="item[i13]"> <div class="ws-li-row"> <span class="ws-li-title">@example_lab</span> </div> <div class="ws-li-sub">ProofBot + GeoSolver 2 just reached silver-medal level — solving 4 out of 6 problems. Combining symbolic search with neural reasoning is the unlock.</div> </li><li class="ws-li" data-widget-anchor="item[i14]"> <div class="ws-li-row"> <span class="ws-li-title">@lean_prover</span> </div> <div class="ws-li-sub">What&#39;s interesting in the ProofBot result isn&#39;t the score — it&#39;s that the model is searching over a formal language where verification is free. That&#39;s the part transferring to other domains is hard.</div> </li></ul></div><div class="ws-list ws-list--vertical"><div class="ws-title">anon_hacker / Hacker News</div><ul><li class="ws-li" data-widget-anchor="item[i15]"> <div class="ws-li-row"> <span class="ws-li-title">Show HN: A tiny Lisp implementation in 500 lines of Rust</span> </div> <div class="ws-li-sub">Hacker News</div> </li></ul></div></div></div></div> <script type="module"> // ---- MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ---- // Spec: hosts deliver tool results via { method: "ui/notifications/tool-result", params: { structuredContent } } // bundles invoke tools via { method: "tools/call", params: { name, arguments } } let nextId = 1; const initialState = {"type":"stack","header":{"glyph":"<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z\"/>\n </svg>","color":"indigo","title":"Feed","meta":"2026-05-10T09:00:00Z"},"body":[{"type":"list","title":"Example Daily","items":[{"id":"i1","title":"Acme AI raises $500M Series C at $5B valuation, led by Atlas Capital","subtitle":"The round, led by Atlas Capital with participation from existing investors, brings total funding to $750M. Acme AI plans to expand its inference infrastructure."}]},{"type":"list","title":"More","items":[{"id":"i2","title":"Acme AI closes Series C, eyeing $5B valuation","subtitle":"Example Tech"},{"id":"i3","title":"Atlas Capital Leads $500M Round in Acme AI","subtitle":"Example Wire"},{"id":"i4","title":"Acme AI raises $500M Series C (example.com)","subtitle":"Hacker News"},{"id":"i5","title":"Inside Acme AI's Series C: The Cap Table That Took Shape","subtitle":"Example Newsletter"}]},{"type":"list","title":"X","items":[{"id":"i6","title":"@ai_capital","subtitle":"Acme AI at $5B is the cleanest pure-play AI capital story of the year. Most of the rest is bundled into bigger platform bets."},{"id":"i7","title":"@enterprise_signal","subtitle":"Worth noting: Atlas Capital leading a Series C is a different signal than a growth fund. Enterprise channel suddenly matters in a way it didn't 12 months ago."},{"id":"i8","title":"@ai_economist","subtitle":"Valuation reflects narrative, not revenue. The interesting number is unit economics on API calls — which nobody's publishing."}]},{"type":"list","title":"Bluesky","items":[{"id":"i9","title":"@ml_curious.bsky.social","subtitle":"Curious whether the round was raised primarily to fund inference compute or to fund a training run bigger than anyone has run."}]},{"type":"list","title":"LinkedIn","items":[{"id":"i10","title":"A. Investor","subtitle":"Notable that this round was led by a tier-one fund rather than a corporate strategic. That structure is becoming the default for late-stage AI rounds — the deep pockets and distribution channels matter more than the financing mechanics at this scale."}]},{"type":"list","title":"Example Research Lab","items":[{"id":"i11","title":"ProofBot and GeoSolver 2 solve advanced math problems at silver-medal level","subtitle":"Combining symbolic search with neural reasoning, the system solves 4 of 6 olympiad problems in under three days — first system to reach silver-medal performance on this benchmark."}]},{"type":"list","title":"More","items":[{"id":"i12","title":"Hybrid symbolic-neural system reaches silver-medal performance on math olympiad benchmark","subtitle":"R. Researcher et al. · Example Journal"}]},{"type":"list","title":"X","items":[{"id":"i13","title":"@example_lab","subtitle":"ProofBot + GeoSolver 2 just reached silver-medal level — solving 4 out of 6 problems. Combining symbolic search with neural reasoning is the unlock."},{"id":"i14","title":"@lean_prover","subtitle":"What's interesting in the ProofBot result isn't the score — it's that the model is searching over a formal language where verification is free. That's the part transferring to other domains is hard."}]},{"type":"list","title":"anon_hacker / Hacker News","items":[{"id":"i15","title":"Show HN: A tiny Lisp implementation in 500 lines of Rust","subtitle":"Hacker News"}]}]}; function rpc(method, params) { window.parent.postMessage( { jsonrpc: "2.0", id: String(nextId++), method, params: params ?? {} }, "*", ); } // Public bridge — bundles or developer-tools can drive it. window.scenecast = { initialState, /** Call a host-registered tool by name. */ callTool: (name, args) => rpc("tools/call", { name, arguments: args ?? {} }), /** Post a follow-up message to the conversation. */ postMessage: (text) => rpc("ui/message", { content: [{ type: "text", text }] }), /** Sync UI-derived state into the model's context. */ updateModelContext: (content) => rpc("ui/update-model-context", { content }), }; // Wire any element with [data-tool-call] to fire tools/call on click. // Use [data-tool-args] (JSON) to pass arguments. document.addEventListener("click", (e) => { const t = e.target.closest && e.target.closest("[data-tool-call]"); if (!t) return; e.preventDefault(); const name = t.getAttribute("data-tool-call"); let args = {}; const raw = t.getAttribute("data-tool-args"); if (raw) { try { args = JSON.parse(raw); } catch {} } window.scenecast.callTool(name, args); }); // Receive tool results / state updates from the host. window.addEventListener("message", (e) => { const msg = e.data; if (!msg || typeof msg !== "object") return; if (msg.method === "ui/notifications/tool-result") { const next = msg.params && msg.params.structuredContent; if (next) { window.scenecast.initialState = next; window.dispatchEvent(new CustomEvent("scenecast:state", { detail: next })); } } // Optional theme override — the scenecast gallery and other embedding // pages use this to keep the iframe's color-scheme in sync with the // page's user-selected theme. Values: "light" | "dark" | "auto". if (msg.method === "scenecast/set-theme") { const t = msg.params && msg.params.theme; if (t === "light" || t === "dark") { document.documentElement.setAttribute("data-theme", t); } else { document.documentElement.removeAttribute("data-theme"); } } }); </script> </body> </html>