Source profileQuality 90/100

yonatangross/orchestkit/src/skills/multi-surface-render/SKILL.md

multi-surface-render

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.

Source repository stars
223
Declared platforms
1
Static risk flags
0
Last source update
2026-08-24
Source checked
2026-08-25

Decision brief

What it does: where it fits

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.

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.

Not for

  • Building separate component trees for each surface — defeats the purpose; share the catalog and spec
  • Using Puppeteer to screenshot React for PDF generation — slow, fragile; use native react-pdf rendering

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeDeclaredSource recordInstall path and trigger
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/yonatangross/orchestkit --skill "src/skills/multi-surface-render"
Safe inspection promptEditorial

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

What the source asks the agent to do

  1. 01

    Quick Start — Same Catalog, Different Renderers

    Useful for /ork: CLI dashboards and streaming agent chat interfaces — ships 20+ Ink-native components (Box, Text, Spinner, Table, Markdown, Progress, etc.).

    Useful for /ork: CLI dashboards and streaming agent chat interfaces — ships 20+ Ink-native components (Box, Text, Spinner, Table, Markdown, Progress, etc.).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:A spec describes a route tree (pages, layouts, metadata, loading and error states), not just a component tree.
  2. 02

    Quick Reference

    Total: 5 rules across 5 categories

    Total: 5 rules across 5 categories
  3. 03

    How Multi-Surface Rendering Works

    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…

    One catalog — Zod-typed component definitions shared across all surfacesOne spec — flat-tree JSON/YAML describing the UI structureMany registries — each surface maps catalog types to its own component implementations
  4. 04

    Shared Catalog (used by all surfaces)

    Review the “Shared Catalog (used by all surfaces)” section in the pinned source before continuing.

    Review and apply the “Shared Catalog (used by all surfaces)” source section.
  5. 05

    Render to Web (React)

    Review the “Render to Web (React)” section in the pinned source before continuing.

    Review and apply the “Render to Web (React)” source section.

Permission review

Static risk signals and limitations

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

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score90/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars223SourceRepository attention, not individual Skill quality
Compatibility1 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
yonatangross/orchestkit
Skill path
src/skills/multi-surface-render/SKILL.md
Commit
4e5c1327b7d7902022ee69328e12db1f6a88f390
License
MIT
Collected
2026-08-25
Default branch
main
View the original SKILL.md

Multi-Surface Rendering with json-render

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.

Quick Reference

CategoryRulesImpactWhen to Use
Target Selection1HIGHChoosing which renderer for your use case
React Renderer1MEDIUMWeb apps, SPAs, dashboards
PDF & Email Renderer1HIGHReports, documents, notifications
Video & Image Renderer1MEDIUMDemo videos, OG images, social cards
Registry Mapping1HIGHPlatform-specific component implementations

Total: 5 rules across 5 categories

How Multi-Surface Rendering Works

  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 using its registry

The catalog is the contract. The spec is the data. The registry is the platform-specific implementation.

Quick Start — Same Catalog, Different Renderers

Shared Catalog (used by all surfaces)

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,
    },
  },
})

Render to Web (React)

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} />
)

Render to PDF

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 })

Render to Email

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 })

Render to OG Image (Satori)

import { renderToSvg, renderToPng } from '@json-render/image'
import { imageRegistry } from './registries/image'

const png = await renderToPng(spec, {
  registry: imageRegistry,
  width: 1200,
  height: 630,
})

Render to Video (Remotion)

// 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} />
)

Render to Terminal (Ink, 0.15+)

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.).

Render to Next.js App (0.16+)

// 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.

Decision Matrix — When to Use Each Target

