react-native — Claude Code skill: what it does, how to install
This skill turns JSON specs into native React Native mobile UIs. Use it when screens need state bindings, conditional visibility, and actions.
npx skills add vercel-labs/json-render --skill react-native -a claude-codeWhat react-native does
The skill covers the @json-render/react-native renderer, which converts a JSON specification into a tree of native mobile components. Its catalog includes layout, content, input, feedback, and composite components such as Card, ListItem, and Modal.
Rendering is organized around StateProvider, VisibilityProvider, and ActionProvider. Specs can read values with $state, bind form fields with $bindState, and compute conditional props with $cond. The built-in setState action updates the state model, which causes visibility rules and dynamic props to be evaluated again.
You can extend the catalog with defineCatalog, defineRegistry, and custom components whose props use zod schemas. The renderer depends on @json-render/react-native, so check that package before wiring the skill into a project.
What it helps with
- build a mobile UI from a JSON spec
- bind form fields to state with
$bindState - show components according to state conditions
- add custom components to a catalog
- handle presses with the
setStateaction
Example prompts for the agent
- Build a React Native screen from a JSON spec with `Column`, `TextInput`, and `Button`, binding the email field with `$bindState`.
- Add an `Icon` component with `name`, `size`, and `color` props, then register it with `defineRegistry`.
- Show a `Modal` when a `$state` condition matches and close it with `setState`.
How to install react-native
1Skills CLI (Vercel)
npx skills add vercel-labs/json-render --skill react-native -a claude-code2Manually: put the files in place
~/.claude/skills/react-native/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/react-native/
1Skills CLI (Vercel)
npx skills add vercel-labs/json-render --skill react-native -a codex2Manually: put the files in place
.agents/skills/react-native/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add vercel-labs/json-render --skill react-native -a cursor2Manually: put the files in place
.cursor/skills/react-native/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install vercel-labs/json-render react-native2Manually: put the files in place
.github/skills/react-native/SKILL.md1Skills CLI (Vercel)
npx skills add vercel-labs/json-render --skill react-native -a gemini-cli2Platform CLI
gemini skills install https://github.com/vercel-labs/json-render --path skills/react-nativeManually: put the files in place
.devin/skills/react-native/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add vercel-labs/json-render --skill react-native -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
From the same set20
The whole set →Similar
Questions about react-native
How do I install react-native in Claude Code?
Run npx skills add vercel-labs/json-render --skill react-native -a claude-code, then run npx skills add vercel-labs/json-render --skill react-native -a claude-code again. The skill file is at ~/.claude/skills/react-native/SKILL.md.
What does the react-native skill do?
It helps render JSON specifications as native React Native components. The skill covers standard components, state, bindings, visibility conditions, and actions.
How do I bind a form field to state?
Put $bindState on the component's natural value prop, such as value on TextInput. Set the state path with a value like { "$bindState": "/form/email" }.
Source text
SKILL.md · Apache-2.0
---
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
```typescript
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:
```json
{
"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
```json
{
"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:
```json
{ "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:
```tsx
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 |
© vercel-labs · Apache-2.0 · vercel-labs/json-render