Agent Skills: json-render Component Catalogs

json-render component catalog patterns for AI-safe generative UI. Define Zod-typed catalogs that constrain what AI can generate, use @json-render/shadcn for 29 pre-built components, optimize specs for token efficiency with YAML mode. Use when building AI-generated UIs, defining component catalogs, or integrating json-render into React/Vue/Svelte/React Native projects.

frontendID: yonatangross/orchestkit/json-render-catalog

Install this agent skill to your local

pnpm dlx add-skill https://github.com/yonatangross/orchestkit/tree/HEAD/src/skills/json-render-catalog

Skill Files

Browse the full folder contents for json-render-catalog.

Download Skill

Loading file tree…

src/skills/json-render-catalog/SKILL.md

Skill Metadata

Name
json-render-catalog
Description
"json-render component catalog patterns for AI-safe generative UI. Define Zod-typed catalogs that constrain what AI can generate, use @json-render/shadcn for 29 pre-built components, optimize specs for token efficiency with YAML mode. Use when building AI-generated UIs, defining component catalogs, or integrating json-render into React/Vue/Svelte/React Native projects."

json-render Component Catalogs

json-render (Vercel Labs, 12.9K stars, Apache-2.0) is a framework for AI-safe generative UI. AI generates flat-tree JSON (or YAML) specs constrained to a developer-defined catalog — the catalog is the contract between your design system and AI output. If a component or prop is not in the catalog, AI cannot generate it.

Quick Reference

| Category | Rules | Impact | When to Use | |----------|-------|--------|-------------| | Catalog Definition | 1 | HIGH | Defining component catalogs with Zod | | Prop Constraints | 1 | HIGH | Constraining AI-generated props for safety | | shadcn Catalog | 1 | MEDIUM | Using pre-built shadcn components | | Token Optimization | 1 | MEDIUM | Reducing token usage with YAML mode | | Actions & State | 1 | MEDIUM | Adding interactivity to specs |

Total: 5 rules across 5 categories

How json-render Works

  1. Developer defines a catalog — Zod-typed component definitions with constrained props
  2. AI generates a spec — flat-tree JSON/YAML referencing only catalog components
  3. Runtime renders the spec<Render> component validates and renders each element

The catalog is the safety boundary. AI can only reference types that exist in the catalog, and props are validated against Zod schemas at runtime. This prevents hallucinated components and invalid props from reaching the UI.

Quick Start — 3 Steps

Step 1: Define a Catalog

import { defineCatalog } from '@json-render/core'
import { z } from 'zod'

export const catalog = defineCatalog({
  Card: {
    props: z.object({
      title: z.string(),
      description: z.string().optional(),
    }),
    children: true,
  },
  Button: {
    props: z.object({
      label: z.string(),
      variant: z.enum(['default', 'destructive', 'outline', 'ghost']),
    }),
    children: false,
  },
  StatGrid: {
    props: z.object({
      items: z.array(z.object({
        label: z.string(),
        value: z.string(),
        trend: z.enum(['up', 'down', 'flat']).optional(),
      })).max(20),
    }),
    children: false,
  },
})

Step 2: Implement Components

import type { CatalogComponents } from '@json-render/react'
import type { catalog } from './catalog'

export const components: CatalogComponents<typeof catalog> = {
  Card: ({ title, description, children }) => (
    <div className="rounded-lg border p-4">
      <h3 className="font-semibold">{title}</h3>
      {description && <p className="text-muted-foreground">{description}</p>}
      {children}
    </div>
  ),
  Button: ({ label, variant }) => (
    <button className={cn('btn', `btn-${variant}`)}>{label}</button>
  ),
  StatGrid: ({ items }) => (
    <div className="grid grid-cols-3 gap-4">
      {items.map((item) => (
        <div key={item.label}>
          <span>{item.label}</span>
          <strong>{item.value}</strong>
        </div>
      ))}
    </div>
  ),
}

Step 3: Render a Spec

import { Render } from '@json-render/react'
import { catalog } from './catalog'
import { components } from './components'

function App({ spec }: { spec: JsonRenderSpec }) {
  return <Render catalog={catalog} components={components} spec={spec} />
}

Spec Format

The JSON spec is a flat tree — no nesting, just IDs and references. Load references/spec-format.md for full documentation.

{
  "root": "card-1",
  "elements": {
    "card-1": {
      "type": "Card",
      "props": { "title": "Dashboard" },
      "children": ["chart-1", "btn-1"]
    },
    "btn-1": {
      "type": "Button",
      "props": { "label": "View Details", "variant": "default" }
    }
  }
}

With Interactivity (on / watch / state)

{
  "root": "card-1",
  "elements": {
    "card-1": {
      "type": "Card",
      "props": { "title": "Dashboard" },
      "children": ["chart-1", "btn-1"],
      "on": { "press": { "action": "setState", "path": "/view", "value": "detail" } },
      "watch": { "/data": { "action": "load_data", "url": "/api/stats" } }
    }
  },
  "state": { "/activeTab": "overview" }
}

Load rules/action-state.md for event handlers, watch bindings, and state adapter patterns.

YAML Mode — 30% Fewer Tokens

For one-shot (non-streaming) generation, YAML specs use ~30% fewer tokens than JSON:

root: card-1
elements:
  card-1:
    type: Card
    props:
      title: Dashboard
    children: [chart-1, btn-1]
  btn-1:
    type: Button
    props:
      label: View Details
      variant: default

Use JSON for streaming (JSON Patch RFC 6902 over JSONL requires JSON). Use YAML for one-shot generation where token cost matters. Load rules/token-optimization.md for selection criteria.

Progressive Streaming

json-render supports progressive rendering during streaming. As the AI generates spec elements, they render immediately — the user sees the UI building in real-time. This uses JSON Patch (RFC 6902) operations streamed over JSONL:

{"op":"add","path":"/elements/card-1","value":{"type":"Card","props":{"title":"Dashboard"},"children":[]}}
{"op":"add","path":"/elements/btn-1","value":{"type":"Button","props":{"label":"Save","variant":"default"}}}
{"op":"add","path":"/elements/card-1/children/-","value":"btn-1"}

Elements render as soon as their props are complete — no waiting for the full spec.

@json-render/shadcn — 29 Pre-Built Components

The @json-render/shadcn package provides a production-ready catalog of 29 components with Zod schemas already defined. Load rules/shadcn-catalog.md for the full component list and when to extend vs use as-is.

import { shadcnCatalog, shadcnComponents } from '@json-render/shadcn'
import { mergeCatalogs } from '@json-render/core'

// Use as-is
<Render catalog={shadcnCatalog} components={shadcnComponents} spec={spec} />

// Or merge with custom components
const catalog = mergeCatalogs(shadcnCatalog, customCatalog)

Package Ecosystem

23 packages covering web, mobile, 3D, codegen, and state management. Load references/package-ecosystem.md for the full list organized by category.

When to Use vs When NOT to Use

Use json-render when:

  • AI generates UI and you need to constrain what it can produce
  • You want runtime-validated specs that prevent hallucinated components
  • You need cross-platform rendering (React, Vue, Svelte, React Native, PDF, email)
  • You are building generative UI features (dashboards, reports, forms from natural language)

Do NOT use json-render when:

  • Building static, developer-authored UI — use components directly
  • AI generates code (JSX/TSX) rather than specs — use standard code generation
  • You need full creative freedom without catalog constraints — json-render is deliberately restrictive
  • Performance-critical rendering with thousands of elements — the flat-tree abstraction adds overhead

Migrating from Custom GenUI

If you have existing custom generative UI (hand-rolled JSON-to-component mapping), load references/migration-from-genui.md for a step-by-step migration guide.

Rule Details

Catalog Definition

How to define catalogs with defineCatalog() and Zod schemas.

| Rule | File | Key Pattern | |------|------|-------------| | Catalog Definition | rules/catalog-definition.md | defineCatalog with Zod schemas, children types |

Prop Constraints

Constraining props to prevent AI hallucination.

| Rule | File | Key Pattern | |------|------|-------------| | Prop Constraints | rules/prop-constraints.md | z.enum, z.string().max(), z.array().max() |

shadcn Catalog

Using the 29 pre-built shadcn components.

| Rule | File | Key Pattern | |------|------|-------------| | shadcn Catalog | rules/shadcn-catalog.md | @json-render/shadcn components and extension |

Token Optimization

Choosing JSON vs YAML for token efficiency.

| Rule | File | Key Pattern | |------|------|-------------| | Token Optimization | rules/token-optimization.md | YAML for one-shot, JSON for streaming |

Actions & State

Adding interactivity with events, watchers, and state.

| Rule | File | Key Pattern | |------|------|-------------| | Action & State | rules/action-state.md | on events, watch reactivity, state adapters |

Key Decisions

| Decision | Recommendation | |----------|----------------| | Custom vs shadcn catalog | Start with shadcn, extend with custom types for domain-specific components | | JSON vs YAML spec format | YAML for one-shot (30% fewer tokens), JSON for streaming | | Zod constraint strictness | Tighter is better — use z.enum over z.string, z.array().max() over unbounded | | State management adapter | Match your app's existing state library (Zustand, Redux, Jotai, XState) |

Common Mistakes

  1. Using z.any() or z.unknown() in catalog props — defeats the purpose of catalog constraints, AI can generate anything
  2. Always using JSON specs — wastes 30% tokens when streaming is not needed
  3. Nesting component definitions — json-render uses a flat tree; all elements are siblings referenced by ID
  4. Skipping mergeCatalogs() when combining shadcn + custom — manual merging loses type safety
  5. Not setting .max() on arrays — AI can generate unbounded lists that break layouts

Related Skills

  • ork:ai-ui-generation — AI-assisted UI generation patterns for v0, Bolt, Cursor
  • ork:ui-components — shadcn/ui component patterns and CVA variants
  • ork:component-search — Finding and evaluating React/Vue components
  • ork:design-to-code — Converting designs to production code