Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
ant-design avatar

X Card

  • 40 installs
  • 4.7k repo stars
  • Updated August 4, 2026
  • ant-design/x

x-card is a skill for building AI-driven UIs with @ant-design/x-card, the React implementation of the A2UI protocol that renders agent JSON command streams.

About

This skill covers @ant-design/x-card, the React implementation of the A2UI protocol that lets AI agents render interactive UIs from structured JSON command streams. A developer uses it to set up XCard.Box and XCard.Card, register component catalogs, bind data via JSON Pointer paths, and handle user actions sent back to the agent. It also documents A2UI v0.9 commands and streaming progressive rendering.

  • Builds AI-driven UIs with @ant-design/x-card, the React implementation of the A2UI protocol
  • Covers XCard.Box/XCard.Card, A2UI v0.9 commands, catalogs, data binding, and actions
  • Enables agents to render rich interactive UIs from structured JSON command streams

X Card by the numbers

  • 40 all-time installs (skills.sh)
  • Ranked #8,244 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
At a glance

x-card capabilities & compatibility

Capabilities
ant design x · use x chat
Use cases
frontend · ui design · orchestration
From the docs

What x-card says it does

Data binding via JSON Pointer paths (RFC 6901)
SKILL.md
npx skills add https://github.com/ant-design/x --skill x-card

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs40
repo stars4.7k
Last updatedAugust 4, 2026
Repositoryant-design/x

What it does

Render agent-driven interactive UIs from A2UI JSON command streams with @ant-design/x-card.

Who is it for?

Developers rendering agent-generated interactive UIs from A2UI command streams in React.

Skip if: Chat bubble UI (use ant-design-x) or data providers/streaming SDK internals (use @ant-design/x-sdk).

When should I use this skill?

Building AI-driven UIs with @ant-design/x-card, using A2UI commands, catalogs, data binding, actions, or streaming patterns.

What you get

An XCard.Box/Card setup that renders A2UI v0.9 command streams with data binding and action handling.

  • XCard.Box/Card setup
  • component catalog registration
  • action handlers

By the numbers

  • A2UI v0.9 with 4 command types (createSurface, updateComponents, updateDataModel, deleteSurface)
  • data binding via JSON Pointer (RFC 6901)

Files

SKILL.mdMarkdownGitHub ↗

🎯 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.Card component 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

PackageResponsibility
@ant-design/x-cardReact renderer for A2UI protocol — XCard.Box, XCard.Card, catalog APIs
@ant-design/xChat UI components (Bubble, Sender, etc.) — not covered here
@ant-design/x-sdkData 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.CardUSAGE.md → Basic Setup
Send commands from agent to cardCOMMANDS.md
Register a custom component catalogCATALOG.md → Local Catalog
Bind component props to live dataDATA_BINDING.md
Handle user interactions / form submitACTIONS.md
Build a streaming progressive UIUSAGE.md → Streaming
Migrate from v0.8 to v0.9COMMANDS.md → v0.8 vs v0.9
Look up full prop typesAPI.md

🛠 Recommended Workflow

1. Define your catalog — register a local catalog or use the A2UI Basic Catalog URL. 2. Register custom components — pass them via XCard.Box components prop. 3. Create the React tree — wrap surfaces with XCard.Box, add XCard.Card per surface. 4. Feed commands — push XAgentCommand_v0_9[] into commands prop (typically from streaming agent response). 5. Handle actions — receive ActionPayload in onAction, 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 id string.
  • Separate structure from dataupdateComponents for layout, updateDataModel for content/state.
  • Register catalog before mounting — call registerCatalog() before the component tree renders.
  • Pass `components` map to `XCard.Box`, not to XCard.Card — Box distributes to all Cards.
  • Never recreate the `components` object inline — keep it stable with useMemo or 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.context` paths 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

ScenarioSkill combination
AI chat with structured card responsesuse-x-chat + x-components + x-card
Standalone agent form UIx-card only
Streaming Markdown + card side-panelx-markdown + x-card
HTTP streaming from agent into cardx-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

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.