A2UI Catalog Extractor
English | 简体中文
@lynx-js/genui/a2ui-catalog-extractor is the internal TypeDoc-powered extraction
engine behind genui a2ui generate catalog. It turns TypeScript component
interfaces into A2UI component catalog JSON. You write the public component
contract once as a TypeScript interface, describe it with normal TypeDoc
comments, and run the public genui a2ui command to generate the JSON Schema
that an A2UI agent can read.
For user-facing scripts, use genui a2ui generate catalog. Treat
this package as the implementation layer for extraction behavior and tests.
What It Does
A2UI catalogs describe what components a renderer supports. For each component, the catalog tells an agent which props are valid, which props are required, which enum values are allowed, and what each field means.
This extractor generates the components part of an A2UI v0.9 catalog:
It can also wrap those generated components with a catalogId,
functions, and theme through createA2UICatalog.
What It Does Not Do
- It does not render A2UI UI.
- It does not parse TypeScript source text by hand.
- It does not use the TypeScript compiler API directly.
- It does not ask you to write JSON Schema in comments.
- It does not expand arbitrary imported type aliases or external interfaces.
- It does not call an LLM or choose a model.
The package consumes TypeDoc reflection data. This keeps the implementation small, but it also means catalog-facing shapes should be written inline in the marked interface.
Requirements
- Node.js 22 or newer.
- TypeScript or TSX source files that TypeDoc can read.
- One TypeScript
interfaceper catalog-facing component contract.
Installation
Package manager
Run the public CLI after installing @lynx-js/genui:
Then add a script to your package:
Run it with:
Quick Start
This example walks through a complete component contract from TypeScript interface to generated catalog JSON.
1. Create a catalog-facing interface
Create src/catalog/QuickStartCard.tsx:
The important part is @a2uiCatalog QuickStartCard. It tells the
extractor that this interface should become a catalog component named
QuickStartCard.
2. Generate catalog files
Run:
The extractor scans the catalog directory, finds interfaces marked with
@a2uiCatalog, and writes one file per component:
3. Read the generated schema
dist/catalog/QuickStartCard/catalog.json will look like this:
Notice the main conversions:
titleis required because it does not use?.tonebecomes a string enum.tags?: string[]becomes an optional array of strings.authorbecomes a strict inline object withadditionalProperties: false.context?: Record<string, string | number | boolean>becomes an object map withadditionalProperties.- TypeDoc comments become JSON Schema descriptions.
Authoring Guide
Mark only the catalog contract
Only TypeScript interface reflections are converted. Put
@a2uiCatalog on the interface that describes the props an agent is
allowed to send:
Do not put the tag on the component function:
Component names
You can write the component name explicitly:
If the tag is empty, the extractor infers the name from the interface by
removing a trailing Props or ComponentProps:
This becomes DemoText.
Comments become schema metadata
Use normal TypeDoc comments:
The extractor maps comments like this:
For object and array defaults, put JSON inside a code span:
Without the code span, TypeDoc may pass formatted text instead of the raw JSON value.
Supported TypeScript shapes
Unsupported or ambiguous types
These types intentionally fail:
anyunknownnullundefinednevervoid- nullable unions such as
string | null - most imported aliases and referenced external interfaces
Record<number, T>or other non-string record keys
Prefer explicit catalog contracts:
Write the shape inline instead:
CLI Reference
The public CLI entry point is
genui a2ui generate catalog. It delegates to this package
internally.
Generate catalog artifacts
--source and --catalog-dir can be used together. The extractor merges
all inputs, removes duplicates, sorts them, and then runs TypeDoc.
The extractor writes both per-component files such as
dist/catalog/QuickStartCard/catalog.json and a full catalog file at
dist/catalog.json.
The scanner accepts .ts, .tsx, .js, .jsx, .mts, and .cts
files. It ignores .d.ts, node_modules, dist, and .turbo.
Repository-internal Programmatic API
The package entry point intentionally exposes only the extraction helpers needed
by repository tooling and tests. It is not the external integration surface for
product code. Product build scripts should call
genui a2ui generate catalog instead of importing this package directly.
Use cwd in extraction options when paths should be resolved relative to a
specific project directory. Artifact writing and TypeDoc JSON reuse are CLI
implementation details; use genui a2ui generate catalog for those flows.
Troubleshooting
Unsupported ambiguous intrinsic TypeDoc type "unknown"
The catalog needs a concrete schema. Replace unknown or any with a
specific type:
Unsupported nullable union
Nullable unions are not accepted:
Make the property optional if it can be omitted:
Or model the state explicitly:
Unsupported TypeDoc reference
The extractor only understands a small set of references:
Array<T>, ReadonlyArray<T>, and Record<string, T>. Inline object
shapes in the catalog-facing interface instead of importing aliases.
My output directory is empty
Check these points:
- The scanned files contain an
interface, not only atype. - The interface has
@a2uiCatalog. - The path passed to
--catalog-diror--sourceexists. - The files are not
.d.ts. - TypeDoc can parse the files with your
tsconfig.
The generated schema does not include inherited props
Inherited members are skipped. This is intentional because runtime-only props such as renderer context should not be part of the agent-facing catalog. Put every catalog-facing prop directly on the marked interface.
Should I hand-write JSON Schema instead?
No. Keep the contract in TypeScript and comments. Hand-written schema tends to drift away from component props, while this package makes the catalog a repeatable build artifact.
Does this replace TypeScript type checking?
No. TypeDoc conversion is used to read reflection data, not to validate your full application. Continue running your normal TypeScript, lint, and test commands.

