react-native
vercel-labs/json-render
React Native renderer that converts JSON specs into native mobile UIs with standard components and data binding.
What is react-native?
@json-render/react-native turns JSON specifications into native mobile component trees for React Native apps. Use it when building UIs from JSON specs, creating mobile component catalogs, rendering AI-generated mobile designs, or implementing data-driven mobile interfaces.
- Renders JSON specs as native React Native component trees with layout, content, input, and feedback components
- Supports data binding and state management via JSON Pointer expressions ($state, $bindState, $bindItem)
- Provides visibility conditions to conditionally render elements based on state
- Includes built-in actions like setState for interactive UIs without custom handlers
- Offers a type-safe component registry system for extending with custom components
- Supports external state stores for integration with existing state management
How to install react-native
npx skills add https://github.com/vercel-labs/json-render --skill react-native- React Native project setup
- @json-render/core and @json-render/react-native packages installed
- Zod for schema validation (used in examples)
How to use react-native
- 1.Install @json-render/react-native and @json-render/core packages
- 2.Define a catalog with standardComponentDefinitions and any custom components using defineCatalog
- 3.Create a type-safe registry with defineRegistry, registering custom component implementations
- 4.Wrap your app with StateProvider, VisibilityProvider, and ActionProvider
- 5.Pass a JSON spec and registry to the Renderer component to render the mobile UI
- 6.Use $state, $bindState, and visibility conditions in your JSON specs for dynamic behavior
Use cases
- Building dynamic mobile UIs from AI-generated JSON specifications
- Creating mobile component catalogs that render from JSON definitions
- Implementing data-driven forms with two-way state binding
- Building interactive mobile interfaces with conditional rendering and state-based actions
- Rendering mobile UI specs from API endpoints or design systems
- React Native developers building data-driven mobile apps
- Teams using AI agents to generate mobile UI specs
- Developers implementing design systems for mobile platforms
- Engineers building low-code or no-code mobile UI tools
react-native FAQ
Define custom components in the catalog using defineCatalog with Zod schemas for props, then register their implementations in defineRegistry. Standard components are built-in and don't need registration.
Use { "$bindState": "/path/to/field" } on the natural value prop (value, checked, etc.) of form components like TextInput or Switch for two-way binding.
Use Pressable components with the built-in setState action, or define custom actions in the catalog and provide handlers via ActionProvider.
Yes, pass a StateStore to StateProvider for controlled mode, allowing integration with Redux, Zustand, or other state management libraries.
Use the visible prop with conditions like { "$state": "/path" } or { "$state": "/path", "eq": value }, or use { "$cond", "$then", "$else" } for conditional prop values.
Full instructions (SKILL.md)
Source of truth, from vercel-labs/json-render.
name: react-native description: React Native renderer for json-render that turns JSON specs into native mobile UIs. Use when working with @json-render/react-native, building React Native UIs from JSON, creating mobile component catalogs, or rendering AI-generated specs on mobile.
@json-render/react-native
React Native renderer that converts JSON specs into native mobile component trees with standard components, data binding, visibility, actions, and dynamic props.
Quick Start
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/react-native/schema";
import {
standardComponentDefinitions,
standardActionDefinitions,
} from "@json-render/react-native/catalog";
import { defineRegistry, Renderer, type Components } from "@json-render/react-native";
import { z } from "zod";
// Create catalog with standard + custom components
const catalog = defineCatalog(schema, {
components: {
...standardComponentDefinitions,
Icon: {
props: z.object({ name: z.string(), size: z.number().nullable(), color: z.string().nullable() }),
slots: [],
description: "Icon display",
},
},
actions: standardActionDefinitions,
});
// Register only custom components (standard ones are built-in)
const { registry } = defineRegistry(catalog, {
components: {
Icon: ({ props }) => <Ionicons name={props.name} size={props.size ?? 24} />,
} as Components<typeof catalog>,
});
// Render
function App({ spec }) {
return (
<StateProvider initialState={{}}>
<VisibilityProvider>
<ActionProvider handlers={{}}>
<Renderer spec={spec} registry={registry} />
</ActionProvider>
</VisibilityProvider>
</StateProvider>
);
}
Standard Components
Layout
Container- wrapper with padding, background, border radiusRow- horizontal flex layout with gap, alignmentColumn- vertical flex layout with gap, alignmentScrollContainer- scrollable area (vertical or horizontal)SafeArea- safe area insets for notch/home indicatorPressable- touchable wrapper that triggers actions on pressSpacer- fixed or flexible spacingDivider- thin line separator
Content
Heading- heading text (levels 1-6)Paragraph- body textLabel- small label textImage- image display with sizing modesAvatar- circular avatar imageBadge- small status badgeChip- tag/chip for categories
Input
Button- pressable button with variantsTextInput- text input fieldSwitch- toggle switchCheckbox- checkbox with labelSlider- range sliderSearchBar- search input
Feedback
Spinner- loading indicatorProgressBar- progress indicator
Composite
Card- card container with optional headerListItem- list row with title, subtitle, accessoryModal- bottom sheet modal
Visibility Conditions
Use visible on elements. Syntax: { "$state": "/path" }, { "$state": "/path", "eq": value }, { "$state": "/path", "not": true }, [ cond1, cond2 ] for AND.
Pressable + setState Pattern
Use Pressable with the built-in setState action for interactive UIs like tab bars:
{
"type": "Pressable",
"props": {
"action": "setState",
"actionParams": { "statePath": "/activeTab", "value": "home" }
},
"children": ["home-icon", "home-label"]
}
Dynamic Prop Expressions
Any prop value can be a data-driven expression resolved at render time:
{ "$state": "/state/key" }- reads from state model (one-way read){ "$bindState": "/path" }- two-way binding: use on the natural value prop (value, checked, pressed, etc.) of form components.{ "$bindItem": "field" }- two-way binding to a repeat item field. Use inside repeat scopes.- Nested lists use
{ "repeat": { "statePath": { "$item": "comments" } } }inside an enclosing repeat. { "$cond": <condition>, "$then": <value>, "$else": <value> }- conditional value
{
"type": "TextInput",
"props": {
"value": { "$bindState": "/form/email" },
"placeholder": "Email"
}
}
Components do not use a statePath prop for two-way binding. Use { "$bindState": "/path" } on the natural value prop instead.
Built-in Actions
The setState action is handled automatically by ActionProvider and updates the state model directly, which re-evaluates visibility conditions and dynamic prop expressions:
{ "action": "setState", "actionParams": { "statePath": "/activeTab", "value": "home" } }
Providers
| Provider | Purpose |
|---|---|
StateProvider | Share state across components (JSON Pointer paths). Accepts optional store prop for controlled mode. |
ActionProvider | Handle actions dispatched from components |
VisibilityProvider | Enable conditional rendering based on state |
ValidationProvider | Form field validation |
External Store (Controlled Mode)
Pass a StateStore to StateProvider (or JSONUIProvider / createRenderer) to use external state management:
import { createStateStore, type StateStore } from "@json-render/react-native";
const store = createStateStore({ count: 0 });
<StateProvider store={store}>{children}</StateProvider>
store.set("/count", 1); // React re-renders automatically
When store is provided, initialState and onStateChange are ignored.
Key Exports
| Export | Purpose |
|---|---|
defineRegistry | Create a type-safe component registry from a catalog |
Renderer | Render a spec using a registry |
schema | React Native element tree schema |
standardComponentDefinitions | Catalog definitions for all standard components |
standardActionDefinitions | Catalog definitions for standard actions |
standardComponents | Pre-built component implementations |
createStandardActionHandlers | Create handlers for standard actions |
useStateStore | Access state context |
useStateValue | Get single value from state |
useBoundProp | Two-way state binding via $bindState/$bindItem |
useStateBinding | (deprecated) Legacy two-way binding by path |
useActions | Access actions context |
useAction | Get a single action dispatch function |
useUIStream | Stream specs from an API endpoint |
createStateStore | Create a framework-agnostic in-memory StateStore |
StateStore | Interface for plugging in external state management |
Related skills
More from vercel-labs/json-render and the wider catalog.

react-pdf
Render PDF documents from JSON specs using React components.

react-three-fiber
Render interactive 3D scenes from JSON specs using React Three Fiber and Three.js

redux
Redux adapter for json-render's StateStore interface. Use when integrating json-render with Redux or Redux Toolkit for state management via @json-render/redux.

remotion
Convert JSON timeline specs into videos using Remotion compositions.

remotion-best-practices
Domain-specific best practices and patterns for building videos with Remotion and React.

shadcn
36 pre-built shadcn/ui components for json-render with Radix UI + Tailwind CSS.