
x-card
Use when building AI-driven UIs with @ant-design/x-card — covers XCard.Box, XCard.Card, A2UI v0.9 commands, data binding, catalogs, actions, and streaming patterns.
- Installs
- 67
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/ant-design/x --skill x-card- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads x-card automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
🎯 Skill Positioning
This skill covers @ant-design/x-card — the React implementation of the A2UI protocol, enabling AI agents to dynamically render rich interactive UIs through structured JSON command streams.
It covers:
XCard.Box+XCard.Cardcomponent usage- A2UI v0.9 command types:
createSurface,updateComponents,updateDataModel,deleteSurface - Custom component registration and catalog management
- Data binding via JSON Pointer paths (RFC 6901)
- Action handling — sending user events back to the agent
- Streaming progressive rendering patterns
- v0.8 ↔ v0.9 protocol differences
Scope: v0.9 is the recommended protocol. v0.8 is supported for backward compatibility only — prefer v0.9 for all new work.
Table of Contents
- 📦 Package Overview
- 🗂️ Component Architecture
- 🚀 Quick Start Decision Guide
- 🛠 Recommended Workflow
- 🚨 Development Rules
- 🤝 Skill Collaboration
- 🔗 Reference Resources
📦 Package Overview
| Package | Responsibility |
|---|---|
@ant-design/x-card | React renderer for A2UI protocol — XCard.Box, XCard.Card, catalog APIs |
@ant-design/x | Chat UI components (Bubble, Sender, etc.) — not covered here |
@ant-design/x-sdk | Data providers, streaming — not covered here |
npm install @ant-design/x-card
Exports:
import {
XCard,
registerCatalog,
loadCatalog,
validateComponent,
clearCatalogCache,
} from '@ant-design/x-card';
import type {
XAgentCommand_v0_9,
XAgentCommand_v0_8,
ActionPayload,
Catalog,
CatalogComponent,
} from '@ant-design/x-card';
// Subcomponents
XCard.Box; // Container: receives commands, owns catalog maps
XCard.Card; // Renderer: renders a single surface by id
🗂️ Component Architecture
XCard.Box
├── owns: catalogMap, surfaceCatalogMap
├── dispatches: commands → all XCard.Card children
├── aggregates: onAction events from all Cards
└── XCard.Card (id="surface-a")
│ ├── owns: component tree, data model, commandVersion
│ └── resolves: data bindings, triggers actions
└── XCard.Card (id="surface-b")
└── ...
XCard.Box Props
interface BoxProps {
commands?: (XAgentCommand_v0_9 | XAgentCommand_v0_8)[];
/** Component names must start with an uppercase letter (React component convention) */
components?: Record<string, React.ComponentType<any>>;
onAction?: (payload: ActionPayload) => void;
children?: React.ReactNode; // Should contain XCard.Card elements
}
XCard.Card Props
interface CardProps {
id: string; // surfaceId to render
}
ActionPayload
interface ActionPayload {
name: string; // from action.event.name
surfaceId: string; // which surface triggered it
/**
* Context passed by component, with path references automatically resolved.
*
* For action.event.context fields using { path: "xxx" } format:
* - X-Card automatically resolves them to { value: "actual_value" }
* - Other properties (like label) are preserved
*
* Example input config:
* { username: { path: "/form/username", label: "用户名" } }
*
* Example resolved context:
* { username: { value: "张三", label: "用户名" } }
*/
context: Record<string, any>;
}
🚀 Quick Start Decision Guide
| If you need to... | Read first |
|---|---|
| Set up XCard.Box + XCard.Card | USAGE.md → Basic Setup |
| Send commands from agent to card | COMMANDS.md |
| Register a custom component catalog | CATALOG.md → Local Catalog |
| Bind component props to live data | DATA_BINDING.md |
| Handle user interactions / form submit | ACTIONS.md |
| Build a streaming progressive UI | USAGE.md → Streaming |
| Migrate from v0.8 to v0.9 | COMMANDS.md → v0.8 vs v0.9 |
| Look up full prop types | API.md |
🛠 Recommended Workflow
- Define your catalog — register a local catalog or use the A2UI Basic Catalog URL.
- Register custom components — pass them via
XCard.Boxcomponentsprop. - Create the React tree — wrap surfaces with
XCard.Box, addXCard.Cardper surface. - Feed commands — push
XAgentCommand_v0_9[]intocommandsprop (typically from streaming agent response). - Handle actions — receive
ActionPayloadinonAction, update commands in response.
Minimal Working Example
import React, { useState } from 'react';
import { XCard, registerCatalog } from '@ant-design/x-card';
import type { XAgentCommand_v0_9, ActionPayload, Catalog } from '@ant-design/x-card';
// 1. Define and register local catalog
const myCatalog: Catalog = {
catalogId: 'local://my_catalog.json',
components: {
Text: {
type: 'object',
properties: { text: { type: 'string' }, variant: { type: 'string' } },
required: ['text'],
},
Button: {
type: 'object',
properties: { text: { type: 'string' }, action: {} },
required: ['text'],
},
},
};
registerCatalog(myCatalog);
// 2. Custom component implementations
const Text: React.FC<{ text: string; variant?: string }> = ({ text, variant }) => (
<p className={`text-${variant ?? 'body'}`}>{text}</p>
);
const Button: React.FC<{ text: string; onAction?: (ctx: any) => void; action?: any }> = ({
text,
onAction,
action,
}) => <button onClick={() => onAction?.(action?.event?.context ?? {})}>{text}</button>;
// 3. Build commands (from agent stream)
const commands: XAgentCommand_v0_9[] = [
{
version: 'v0.9',
createSurface: {
surfaceId: 'welcome',
catalogId: 'local://my_catalog.json',
},
},
{
version: 'v0.9',
updateComponents: {
surfaceId: 'welcome',
components: [
{ id: 'root', component: 'Column', children: ['title', 'btn'] },
{ id: 'title', component: 'Text', text: { path: '/user/name' }, variant: 'h1' },
{
id: 'btn',
component: 'Button',
text: 'Start',
action: { event: { name: 'start', context: {} } },
},
],
},
},
{
version: 'v0.9',
updateDataModel: {
surfaceId: 'welcome',
path: '/user/name',
value: 'Alice',
},
},
];
// 4. Render
export default function App() {
const [cmdQueue, setCmdQueue] = useState<XAgentCommand_v0_9[]>(commands);
const handleAction = (payload: ActionPayload) => {
console.log('Action:', payload.name, payload.context);
// Append new commands based on agent response
setCmdQueue((prev) => [...prev /* new commands */]);
};
return (
<XCard.Box commands={cmdQueue} components={{ Text, Button }} onAction={handleAction}>
<XCard.Card id="welcome" />
</XCard.Box>
);
}
🚨 Development Rules
- Always include
"version": "v0.9"on every command — omitting it causes protocol rejection. - One and only one
id: "root"component per surface's component tree — this is the tree root. - Flat adjacency list only — never nest component objects inside other component objects; always reference children by
idstring. - Separate structure from data —
updateComponentsfor layout,updateDataModelfor content/state. - Register catalog before mounting — call
registerCatalog()before the component tree renders. - Pass
componentsmap toXCard.Box, not toXCard.Card— Box distributes to all Cards. - Never recreate the
componentsobject inline — keep it stable withuseMemoor module-level constant to avoid re-renders. - Input components require
value: { path: "..." }for two-way binding — literal values do not update the data model. - For streaming: append new commands to the array rather than replacing it — Card processes the diff incrementally.
action.event.contextpaths are write targets — they point to where user-entered data lives in the data model; do not resolve them as read sources.- Path references in action context are automatically resolved — when an action is triggered, X-Card converts
{ path: "xxx" }in the action config to{ value: "actual_value" }in the onAction payload. This works for both v0.9 (action.event.context = { key: { path } }) and v0.8 (action.context = [{ key, value: { path } }]) formats.
🤝 Skill Collaboration
| Scenario | Skill combination |
|---|---|
| AI chat with structured card responses | use-x-chat + x-components + x-card |
| Standalone agent form UI | x-card only |
| Streaming Markdown + card side-panel | x-markdown + x-card |
| HTTP streaming from agent into card | x-request → feed response as commands |
🔗 Reference Resources
- USAGE.md — Setup guide, streaming pattern, multi-surface examples
- COMMANDS.md — All four A2UI v0.9 command types, v0.8 vs v0.9 diff
- DATA_BINDING.md — JSON Pointer paths, dynamic types, two-way binding, template iteration
- ACTIONS.md — Action definitions, ActionPayload, form submission pattern
- CATALOG.md — Local catalog registration, remote URL loading, custom component schema
- API.md — Full TypeScript types for Box, Card, commands, catalog, actions
Official Documentation
FAQ
What does the x-card skill do?
Use when building AI-driven UIs with @ant-design/x-card — covers XCard.Box, XCard.Card, A2UI v0.9 commands, data binding, catalogs, actions, and streaming patterns.
How do I install x-card?
Run npx skills add https://github.com/ant-design/x --skill x-card in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/x-card/ (personal) or .claude/skills/x-card/ (project).
Which AI agents can use x-card?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is x-card safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains x-card?
It is published by ant-design in ant-design/x. It has 67 recorded installs.
More from ant-design/x
x-request
ant-design/x
Focus on explaining the practical configuration and usage of XRequest, providing accurate configuration instructions based on official documentation
x-chat-provider
ant-design/x
Focus on implementing custom Chat Provider, helping to adapt any streaming interface to Ant Design X standard format
Popular other skills
hyperframes-cli
heygen-com/hyperframes
The HyperFrames CLI by job - scaffold, check, look at frames, edit the timeline, preview, render locally or in the cloud, publish, project history - plus reading its JSON and recovering from build or render failures.
triage
mattpocock/skills
Move issues and external PRs through a state machine of triage roles, categorise, verify, grill if needed, and write agent-ready briefs.
ask-matt
mattpocock/skills
Ask which skill or flow fits your situation. A router over the skills in this repo.
to-questionnaire
mattpocock/skills
Turn a decision you can't fully answer into a questionnaire for someone else to fill in.
loop-me
mattpocock/skills
Grill me about specs for the workflows I want to build, within this workspace.