Skip to content

A2UI 1.0

Macros

A macro is a high-level component the model writes in one call. The server expands it into Gen UI 2.0 standard components before anything reaches the browser, so the client renders plain A2UI and needs no code for it. The design follows the A2UI Python SDK's MacroExpander: macro schemas join the catalog the model reads, the expansion keeps the macro's id at its root and names the rest <id>__<type>_<n>, and macros may nest up to 16 levels. A macro can also load its own data: WeatherReport("Lisbon") fetches the forecast.

FlightCard

1 call, 209 characters in Express, 27 standard components on the wire

Flight itinerary: airline, flight number, origin and destination codes with times, duration, stops, price and a select button. One per flight option. Macro: expands into standard components.

what the model writes (Express)
root = FlightCard("Pacific Air", "PA 214", "SFO", "JFK", "San Francisco", "New York", "07:15", "15:52", "5h 37m", 0, "$289", "Economy", "Thu, Nov 13", "Cheapest", _, Event("select_flight", {flight: "PA 214"}))

Expands into

Card, Row x4, Icon x2, Column x5, Title x4, Caption x5, Badge x2, Text x2, Divider, Button

expanded on the server

ProductCard

1 call, 334 characters in Express, 15 standard components on the wire

Product tile: name, price (and compare-at), rating, short specs, badge, buy button. One per item when comparing products. price and compareAt are display text like "$399"; specs is a list of short strings. Macro: expands into standard components.

what the model writes (Express)
root = ProductCard("Studio Wireless Headphones", "$249", "$329", "https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=600&q=80&auto=format&fit=crop", 4.6, 2184, "Best seller", ["Adaptive noise cancelling", "40 hour battery", "USB-C fast charge, 10 min for 5 hours"], "Add to cart", Event("add_to_cart", {sku: "studio-wl"}))

Expands into

Card, Image, Row x4, Title x2, Badge, Icon, Text x2, Caption, List, Button

expanded on the server

WeatherReport

1 call, 30 characters in Express, 23 standard components on the wire

Live weather for a place: current conditions, the next 12 hours as a chart and a 7-day forecast. Write only the place, for example WeatherReport("Lisbon"): the server fetches the forecast. Macro: expands into standard components.

what the model writes (Express)
root = WeatherReport("Lisbon")

Expands into

Card, Row x3, Column x4, Icon x2, Caption x6, Title, Text x4, Chart, List

expanded on the server

Write a macro

Give it a name, a description the model reads, a Zod schema and an expand function that returns standard components. Add a load function to fetch its data on the server. pnpm catalog:export adds it to the model's catalog and to the generated skills.

src/a2ui/macros/macros.ts
import { z } from "zod";
import { defineMacro, h } from "@/a2ui/macros/macro";

export const FlightCard = defineMacro({
  name: "FlightCard",
  description: "Flight itinerary with a select button. One per flight option.",
  props: z.object({ airline: z.string(), from: z.string(), to: z.string(), price: z.string().optional() }),
  events: { onAction: { description: "Fires when the flight is selected.", parameters: z.object({}).passthrough() } },
  // Pure: props in, a tree of standard components out. Props may be bound ({"@path"}).
  expand: (p) =>
    h("Card", { gap: 3 },
      h("Row", { justify: "spaceBetween" }, h("Title", { text: p.from, size: "xl" }), h("Title", { text: p.to, size: "xl" })),
      h("Button", { label: "Select flight", variant: "primary", onClick: p.onAction })),
});