Skip to main content
skill Claude Code CX Codex Cursor GitHub Copilot

solid — Claude Code skill: render SolidJS UI from JSON specs

Skill to render JSON-specs into reactive SolidJS components. Use it when building UI catalogs, wiring providers, or debugging Solid reactivity patterns.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add vercel-labs/json-render --skill solid -a claude-code
Open on GitHub

What solid does

@json-render/solid transforms JSON descriptions into live Solid components with fine-grained reactivity. Wrap your app in JSONUIProvider, pass a spec and registry, and the skill handles state bindings, element visibility, form validation, and actions.

Four providers do the heavy lifting: StateProvider syncs state, VisibilityProvider evaluates conditions, ValidationProvider checks fields, ActionProvider runs built-in and custom logic. Components receive emit for events and useBoundProp for two-way bindings. Specs support templates, computed values, conditionals, and repeats via repeat.statePath.

The skill enforces Solid reactivity rules: do not destructure props in function signatures if they change; keep reactive reads inside JSX, createMemo, or createEffect. For streaming UI generation, use useUIStream or useChatUI.

What it helps with

  • render UI from JSON specs into a SolidJS app
  • bind component state to JSON bindings
  • validate forms and sync state across the tree
  • handle component events and run custom actions
  • stream generated UI from an API

Example prompts for the agent

  • Build a catalog with `defineCatalog`, register components in `defineRegistry`, wrap it in `JSONUIProvider`
  • Write a component, use `useBoundProp` to bind input values to state
  • Set up `useUIStream` and send a prompt; the API generates a spec, `Renderer` displays it

How to install solid

1Skills CLI (Vercel)

npx skills add vercel-labs/json-render --skill solid -a claude-code

2Manually: put the files in place

~/.claude/skills/solid/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/solid/

From the same set20

The whole set →
react vercel-labs This skill turns json-render JSON specs into React component trees. Use it when building JSON-driven UIs or defining a component catalog for generated specs. Claude Code CX Codex Cursor +1 16,300installs core vercel-labs Defines the schema and component catalog for json-render and builds the system prompt that makes an AI emit JSON UI specs. Claude Code CX Codex Cursor +1 15,000installs codegen vercel-labs Utilities for generating code from json-render UI trees. Build custom code exporters for Next.js, Remix, and other frameworks, traverse specs, and serialize props. Claude Code CX Codex Cursor +1 8,900installs next vercel-labs Converts JSON specs into Next.js apps with routes, layouts, SSR, and metadata. Handy when building AI-generated multi-page apps with @json-render/next. Claude Code CX Codex Cursor +1 8,600installs devtools vercel-labs Debug panel for json-render apps: component tree, state editor, actions log, streaming patches, and element picker. Claude Code CX Codex Cursor +1 8,300installs directives vercel-labs Pre-built directives for json-render: formatting, math, string handling, i18n. Wire them into your catalog and renderer with one import. Claude Code CX Codex Cursor +1 8,000installs mcp vercel-labs This skill helps build MCP servers that render interactive json-render UIs in Claude, ChatGPT, Cursor, and VS Code. Claude Code CX Codex Cursor +1 5,800installs react-native vercel-labs This skill turns JSON specs into native React Native mobile UIs. Use it when screens need state bindings, conditional visibility, and actions. Claude Code CX Codex Cursor +1 3,200installs

Similar

libraries-dev Jakubantalik Selects and integrates Libraries.dev React UI effects for AI interfaces, covering loaders, voice glows, animated borders, and bot avatars. Claude Code CX Codex Cursor +1 991installs wp-block-themes WordPress Guides the agent through building WordPress block themes, editing theme.json, and organizing templates. Useful when styles fail to apply in the Site Editor. Claude Code CX Codex Cursor +1 5,800installs godot-ui-control gamedev-skills A Claude Code skill that teaches the agent to lay out Godot 4.7 HUDs and menus with Control nodes: anchors, containers, themes and focus. Claude Code CX Codex Cursor +1 6,400installs salesforce-component-standards official github Guides Salesforce UI development across LWC, Aura, and Visualforce. Enforces SLDS 2 compliance, accessibility, and platform security. GitHub Copilot 770installs react18-dep-compatibility official github Checks minimum dependency versions for React 18.3.1 and React 19. Use it during React upgrades and when resolving peer dependency conflicts. GitHub Copilot 764installs react-19 prowler-cloud Skill for React 19 with React Compiler: no manual memoization, server components first, ref as a prop. Claude Code CX Codex Cursor +1 671installs frontend-design official anthropics This skill guides intentional visual design for new interfaces and redesigns. Use it when a generic generated UI is not enough. Claude Code Claude.ai 1,025,790installs design-taste-frontend Leonxlnx This skill directs the design of public pages and work screens, then checks the result in a browser through screenshots. Use it when an interface feels generic or unfinished. Claude Code CX Codex Cursor +1 673,100installs

Questions about solid

How do I install solid in Claude Code?

Run npx skills add vercel-labs/json-render --skill solid -a claude-code, then check ~/.claude/skills/solid/SKILL.md.

What does solid do?

The skill renders JSON-described UIs into reactive SolidJS components, automatically syncing state, visibility, validation, and event handling.

How do I make a two-way binding for form inputs?

Use useBoundProp(props.props.value, props.bindings?.value) — it returns the current value and a write function. Read the value inside JSX to keep it reactive.

Source text

SKILL.md · Apache-2.0
---
name: solid
description: SolidJS renderer for json-render. Use when building @json-render/solid catalogs/registries, wiring Renderer providers, implementing bindings/actions, or troubleshooting Solid-specific reactivity patterns.
---

# @json-render/solid

`@json-render/solid` renders json-render specs into Solid component trees with fine-grained reactivity.

## Quick Start

```tsx
import { Renderer, JSONUIProvider } from "@json-render/solid";
import type { Spec } from "@json-render/solid";
import { registry } from "./registry";

export function App(props: { spec: Spec | null }) {
  return (
    <JSONUIProvider registry={registry} initialState={{}}>
      <Renderer spec={props.spec} registry={registry} />
    </JSONUIProvider>
  );
}
```

## Create a Catalog

```typescript
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/solid/schema";
import { z } from "zod";

export const catalog = defineCatalog(schema, {
  components: {
    Button: {
      props: z.object({
        label: z.string(),
        variant: z.enum(["primary", "secondary"]).nullable(),
      }),
      description: "Clickable button",
    },
    Card: {
      props: z.object({ title: z.string() }),
      description: "Card container",
    },
  },
  actions: {
    submit: { description: "Submit data" },
  },
});
```

## Define Components

Components receive `ComponentRenderProps` from the renderer:

```ts
interface ComponentRenderProps<P = Record<string, unknown>> {
  element: UIElement<string, P>;
  children?: JSX.Element;
  emit: (event: string) => void;
  on: (event: string) => EventHandle;
  bindings?: Record<string, string>;
  loading?: boolean;
}
```

Example:

```tsx
import type { BaseComponentProps } from "@json-render/solid";

export function Button(props: BaseComponentProps<{ label: string }>) {
  return (
    <button onClick={() => props.emit("press")}>{props.props.label}</button>
  );
}
```

## Create a Registry

```typescript
import { defineRegistry } from "@json-render/solid";
import { catalog } from "./catalog";
import { Card } from "./Card";
import { Button } from "./Button";

const { registry, handlers, executeAction } = defineRegistry(catalog, {
  components: {
    Card,
    Button,
  },
  actions: {
    submit: async (params, setState, state) => {
      // custom action logic
    },
  },
});
```

## Spec Structure

```json
{
  "root": "card1",
  "elements": {
    "card1": {
      "type": "Card",
      "props": { "title": "Hello" },
      "children": ["btn1"]
    },
    "btn1": {
      "type": "Button",
      "props": { "label": "Click me" },
      "on": {
        "press": { "action": "submit" }
      }
    }
  }
}
```

## Providers

- `StateProvider`: state model read/write and controlled mode via `store`
- `VisibilityProvider`: evaluates `visible` conditions
- `ValidationProvider`: field validation + `validateForm` integration
- `ActionProvider`: runs built-in and custom actions
- `JSONUIProvider`: combined provider wrapper

## Hooks

- `useStateStore`, `useStateValue`, `useStateBinding`
- `useVisibility`, `useIsVisible`
- `useActions`, `useAction`
- `useValidation`, `useOptionalValidation`, `useFieldValidation`
- `useBoundProp`
- `useUIStream`, `useChatUI`

## Built-in Actions

Handled automatically by `ActionProvider`:

- `setState`
- `pushState`
- `removeState`
- `validateForm`

## Dynamic Props and Bindings

Nested lists can set `repeat.statePath` to `{ "$item": "field" }` inside an enclosing repeat.

Supported expression forms include:

- `{"$state": "/path"}`
- `{"$bindState": "/path"}`
- `{"$bindItem": "field"}`
- `{"$template": "Hi ${/user/name}"}`
- `{"$computed": "fn", "args": {...}}`
- `{"$cond": <condition>, "$then": <value>, "$else": <value>}`

Use `useBoundProp` in components for writable bound values:

```tsx
import { useBoundProp, type BaseComponentProps } from "@json-render/solid";

function Input(props: BaseComponentProps<{ value?: string }>) {
  const [, setValue] = useBoundProp(props.props.value, props.bindings?.value);
  return (
    <input
      value={String(props.props.value ?? "")}
      onInput={(e) => setValue(e.currentTarget.value)}
    />
  );
}
```

`useBoundProp` returns a scalar value and a write-back setter. Read the resolved prop inside JSX so later state updates remain reactive.

`useStateValue`, `useStateBinding`, and the `state` / `errors` / `isValid` fields from `useFieldValidation` are reactive accessors in Solid. Call them as functions inside JSX, `createMemo`, or `createEffect`.

## Solid Reactivity Rules

- Do not destructure component props in function signatures when values need to stay reactive.
- Keep changing reads inside JSX expressions, `createMemo`, or `createEffect`.
- Context values are exposed through getter-based objects so consumers always observe live signals.

## Streaming UI

```tsx
import { useUIStream, Renderer } from "@json-render/solid";

const stream = useUIStream({ api: "/api/generate-ui" });
await stream.send("Create a support dashboard");

<Renderer
  spec={stream.spec}
  registry={registry}
  loading={stream.isStreaming}
/>;
```

Use `useChatUI` for chat + UI generation flows.

© vercel-labs · Apache-2.0 · vercel-labs/json-render

See also

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor