
Solid JSON Renderer
OfficialFreeRender JSON specs into Solid component trees with reactivity.
Free · Opens the source repo
What Solid JSON Renderer does
The Solid JSON Renderer is a tool designed for developers building applications with SolidJS that require dynamic rendering of JSON specifications. By utilizing the @json-render/solid library, it enables the creation of component trees that are responsive to changes in state and props, leveraging Solid's fine-grained reactivity model. This renderer is particularly useful when integrating with JSON-based UI definitions, allowing developers to define components and their behaviors in a structured manner.
With the ability to define catalogs and registries, developers can create reusable components that adhere to specific schemas, ensuring consistency across applications. The library provides a straightforward API for defining components, actions, and their interactions, making it easier to manage complex UIs. The integration of various providers, such as StateProvider and ValidationProvider, enhances the functionality by allowing state management and validation to be seamlessly incorporated into the rendering process.
For those working with SolidJS, this skill is a valuable addition to their toolkit, especially when building applications that require dynamic UI generation based on JSON data. It simplifies the process of connecting UI elements with underlying data models, enabling developers to focus on building features rather than managing boilerplate code. The built-in hooks and dynamic props support further enhance the developer experience by providing reactive access to state and validation logic.
Overall, the Solid JSON Renderer is ideal for developers looking to implement JSON-driven UIs in SolidJS applications, providing a robust framework for building interactive and reactive user interfaces.
When to use it
Use this skill when developing applications that require rendering of UI components based on JSON data structures, especially in SolidJS environments.
When not to use it
This skill may not be suitable for applications that do not utilize SolidJS or do not require dynamic JSON-based rendering.
What you can build with it
Building a Dynamic Form
Create a form that adapts its fields based on user input by rendering components defined in a JSON schema.
Creating a Reusable Component Library
Define a catalog of UI components that can be reused across different parts of an application, ensuring consistency.
Integrating with APIs
Render UI components based on data fetched from APIs, allowing for real-time updates and interactions.
How to install Solid JSON Renderer
View source1. Install with the skills CLI
npx skills add vercel-labs/json-render/solid --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by vercel-labs@json-render/solid
@json-render/solid renders json-render specs into Solid component trees with fine-grained reactivity.
Quick Start
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
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:
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:
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
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
{
"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 viastoreVisibilityProvider: evaluatesvisibleconditionsValidationProvider: field validation +validateFormintegrationActionProvider: runs built-in and custom actionsJSONUIProvider: combined provider wrapper
Hooks
useStateStore,useStateValue,useStateBindinguseVisibility,useIsVisibleuseActions,useActionuseValidation,useOptionalValidation,useFieldValidationuseBoundPropuseUIStream,useChatUI
Built-in Actions
Handled automatically by ActionProvider:
setStatepushStateremoveStatevalidateForm
Dynamic Props and Bindings
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:
import { useBoundProp } from "@json-render/solid";
function Input(props: BaseComponentProps<{ value?: string }>) {
const [value, setValue] = useBoundProp(
props.props.value,
props.bindings?.value,
);
return (
<input
value={String(value() ?? "")}
onInput={(e) => setValue(e.currentTarget.value)}
/>
);
}
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, orcreateEffect. - Context values are exposed through getter-based objects so consumers always observe live signals.
Streaming UI
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.
Frequently asked questions about Solid JSON Renderer
Similar skills
Playwright Component Testing
Test React and Vue components in isolation with Playwright.
Fluent UI Blazor
Integrate Fluent UI components in Blazor applications effortlessly.
Build MCP App
Create interactive UI widgets for MCP servers.
Web Design Reviewer
Identify and fix design issues in websites efficiently.
Markstream Install
Seamlessly integrate Markstream for Markdown rendering.
GSAP & Framer Scroll Animation
Create advanced scroll animations effortlessly.
