Skip to content

feat(composer): production-quality A2UI Composer with AI authoring#1134

Closed
GeneralJerel wants to merge 8 commits intogoogle:mainfrom
GeneralJerel:feat/composer-copilotkit
Closed

feat(composer): production-quality A2UI Composer with AI authoring#1134
GeneralJerel wants to merge 8 commits intogoogle:mainfrom
GeneralJerel:feat/composer-copilotkit

Conversation

@GeneralJerel
Copy link
Copy Markdown

@GeneralJerel GeneralJerel commented Apr 10, 2026

Summary

Production-quality upgrade of the A2UI Composer tool (building on #987). Replaces the original prototype with a fully-featured widget editor powered by CopilotKit and the A2UI v0.9 spec.

  • Widget Editor — Split-pane editor with Monaco code editing, live A2UI preview, and a data panel for inspecting/modifying the data model
  • AI Authoring — Describe a widget in natural language; the AI generates valid A2UI v0.9 JSON using the full component vocabulary (Card, Row, Column, Text, Image, Button, List, Tabs, Modal, etc.)
  • Gallery — Browse, search, and manage saved widgets with IndexedDB persistence (localforage)
  • Theater — Replay recorded A2UI streaming scenarios chunk-by-chunk with JSONL wire inspection, lifecycle events, and variable playback speed
  • Icon Browser — Search and preview Material Symbols icons available to the Icon component
  • Reactive RenderingA2uiSurface uses useSyncExternalStore for granular re-renders via the SurfaceModel
  • Catalog-Driven AI — The built-in A2UI v0.9 basic catalog shapes both the renderer and the LLM system prompt

Key Architecture

  • CopilotKit v2 integration for AI chat runtime (/api/copilotkit route)
  • Next.js 16 App Router with Turbopack, React 19
  • @a2ui/web_core v0.9SurfaceModel, ComponentContext, MessageProcessor, Catalog
  • Client-side persistence via IndexedDB (no server-side database required)

Commits

Commit Description
696b945 Replace PR#987 app with widget-builder from cpk-deployed-composer
08a12fb Add Apache 2.0 license headers to all source files
82d2e65 Add README, AGENTS.md, and CHANGELOG entry
c25b76f Remove custom catalog feature, fix CopilotChat type errors
3112e9b Fix theater JSON syntax colors for light mode, fix card clipping
9ca87f2 Restore test infrastructure (31 tests) and fix Text prop bug
b9723d0 Remove width:100% from Card to prevent right-edge clipping
f45ac2f Add user-facing error notifications for storage failures

Test plan

  • pnpm install && pnpm build — clean build with zero errors
  • pnpm test — 31 tests pass
  • pnpm dev — verify all routes: /, /gallery, /theater, /icons, /components
  • Create a widget via AI prompt on / — verify AI generates valid A2UI v0.9 JSON
  • Edit widget JSON in Monaco editor — verify live preview updates
  • Play a theater scenario — verify JSONL stream Pretty tab is readable, cards render without clipping
  • Verify gallery persistence across page reloads (IndexedDB)

Note: AI authoring requires a GOOGLE_GENERATIVE_AI_API_KEY, GEMINI_API_KEY, or OPENAI_API_KEY in .env.local.

Pre-launch Checklist

🤖 Generated with Claude Code

GeneralJerel and others added 5 commits April 9, 2026 11:06
…yed-composer

Replace the standalone Next.js app in tools/composer/ with the
widget-builder from cpk-deployed-composer/apps/widget-builder/.
The new source includes v0.9 A2UI support, AI authoring via CopilotKit,
custom catalog support, and a local a2ui-v09-renderer.

Changes:
- Clear old tools/composer/ contents (PR google#987 standalone app)
- Port widget-builder source (src, public, config files)
- Remove dead workspace dep @copilotkitnext/a2ui-renderer
- Add .env.example with required AI provider keys
- Add .gitignore for node_modules, .next, .env*, .vercel, .turbo
- Security audit: no hardcoded secrets found

Co-Authored-By: Jerel <jerel@copilotkit.ai>
Co-Authored-By: Jerel <jerel@copilotkit.ai>
Co-Authored-By: Jerel <jerel@copilotkit.ai>
… props

Remove the custom catalog system (CatalogContext, custom-catalog.ts,
/catalog route) to keep the PR scope lean. Also fix pre-existing type
errors from CopilotKit API changes (feather, inputProps, disclaimer
props no longer exist on CopilotChat).

Co-Authored-By: Jerel <jerel@copilotkit.ai>
Shift Pretty tab JSON syntax colors from -400 to -700 shades for
readable light-mode contrast (standard IDE conventions). Fix card
right-side clipping by adding width/overflow constraints to the
A2uiSurface root div and theater renderer wrapper.

Co-Authored-By: Jerel <jerel@copilotkit.ai>
@google-cla
Copy link
Copy Markdown

google-cla bot commented Apr 10, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request upgrades the A2UI Composer tool to a production-quality version, introducing a reactive rendering architecture, AI-assisted widget authoring, and a new gallery and theater for widget management. My review identified a critical regression regarding the removal of the testing infrastructure, which violates the repository's style guide requiring tests for code changes. Additionally, I found a bug in the default widget creation where the wrong prop is passed to the Text component, and I suggested adding user-facing error handling for storage operations to prevent silent data loss.

Comment on lines +42 to -70
"eslint-config-next": "16.0.8",
"express": "4.22.1",
"tailwindcss": "^4",
"tw-animate-css": "^1.4.0",
"typescript": "5.9.3",
"typescript-eslint": "^8.40.0",
"vitest": "^4.0.18",
"wrangler": "^4.73.0"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This pull request introduces a significant amount of new functionality and refactoring, but it also removes the entire testing infrastructure, including vitest and @testing-library. The repository's style guide states, "If there are code changes, code should have tests." Removing tests for a "production-quality" upgrade is a major regression in code quality and maintainability. Please reintroduce a testing setup and add tests for the new features to ensure the composer is robust and prevent future regressions.

References
  1. The repository style guide requires that code changes should have tests. (link)

Comment on lines +35 to +37
component: "Text",
value: "Hello World",
variant: "body",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The Text component expects a text prop, but value is being provided here for the default component. This will result in blank widgets created via the "Start Blank" button not displaying the "Hello World" text.

Suggested change
component: "Text",
value: "Hello World",
variant: "body",
component: "Text",
text: "Hello World",
variant: "body",

Comment on lines +106 to +108
if (widgetToSave) {
await saveWidget(widgetToSave).catch(err => console.error('Failed to persist widget:', err));
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The updateWidget function performs an optimistic UI update and then saves to storage. If the saveWidget call fails, the error is only logged to the console. The user will not be aware that their changes were not persisted, leading to potential data loss if they refresh the page. Consider adding user-facing error handling, such as a toast notification, to inform the user of the failure and allow them to take action.

Add vitest, @testing-library/react, jsdom and 31 tests covering
json-parser, storage, data-panel, editor-header, widget-editor, and
widgets-context. Fix default widget Text component using wrong prop
name (value → text).

Co-Authored-By: Jerel <jerel@copilotkit.ai>
@GeneralJerel GeneralJerel force-pushed the feat/composer-copilotkit branch from 7f4a29d to 9ca87f2 Compare April 10, 2026 18:59
GeneralJerel and others added 2 commits April 10, 2026 12:05
…ping

Cards had width:100% plus 8px horizontal margin, causing the total
footprint to exceed the parent and get clipped by overflow:hidden.
Flex stretch from parent containers handles the width naturally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Addresses Gemini review feedback — storage operations (save, delete,
clear) now show a dismissible error notification instead of only logging
to console. Auto-dismisses after 5 seconds.

Co-Authored-By: Claude Opus 4.6 (1M context) <jerel@copilotkit.ai>
@GeneralJerel
Copy link
Copy Markdown
Author

Closing in favor of a new PR from feat/composer-v09-theater-and-cleanup which includes v0.9 theater updates, gallery fixes, and renderer improvements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant