Best for
- All @json-render/ renderers are verified against 0.19.0 (@json-render/core).
- Load rules/target-selection.md for detailed selection criteria and trade-offs.
yonatangross/orchestkit/src/skills/multi-surface-render/SKILL.md
Multi-surface rendering with json-render — one JSON spec produces React web, Next.js, React Native, Ink terminal UIs, PDFs, emails, Remotion videos, OG images, and 3D scenes. Covers renderer target selection, registry mapping, and platform APIs (renderToBuffer, renderToStream, renderToFile). Use when generating output for several platforms or creating PDF reports, email templates, demo videos, or social images from one component spec.
Decision brief
Define once, render everywhere. A single json-render catalog and spec can produce React web UIs, PDF reports, HTML emails, Remotion demo videos, and OG images — each surface gets its own registry that maps catalog types to platform-native components.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Declared | Source record | Install path and trigger |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/yonatangross/orchestkit --skill "src/skills/multi-surface-render"Inspect the Agent Skill "multi-surface-render" from https://github.com/yonatangross/orchestkit/blob/4e5c1327b7d7902022ee69328e12db1f6a88f390/src/skills/multi-surface-render/SKILL.md at commit 4e5c1327b7d7902022ee69328e12db1f6a88f390. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Useful for /ork: CLI dashboards and streaming agent chat interfaces — ships 20+ Ink-native components (Box, Text, Spinner, Table, Markdown, Progress, etc.).
Total: 5 rules across 5 categories
1. One catalog — Zod-typed component definitions shared across all surfaces 2. One spec — flat-tree JSON/YAML describing the UI structure 3. Many registries — each surface maps catalog types to its own component implementations 4. Many renderers — each package renders the spec u…
Review the “Shared Catalog (used by all surfaces)” section in the pinned source before continuing.
Review the “Render to Web (React)” section in the pinned source before continuing.
Permission review
No configured static risk pattern was detected
This is not proof of safety. Runtime behavior, indirect dependencies, and hidden external systems are outside the static scan.
Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 90/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 223 | Source | Repository attention, not individual Skill quality |
| Compatibility | 1 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Define once, render everywhere. A single json-render catalog and spec can produce React web UIs, PDF reports, HTML emails, Remotion demo videos, and OG images — each surface gets its own registry that maps catalog types to platform-native components.
| Category | Rules | Impact | When to Use |
|---|---|---|---|
| Target Selection | 1 | HIGH | Choosing which renderer for your use case |
| React Renderer | 1 | MEDIUM | Web apps, SPAs, dashboards |
| PDF & Email Renderer | 1 | HIGH | Reports, documents, notifications |
| Video & Image Renderer | 1 | MEDIUM | Demo videos, OG images, social cards |
| Registry Mapping | 1 | HIGH | Platform-specific component implementations |
Total: 5 rules across 5 categories
The catalog is the contract. The spec is the data. The registry is the platform-specific implementation.
import { defineCatalog } from '@json-render/core'
import { schema } from '@json-render/react/schema'
import { z } from 'zod'
export const catalog = defineCatalog(schema, {
components: {
Heading: {
props: z.object({
text: z.string(),
level: z.enum(['h1', 'h2', 'h3']),
}),
children: false,
},
Paragraph: {
props: z.object({ text: z.string() }),
children: false,
},
StatCard: {
props: z.object({
label: z.string(),
value: z.string(),
trend: z.enum(['up', 'down', 'flat']).optional(),
}),
children: false,
},
},
})
import { Renderer } from '@json-render/react'
import { webRegistry } from './registries/web'
// webRegistry comes from `defineRegistry(catalog, { components })`.
// RendererProps is { spec, registry, loading?, fallback? } — no catalog prop.
export const Dashboard = ({ spec }) => (
<Renderer spec={spec} registry={webRegistry} />
)
import { renderToBuffer, renderToFile } from '@json-render/react-pdf'
import { pdfRegistry } from './registries/pdf'
// Buffer for HTTP response. PDF options are { registry?, state?, handlers? }.
// includeStandard is an EMAIL option, not a PDF one (see references/upstream-pdf.md).
const buffer = await renderToBuffer(spec, { registry: pdfRegistry })
// Direct file output — renderToFile(spec, filePath, options?)
await renderToFile(spec, './output/report.pdf', { registry: pdfRegistry })
import { renderToHtml } from '@json-render/react-email'
import { emailRegistry } from './registries/email'
const html = await renderToHtml(spec, { registry: emailRegistry })
await sendEmail({ to: user.email, subject: 'Weekly Report', html })
import { renderToSvg, renderToPng } from '@json-render/image'
import { imageRegistry } from './registries/image'
const png = await renderToPng(spec, {
registry: imageRegistry,
width: 1200,
height: 630,
})
// Verified 2026-07-31 against @json-render/[email protected]: the export is
// `Renderer` and its props are { spec, components }. fps and durationInFrames
// belong on Remotion's own Composition, not on this renderer.
import { Renderer } from '@json-render/remotion'
import { remotionComponents } from './registries/remotion'
export const DemoVideo = () => (
<Renderer spec={spec} components={remotionComponents} />
)
import { render } from 'ink'
import { Renderer } from '@json-render/ink'
import { catalog } from './catalog'
import { inkRegistry } from './registries/ink'
render(<Renderer spec={spec} catalog={catalog} registry={inkRegistry} />)
Useful for /ork:* CLI dashboards and streaming agent chat interfaces — ships 20+ Ink-native components (Box, Text, Spinner, Table, Markdown, Progress, etc.).
// createNextApp lives on the /server subpath, not the package root.
import { createNextApp } from '@json-render/next/server'
const { getPageData, generateMetadata, generateStaticParams } = createNextApp({
spec, // NextAppSpec: routes keyed by Next.js URL patterns
loaders: { getPost }, // server-side data loaders referenced by route.loader
})
It does not scaffold a project on disk. createNextApp returns the server-side pieces you
re-export from a catch-all route, and the page itself renders through PageRenderer:
// app/[[...slug]]/page.tsx
export { generateMetadata, generateStaticParams }
export default async function Page({ params }) {
const data = await getPageData(params)
if (!data) notFound()
return <PageRenderer {...data} registry={webRegistry} />
}
A spec describes a route tree (pages, layouts, metadata, loading and error states), not just a component tree.
| Target | Package | When to Use | Output |
|---|---|---|---|
| React | @json-render/react | Web apps, SPAs | JSX |
| Next.js | @json-render/next (0.16+) | Full apps: routes, layouts, SSR, metadata | Next.js app |
| Vue | @json-render/vue | Vue projects | Vue components |
| Svelte | @json-render/svelte | Svelte projects | Svelte components |
| Svelte+shadcn | @json-render/shadcn-svelte (0.16+) | 36-component Svelte 5 catalog | Svelte + Tailwind |
| React Native | @json-render/react-native | Mobile apps (25+ components) | Native views |
| Terminal | @json-render/ink (0.15+) | CLI UIs, TUIs, streaming chat | Ink (terminal) |
@json-render/react-pdf | Reports, documents | PDF buffer/file | |
@json-render/react-email | Notifications, digests | HTML string | |
| Remotion | @json-render/remotion | Demo videos, marketing | MP4/WebM |
| Image | @json-render/image | OG images, social cards | SVG/PNG (Satori) |
| YAML | @json-render/yaml (0.14+) | Token optimization, streaming parser | YAML string |
| MCP | @json-render/mcp | Claude/Cursor/ChatGPT conversations | Sandboxed iframe |
| 3D | @json-render/react-three-fiber | 3D scenes (19 components, verified 2026-07-31; roster lives upstream) | Three.js canvas |
| Codegen | @json-render/codegen | Source code from specs | TypeScript/JSX |
All @json-render/* renderers are verified against 0.19.0 (@json-render/core).
Load rules/target-selection.md for detailed selection criteria and trade-offs.
This skill wraps @json-render/*. Vendor documentation is fetched, not repeated. What survives here
is the house delta: references/ork-delta.md plus the five rules.
| Topic | Source |
|---|---|
Full renderer signatures and option objects (renderToBuffer / renderToFile / renderToStream, renderToHtml / renderToPlainText, renderToSvg / renderToPng, Remotion exports) | references/upstream-pdf.md, upstream-email.md, upstream-image.md, upstream-remotion.md (vendored verbatim; re-sync with bash scripts/sync-vercel-skills.sh) |
Standard component rosters per target (Document, Page, Table, email Section / Row / Column, Remotion transitions and effects) | the same four vendored references/upstream-*.md files |
<Renderer> props, defineRegistry, useUIStream | https://github.com/vercel-labs/json-render/tree/main/packages/react. The 0.19 prop-shape correction (no catalog prop, no top-level onError) is a house finding and stays in rules/react-renderer.md |
| Email client constraints: 600px container, table layout, inline styles, absolute image URLs | references/upstream-email.md ("Email Best Practices") |
| Satori CSS support matrix | https://github.com/vercel/satori. The working subset this skill designs image registries against stays in rules/video-image-renderer.md |
| react-pdf style property support (flexbox set, no grid) | https://react-pdf.org/styling |
| Remotion render cost and cloud rendering | https://www.remotion.dev/docs/lambda |
| Per-package capability and output matrix | the house target picks stay in the Decision Matrix above and in rules/target-selection.md; per-package detail at https://github.com/vercel-labs/json-render |
Read references/ork-delta.md before writing renderer code: it carries the API-drift rule, the
Remotion and PDF latency budgets, and the PDF / React Native registry layout ceiling.
The @json-render/react-pdf package renders specs to PDF using react-pdf under the hood. Three output modes: buffer, file, and stream.
import { renderToBuffer, renderToFile, renderToStream } from '@json-render/react-pdf'
// In-memory buffer (for HTTP responses, S3 upload)
// PDF options are { registry?, state?, handlers? }, no catalog field
const buffer = await renderToBuffer(spec, { registry: pdfRegistry })
res.setHeader('Content-Type', 'application/pdf')
res.send(buffer)
// Direct file write — renderToFile(spec, filePath, options?)
await renderToFile(spec, './output/report.pdf', { registry: pdfRegistry })
// Streaming (for large documents)
const stream = await renderToStream(spec, { registry: pdfRegistry })
stream.pipe(res)
Load rules/pdf-email-renderer.md for PDF registry patterns and email rendering.
The @json-render/image package uses Satori to convert specs to SVG, then optionally to PNG. Designed for server-side generation of social media images.
import { renderToSvg, renderToPng } from '@json-render/image'
// SVG output (smaller, scalable)
const svg = await renderToSvg(spec, {
registry: imageRegistry,
width: 1200,
height: 630,
})
// PNG output (universal compatibility)
const png = await renderToPng(spec, {
registry: imageRegistry,
width: 1200,
height: 630,
})
Load rules/video-image-renderer.md for Satori constraints and Remotion composition patterns.
Each surface needs its own registry. The registry maps catalog types to platform-specific component implementations while the catalog and spec stay identical.
// Web registry — uses HTML elements
const webRegistry = {
Heading: ({ text, level }) => {
const Tag = level // h1, h2, h3
return <Tag className="font-bold">{text}</Tag>
},
StatCard: ({ label, value, trend }) => (
<div className="rounded border p-4">
<span className="text-sm text-gray-500">{label}</span>
<strong className="text-2xl">{value}</strong>
</div>
),
}
// PDF registry — uses react-pdf primitives
import { Text, View } from '@react-pdf/renderer'
const pdfRegistry = {
Heading: ({ text, level }) => (
<Text style={{ fontSize: level === 'h1' ? 24 : level === 'h2' ? 18 : 14 }}>
{text}
</Text>
),
StatCard: ({ label, value }) => (
<View style={{ border: '1pt solid #ccc', padding: 8 }}>
<Text style={{ fontSize: 10, color: '#666' }}>{label}</Text>
<Text style={{ fontSize: 18, fontWeight: 'bold' }}>{value}</Text>
</View>
),
}
Load rules/registry-mapping.md for registry creation patterns and type safety.
Decision criteria for choosing the right renderer target.
| Rule | File | Key Pattern |
|---|---|---|
| Target Selection | rules/target-selection.md | Use case mapping, output format constraints |
Web rendering with the <Renderer> component.
| Rule | File | Key Pattern |
|---|---|---|
| React Renderer | rules/react-renderer.md | <Renderer> component, streaming, error boundaries |
Server-side rendering to PDF buffers/files and HTML email strings.
| Rule | File | Key Pattern |
|---|---|---|
| PDF & Email | rules/pdf-email-renderer.md | renderToBuffer, renderToFile, renderToHtml |
Remotion compositions and Satori image generation.
| Rule | File | Key Pattern |
|---|---|---|
| Video & Image | rules/video-image-renderer.md | Renderer (Remotion), renderToPng, renderToSvg |
Creating platform-specific registries for a shared catalog.
| Rule | File | Key Pattern |
|---|---|---|
| Registry Mapping | rules/registry-mapping.md | Per-platform registries, type-safe mapping |
| Decision | Recommendation |
|---|---|
| PDF library | Use @json-render/react-pdf (react-pdf), not Puppeteer screenshots |
| Email rendering | Use @json-render/react-email (react-email), not MJML or custom HTML |
| OG images | Use @json-render/image (Satori), not Puppeteer or canvas |
| Video | Use @json-render/remotion (Remotion), not FFmpeg scripts |
| Registry per platform | Always separate registries; never one registry for all surfaces |
| Catalog sharing | One catalog definition shared via import across all registries |
<View>/<Text>, web uses <div>/<span>ork:json-render-catalog — Catalog definition patterns with Zod, shadcn componentsork:demo-producer — Video production pipeline using Remotionork:mcp-visual-output — Rendering specs in Claude/Cursor via MCPFrequently asked questions
Define once, render everywhere. A single json-render catalog and spec can produce React web UIs, PDF reports, HTML emails, Remotion demo videos, and OG images — each surface gets its own registry that maps catalog types to platform-native components.
The source record exposes this install command: npx skills add https://github.com/yonatangross/orchestkit --skill "src/skills/multi-surface-render". Inspect the command and pinned source before running it.
The pinned source record declares support for: claude code.
Alternatives
yonatangross/orchestkit
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 36 pre-built components, optimize specs with YAML mode, and apply the three edit modes (patch/merge/diff) for progressive updates. Use when building AI-generated UIs, defining component catalogs, or integrating json-render into React/Vue/Svelte/React Native/Ink/Next.js projects.
yonatangross/orchestkit
Use when building Next.js 16+ apps with React Server Components. Covers App Router, Cache Components (replacing experimental_ppr), streaming SSR, Server Actions, and React 19 patterns for server-first architecture.
vasilyu1983/AI-Agents-public
Implements production-grade i18n/l10n for React, Vue, Angular, and Next.js with ICU format and RTL support. Use when setting up or debugging localisation.
fcakyon/claude-codex-settings
Guide for implementing smooth, native-feeling animations using React's View Transition API (`<ViewTransition>` component, `addTransitionType`, and CSS view transition pseudo-elements). Use this skill whenever the user wants to add page transitions, animate route changes, create shared element animations, animate enter/exit of components, animate list reorder, implement directional (forward/back) navigation animations, or integrate view transitions in Next.js. Also use when the user mentions view