PluginBench
Skill
Official
Pass
Audit score 90

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
Prerequisites
  • React Native project setup
  • @json-render/core and @json-render/react-native packages installed
  • Zod for schema validation (used in examples)
Claude Code
Cursor
Windsurf
Cline

How to use react-native

  1. 1.Install @json-render/react-native and @json-render/core packages
  2. 2.Define a catalog with standardComponentDefinitions and any custom components using defineCatalog
  3. 3.Create a type-safe registry with defineRegistry, registering custom component implementations
  4. 4.Wrap your app with StateProvider, VisibilityProvider, and ActionProvider
  5. 5.Pass a JSON spec and registry to the Renderer component to render the mobile UI
  6. 6.Use $state, $bindState, and visibility conditions in your JSON specs for dynamic behavior

Use cases

Good for
  • 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
Who it's for
  • 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

How do I add custom components beyond the standard set?

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.

How do I bind form inputs to state?

Use { "$bindState": "/path/to/field" } on the natural value prop (value, checked, etc.) of form components like TextInput or Switch for two-way binding.

How do I handle user interactions and actions?

Use Pressable components with the built-in setState action, or define custom actions in the catalog and provide handlers via ActionProvider.

Can I use external state management?

Yes, pass a StateStore to StateProvider for controlled mode, allowing integration with Redux, Zustand, or other state management libraries.

How do I conditionally show/hide elements?

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 radius
  • Row - horizontal flex layout with gap, alignment
  • Column - vertical flex layout with gap, alignment
  • ScrollContainer - scrollable area (vertical or horizontal)
  • SafeArea - safe area insets for notch/home indicator
  • Pressable - touchable wrapper that triggers actions on press
  • Spacer - fixed or flexible spacing
  • Divider - thin line separator

Content

  • Heading - heading text (levels 1-6)
  • Paragraph - body text
  • Label - small label text
  • Image - image display with sizing modes
  • Avatar - circular avatar image
  • Badge - small status badge
  • Chip - tag/chip for categories

Input

  • Button - pressable button with variants
  • TextInput - text input field
  • Switch - toggle switch
  • Checkbox - checkbox with label
  • Slider - range slider
  • SearchBar - search input

Feedback

  • Spinner - loading indicator
  • ProgressBar - progress indicator

Composite

  • Card - card container with optional header
  • ListItem - list row with title, subtitle, accessory
  • Modal - 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

ProviderPurpose
StateProviderShare state across components (JSON Pointer paths). Accepts optional store prop for controlled mode.
ActionProviderHandle actions dispatched from components
VisibilityProviderEnable conditional rendering based on state
ValidationProviderForm 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

ExportPurpose
defineRegistryCreate a type-safe component registry from a catalog
RendererRender a spec using a registry
schemaReact Native element tree schema
standardComponentDefinitionsCatalog definitions for all standard components
standardActionDefinitionsCatalog definitions for standard actions
standardComponentsPre-built component implementations
createStandardActionHandlersCreate handlers for standard actions
useStateStoreAccess state context
useStateValueGet single value from state
useBoundPropTwo-way state binding via $bindState/$bindItem
useStateBinding(deprecated) Legacy two-way binding by path
useActionsAccess actions context
useActionGet a single action dispatch function
useUIStreamStream specs from an API endpoint
createStateStoreCreate a framework-agnostic in-memory StateStore
StateStoreInterface for plugging in external state management