TargetPackageWhen to UseOutput
React@json-render/reactWeb apps, SPAsJSX
Next.js@json-render/next (0.16+)Full apps: routes, layouts, SSR, metadataNext.js app
Vue@json-render/vueVue projectsVue components
Svelte@json-render/svelteSvelte projectsSvelte components
Svelte+shadcn@json-render/shadcn-svelte (0.16+)36-component Svelte 5 catalogSvelte + Tailwind
React Native@json-render/react-nativeMobile apps (25+ components)Native views
Terminal@json-render/ink (0.15+)CLI UIs, TUIs, streaming chatInk (terminal)
PDF@json-render/react-pdfReports, documentsPDF buffer/file
Email@json-render/react-emailNotifications, digestsHTML string
Remotion@json-render/remotionDemo videos, marketingMP4/WebM
Image@json-render/imageOG images, social cardsSVG/PNG (Satori)
YAML@json-render/yaml (0.14+)Token optimization, streaming parserYAML string
MCP@json-render/mcpClaude/Cursor/ChatGPT conversationsSandboxed iframe
3D@json-render/react-three-fiber3D scenes (19 components, verified 2026-07-31; roster lives upstream)Three.js canvas
Codegen@json-render/codegenSource code from specsTypeScript/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.

Upstream coverage (do not restate)

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.

TopicSource
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, useUIStreamhttps://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 URLsreferences/upstream-email.md ("Email Best Practices")
Satori CSS support matrixhttps://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 renderinghttps://www.remotion.dev/docs/lambda
Per-package capability and output matrixthe 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.

PDF Renderer — Reports and Documents

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.

Image Renderer — OG Images and Social Cards

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.

Registry Mapping — Same Catalog, Platform-Specific Components

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.

Rule Details

Target Selection

Decision criteria for choosing the right renderer target.

RuleFileKey Pattern
Target Selectionrules/target-selection.mdUse case mapping, output format constraints

React Renderer

Web rendering with the <Renderer> component.

RuleFileKey Pattern
React Rendererrules/react-renderer.md<Renderer> component, streaming, error boundaries

PDF & Email Renderer

Server-side rendering to PDF buffers/files and HTML email strings.

RuleFileKey Pattern
PDF & Emailrules/pdf-email-renderer.mdrenderToBuffer, renderToFile, renderToHtml

Video & Image Renderer

Remotion compositions and Satori image generation.

RuleFileKey Pattern
Video & Imagerules/video-image-renderer.mdRenderer (Remotion), renderToPng, renderToSvg

Registry Mapping

Creating platform-specific registries for a shared catalog.

RuleFileKey Pattern
Registry Mappingrules/registry-mapping.mdPer-platform registries, type-safe mapping

Key Decisions

DecisionRecommendation
PDF libraryUse @json-render/react-pdf (react-pdf), not Puppeteer screenshots
Email renderingUse @json-render/react-email (react-email), not MJML or custom HTML
OG imagesUse @json-render/image (Satori), not Puppeteer or canvas
VideoUse @json-render/remotion (Remotion), not FFmpeg scripts
Registry per platformAlways separate registries; never one registry for all surfaces
Catalog sharingOne catalog definition shared via import across all registries

Common Mistakes

  1. Building separate component trees for each surface — defeats the purpose; share the catalog and spec
  2. Using Puppeteer to screenshot React for PDF generation — slow, fragile; use native react-pdf rendering
  3. One giant registry covering all platforms — impossible since PDF uses <View>/<Text>, web uses <div>/<span>
  4. Forgetting Satori limitations — no CSS grid, limited flexbox; design image registries with these constraints
  5. Duplicating catalog definitions per surface — one catalog, many registries; the catalog is the contract

Related Skills

  • ork:json-render-catalog — Catalog definition patterns with Zod, shadcn components
  • ork:demo-producer — Video production pipeline using Remotion
  • ork:mcp-visual-output — Rendering specs in Claude/Cursor via MCP

Frequently asked questions

What to verify before installation and use

What does the multi-surface-render source document cover?

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.

How do I install multi-surface-render?

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.

Which Agent platforms does the source record declare?

The pinned source record declares support for: claude code.

Alternatives

Compare before choosing

Computed 96223

yonatangross/orchestkit

json-render-catalog

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.

Computed 96223

yonatangross/orchestkit

react-server-components-framework

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.

Computed 9180

vasilyu1983/AI-Agents-public

software-localisation

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.

Computed 961,101

fcakyon/claude-codex-settings

vercel-react-view-transitions

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