Claude-skill-registry json-render-ui
Generate guardrailed UI from natural language. Claude emits constrained JSON, skill runtime renders via Preact. Use when user provides json and requests: Dashboards with metrics, charts, tables; Admin panels; Data visualization interfaces; Form-based applications
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/json-render-ui" ~/.claude/skills/majiayu000-claude-skill-registry-json-render-ui && rm -rf "$T"
skills/data/json-render-ui/SKILL.mdJSON Render UI
Overview
Transform natural language UI requests into working dashboards and applications. Claude acts as the translation layer (prompt → JSON), the skill provides the rendering runtime (JSON → UI).
Architecture:
User prompt → Claude (constrained by catalog) → UITree JSON → Preact renderer → UI
Output Format
Claude emits a UITree structure:
{ "root": "main", "elements": { "main": { "key": "main", "type": "Grid", "props": { "columns": 2, "gap": "md" }, "children": ["metric1", "metric2"] }, "metric1": { "key": "metric1", "type": "Metric", "props": { "label": "Revenue", "valuePath": "/revenue", "format": "currency" } }, "metric2": { "key": "metric2", "type": "Metric", "props": { "label": "Growth", "valuePath": "/growth", "format": "percent" } } }, "data": { "revenue": 125000, "growth": 0.15 } }
Component Catalog
Claude can ONLY use these components. This is the guardrail.
Layout Components
| Component | Props | Children | Description |
|---|---|---|---|
| , , | Yes | Container with optional header |
| , | Yes | CSS grid layout |
| , , | Yes | Flexbox stack |
Data Display
| Component | Props | Children | Description |
|---|---|---|---|
| , , , , | No | Single KPI display |
| , , , | No | Data visualization |
| , | No | Tabular data |
| , | Yes | Rendered list from array |
Interactive
| Component | Props | Children | Description |
|---|---|---|---|
| , , , , | No | Clickable action |
| , , , | No | Dropdown select |
| , , | No | Date input |
Typography
| Component | Props | Children | Description |
|---|---|---|---|
| , | No | Section heading |
| , , | No | Text paragraph |
Status
| Component | Props | Children | Description |
|---|---|---|---|
| , | No | Status indicator |
| , , , | No | Notification banner |
Special
| Component | Props | Children | Description |
|---|---|---|---|
| | No | Visual separator |
| , , , | No | Empty state |
Data Binding
Props ending in
Path (e.g., valuePath, dataPath, bindPath) reference the data model using JSON Pointer syntax:
→/revenuedata.revenue
→/users/0/namedata.users[0].name
→/filters/dateRangedata.filters.dateRange
Visibility Conditions
Any element can have a
visible property:
{ "type": "Alert", "props": { "type": "error", "title": "Error" }, "visible": { "path": "/hasError" } }
Visibility expressions:
/true
— Staticfalse
— Truthy check{ "path": "/some/path" }
— All conditions true{ "and": [...] }
— Any condition true{ "or": [...] }
— Negation{ "not": {...} }
— Equality{ "eq": [a, b] }
Generating Output
Step 1: Emit UITree JSON
Analyze the user's request and emit a UITree structure. Include sample data that matches the schema.
Step 2: Create Artifact
Create an HTML artifact that:
- Embeds the UITree JSON
- Imports the renderer from
(inline it)assets/renderer.js - Renders the UI
Use the template in
assets/template.html.
Constraints
DO:
- Use only catalog components
- Provide realistic sample data
- Use semantic component choices (Metric for KPIs, Table for tabular data)
- Keep trees flat (no deep nesting beyond 3 levels)
DO NOT:
- Invent new component types
- Use arbitrary HTML/CSS
- Omit required props
- Create deeply nested structures
Example
User: "Create a sales dashboard with revenue, orders, and a chart showing monthly trends"
Claude outputs:
{ "root": "dashboard", "elements": { "dashboard": { "key": "dashboard", "type": "Stack", "props": { "direction": "vertical", "gap": "lg" }, "children": ["header", "metrics", "chartCard"] }, "header": { "key": "header", "type": "Heading", "props": { "text": "Sales Dashboard", "level": "h1" } }, "metrics": { "key": "metrics", "type": "Grid", "props": { "columns": 3, "gap": "md" }, "children": ["revenue", "orders", "avgOrder"] }, "revenue": { "key": "revenue", "type": "Card", "props": { "padding": "md" }, "children": ["revenueMetric"] }, "revenueMetric": { "key": "revenueMetric", "type": "Metric", "props": { "label": "Total Revenue", "valuePath": "/revenue", "format": "currency", "trend": "up", "trendValue": "12%" } }, "orders": { "key": "orders", "type": "Card", "props": { "padding": "md" }, "children": ["ordersMetric"] }, "ordersMetric": { "key": "ordersMetric", "type": "Metric", "props": { "label": "Orders", "valuePath": "/orders", "format": "number" } }, "avgOrder": { "key": "avgOrder", "type": "Card", "props": { "padding": "md" }, "children": ["avgMetric"] }, "avgMetric": { "key": "avgMetric", "type": "Metric", "props": { "label": "Avg Order Value", "valuePath": "/avgOrderValue", "format": "currency" } }, "chartCard": { "key": "chartCard", "type": "Card", "props": { "title": "Monthly Trends", "padding": "md" }, "children": ["chart"] }, "chart": { "key": "chart", "type": "Chart", "props": { "type": "line", "dataPath": "/monthlyData", "height": 300 } } }, "data": { "revenue": 284500, "orders": 1247, "avgOrderValue": 228, "monthlyData": [ { "month": "Jan", "value": 18000 }, { "month": "Feb", "value": 22000 }, { "month": "Mar", "value": 28000 }, { "month": "Apr", "value": 24000 }, { "month": "May", "value": 32000 } ] } }
Then wrap in the artifact template from
assets/template.html.
Files
— Complete artifact template with embedded rendererassets/template.html
— Machine-readable component schemasassets/catalog.json
— Detailed UITree specificationreferences/uitree-format.md