Make any chatbot response carry interactive UI components such as charts, architecture diagrams, calculators, and data visualizations. No frontend refactor is required. Any model that can output Markdown can drive it.
Project Status: All planned milestones (M0–M3) are complete. The rendering runtime
generative-ui-rendereris published on npm. Channel adaptation (Telegram, Feishu, QQ) is operational. This project is in maintenance mode — no active feature development is planned at this time.
The inspiration and core technical references for this project come from the following authors and open-source projects:
- @op7418 - The article I Recreated Claude's Newly Released Generative UI Interaction helped us recognize early that the code-fence-plus-iframe-isolation approach was technically viable, and it gave this project important direction.
- pi-generative-ui by Michaelliv under the MIT License - It reverse-engineered Claude.ai's native
show_widgetimplementation, extracted the full Anthropic design guidelines (~72 KB), and reproduced the streaming rendering experience in a terminal agent with morphdom and Glimpse. The design guides inprompts/guidelines/in this project are adapted from that extracted material. Reverse-engineering article: Reverse-engineering Claude's generative UI
On March 12, 2026, Anthropic launched generative UI interaction on Claude.ai, allowing models to render interactive HTML/SVG components inline in conversations. Soon after, pi-generative-ui produced a relatively complete open-source reproduction of the mechanism, and the CodePilot article and implementation also provided valuable engineering inspiration.
The goal of this project is to abstract that capability into a general-purpose skill, so every chatbot and AI agent managed by OpenClaw can generate rich UI responses.
maincontains the full M1 + M2 + M3 deliverables. The Web Playground is ready to use, and channel adaptation scripts (screenshot + drill-down button extraction) are in place.- Telegram / Feishu / QQ channel adaptation is operational: widgets are screenshotted as PNG images, and drill-down interactions are mapped to native channel buttons.
generative-ui-rendereris published on npm.- Plugin Hook (
widget-fence-cleaner) is available as an optional install to auto-clean widget fences from outgoing messages.
Channel adaptation relies on the agent proactively calling screenshot scripts and sending images, which demands strong Skill instruction-following capability from the model. Observed performance:
- Strong models (Claude Opus/Sonnet, GPT-5.4) — reliably execute the full screenshot + send + button extraction workflow
- Mid-tier models (Kimi K2.5, Seed 2.0 Pro, etc.) — may occasionally skip the screenshot step or miss button extraction; stronger prompt guidance helps
- Weaker models — may not reliably follow multi-step Skill instructions; not recommended for channel adaptation scenarios
The Web Playground is not affected by this limitation — any model capable of outputting show-widget fences works fine.
The solution is split into three layers: Prompt Skill -> Rendering Runtime -> Channel Adapter Layer, with clear separation between them.
┌─────────────────────────────────────────────────────────┐
│ Any LLM Model │
│ (Claude / GPT / Kimi / Seed / ...) │
└────────────────────────┬────────────────────────────────┘
│ Inject System Prompt + Guidelines
▼
┌─────────────────────────────────────────────────────────┐
│ ① Prompt Skill (M1) │
│ │
│ The model learns to output HTML/SVG widgets inside │
│ ```show-widget fences │
│ Modular design guides are loaded on demand │
│ (diagram / chart / art / ...) │
└────────────────────────┬────────────────────────────────┘
│ The model streams text that contains
│ show-widget fences
▼
┌─────────────────────────────────────────────────────────┐
│ ② Rendering Runtime (M2) │
│ generative-ui-renderer │
│ │
│ Streaming fence detection -> HTML sanitization -> │
│ CSS variable bridging -> rendering │
│ Three-stage pipeline: streaming DOM preview -> │
│ sandbox iframe -> interaction bridge │
└────────────────────────┬────────────────────────────────┘
│ Standardized widget rendering
▼
┌─────────────────────────────────────────────────────────┐
│ ③ Channel Adapter Layer (M3) │
│ │
│ Rendering strategy is chosen based on channel │
│ capabilities: │
│ Web -> full rendering pipeline │
│ Feishu / Telegram / QQ -> image + buttons │
└─────────────────────────────────────────────────────────┘
Key design choices:
- Code fences instead of
tool_use- No dependency on a specific SDK. Any model that can emit Markdown can drive the system. - Three-stage rendering pipeline - Streaming preview for live generation, sandbox iframe for safe execution, and an interaction bridge for drill-down follow-up.
- Modular design guides - Adapted from Anthropic's original guidance and loaded only when needed to avoid wasting tokens.
The system-prompt injection layer is the foundation of the whole approach. Once enabled, the model knows how to output valid HTML/SVG widgets inside ````show-widget` code fences.
Six design-guide modules are built in and can be freely combined:
| Module | Typical Scenarios |
|---|---|
| core | Structured text explanation: concepts, rules, methods, and bullet summaries |
| diagram | Relationships, structures, and flow diagrams such as architecture diagrams, sequence diagrams, and user journeys |
| chart | Data charts for trends, comparisons, distributions, and composition |
| interactive | Interactive content such as clickable, draggable, or parameter-adjustable demos, simulators, and tools |
| mockup | Interfaces, prototypes, and high-fidelity page compositions |
| art | Stylized visuals such as illustrations, posters, mood boards, and world-building scenes |
Every topic includes at least core, then layers on additional perspectives. A single topic can combine 2 to 4 modules to make the output more multidimensional.
generative-ui-renderer is a framework-agnostic JavaScript library currently in M2 development. Once included in a frontend app, it can render the HTML/SVG contained in show-widget fences. Core capabilities include:
- Streaming fence detection plus partial JSON extraction
- Two-stage HTML sanitization: strip dangerous tags during streaming, then preserve scripts for execution inside the sandbox at the final stage
- CSS variable bridging: the model writes standard variable names and the bridge maps them to host-specific variables
- Dual renderer modes: iframe isolation mode and morphdom performance mode
- Packaging as a Web Component:
<widget-renderer>
The project includes a complete local testing environment in playground/ so you can experience Generative UI directly:
cd playground
cp .env.example .env # Configure your API key
npm install
npm start # Then visit http://localhost:3456The playground includes:
- An Express backend with SSE streaming proxy support for OpenAI, Anthropic, and compatible APIs
- A chat UI frontend with streaming fence detection, incremental DOM preview, and sandbox iframe rendering
- Six example widgets in
examples/: a flowchart, a chart, a calculator, a comparison view, a 3D solar-system scene, and a 3D brewing-process scene
The playground also serves as the prototype validation environment for the M2 rendering runtime. playground/public/app.js already verifies the full three-stage rendering pipeline, and M2 is being extracted from that implementation into a reusable library.
This project is open-sourced for self-hosted and local use. There is currently no shared hosted demo with centrally managed API keys.
To use the playground yourself:
- Clone this repository locally.
- Install dependencies and start the local server.
- Open
http://localhost:3456in your browser. - Use the Playground settings UI to configure your provider, API key, and model list.
- Start testing with your own provider credentials.
Example:
git clone https://github.com/ai-freer/generative-ui-skill.git
cd generative-ui-skill/playground
npm install
npm startFor advanced or repeatable setups, you can also preconfigure playground/.env manually from playground/.env.example, but that is optional rather than the primary path.
If you want to share it inside your own team, the recommended path is to deploy the playground in your own environment and let each team or deployment manage its own API keys through the UI or environment-based configuration.
Different message containers have very different rendering capabilities. The project defines two rendering strategies and chooses among them based on what the target channel supports:
This section is meant for both end users and developers building channel integrations.
If you want to install this project into channels managed by OpenClaw, or you need the OpenClaw-side setup flow, plugin installation steps, and pre-run requirements, read INSTALL.md first. It contains the dedicated OpenClaw installation and configuration instructions.
| Strategy | Applicable Channels | Method |
|---|---|---|
| Full rendering | Web (iframe) | Complete generative-ui-renderer pipeline with streaming preview and JavaScript interaction |
| Static image + buttons | Feishu, Telegram, QQ | Render the widget headlessly to PNG and map drill-down actions to native buttons |
If you already have a web application, you can integrate the rendering runtime directly:
<script src="generative-ui-renderer"></script>
<widget-renderer stream="..."></widget-renderer>Or you can use playground/ as a reference and embed the streaming-rendering logic into your own chat UI.
If you need to integrate Feishu, Telegram, QQ, or other channels, refer to the architecture design in architecture/m3-channel-adapters.md and implement your own channel adapter. Each adapter only needs to:
- Receive
{ title, widget_code }parsed by the Widget Interceptor - Select a rendering strategy based on channel capabilities
- Call the corresponding rendering service such as the renderer or screenshot service
- Deliver the final result through the channel API
Adding a new channel only requires adding a new adapter. It does not affect the upstream skill or renderer.
| Model | Status | Notes |
|---|---|---|
| Claude Opus 4.6 | ✅ Tested | Best overall stability in the current validation round |
| Claude Sonnet 4.6 | ✅ Tested | Strong balance between quality and cost |
| GPT-5.4 | ✅ Tested | Completed the current validation set with solid overall results |
| Kimi K2.5 | ✅ Tested | Strong visual quality after serial revalidation |
| Seed 2.0 Pro | ✅ Tested with caveats | Good chart/mockup performance, but still weaker on no-widget restraint |
| GLM-5 | ✅ Tested | Improved noticeably after serial revalidation |
| gemini-3.1-pro-preview | ✅ Tested with caveats | Completed the 13-case validation set plus the 3D supplement; the remaining known issue is still the no-widget weather prompt |
The detailed validation record lives in [tests/prompt-validation.md](./tests/prompt-validation.md). The current repository workflow has now covered the 13 main validation cases for Gemini and the 3D supplement (cases 14 / 15A / 15B) for all tested models.
Instruction-following ability varies significantly across models, especially in interaction design such as drill-down and follow-up:
- Stronger models such as Claude Opus/Sonnet and GPT-4/5 can independently decide which content is worth expanding, proactively add drill-down interactions to key nodes, and generate follow-up guidance. The prompt only needs to define the principles and the model can decide on its own.
- Mid-tier models such as Kimi K2.5 and Seed 2.0 Pro can complete basic widget rendering, but they are weaker at judging what deserves interaction and tend to output static charts.
To address that, the system prompt uses a layered guidance strategy:
- Principle layer - defines the criteria for a "meaningful node" such as terminology, data points, process steps, and comparison items, so stronger models can decide autonomously
- Fallback bias - "When in doubt, prefer clickable over static", giving mid-tier models a clear behavioral bias
- Minimum guarantee - requires every widget to include at least 2 to 3 follow-up question buttons at the bottom, so users still have a path to continue even if the model cannot create node-level interaction
Inside widgets, <script src> may only load from the following CDNs, enforced by CSP:
- cdnjs.cloudflare.com - mainstream libraries such as Chart.js and D3
- cdn.jsdelivr.net - npm package CDN
- unpkg.com - npm package CDN
- esm.sh - ESM-focused CDN
cd playground
npm test # Run all tests
npm run test:unit # Unit tests only (parser / search / prompt / planner)
npm run test:e2e # E2E tests plus widget rendering checks| Phase | Scope | Status |
|---|---|---|
| M0 | Technical analysis, source research, and project planning | ✅ Done |
| M1 | Prompt Skill creation and validation | ✅ Done |
| M2 | Rendering runtime library generative-ui-renderer |
✅ Done (published on npm) |
| M3a | Channel adaptation scripts (screenshot + drill-down + fence cleaner) | ✅ Done |
| M3b | Telegram / Feishu / QQ integration | ✅ Done |
For the detailed development roadmap, see DEVELOPMENT.md. For the channel adaptation architecture, see architecture/m3-channel-adapters.md.
- Original article by 歸藏: I Recreated Claude's Newly Released Generative UI Interaction
- Reverse-engineering article: Reverse-engineering Claude's generative UI
- pi-generative-ui repository: https://github.com/Michaelliv/pi-generative-ui (MIT License)
- CodePilot repository: https://github.com/op7418/CodePilot (license not declared)
This project is open-sourced under the Apache License 2.0.
When using this project, please retain the copyright notice and third-party attribution information in NOTICE.