Back to list
oaustegard

json-render-ui

by oaustegard

My collection of Claude skills

30🍴 2📅 Jan 24, 2026

SKILL.md


name: json-render-ui description: 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 metadata: version: 0.0.1

JSON 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

ComponentPropsChildrenDescription
Cardtitle?, description?, padding?: sm|md|lgYesContainer with optional header
Gridcolumns?: 1-4, gap?: sm|md|lgYesCSS grid layout
Stackdirection?: horizontal|vertical, gap?: sm|md|lg, align?: start|center|end|stretchYesFlexbox stack

Data Display

ComponentPropsChildrenDescription
Metriclabel, valuePath, format?: number|currency|percent, trend?: up|down|neutral, trendValue?NoSingle KPI display
Charttype: bar|line|pie|area, dataPath, title?, height?NoData visualization
TabledataPath, columns: [{key, label, format?: text|currency|date|badge}]NoTabular data
ListdataPath, emptyMessage?YesRendered list from array

Interactive

ComponentPropsChildrenDescription
Buttonlabel, action, variant?: primary|secondary|danger|ghost, size?: sm|md|lg, disabled?NoClickable action
Selectlabel?, bindPath, options: [{value, label}], placeholder?NoDropdown select
DatePickerlabel?, bindPath, placeholder?NoDate input

Typography

ComponentPropsChildrenDescription
Headingtext, level?: h1|h2|h3|h4NoSection heading
Textcontent, variant?: body|caption|label, color?: default|muted|success|warning|dangerNoText paragraph

Status

ComponentPropsChildrenDescription
Badgetext, variant?: default|success|warning|danger|infoNoStatus indicator
Alerttype: info|success|warning|error, title, message?, dismissible?NoNotification banner

Special

ComponentPropsChildrenDescription
Dividerlabel?NoVisual separator
Emptytitle, description?, action?, actionLabel?NoEmpty 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 / false — Static
  • { "path": "/some/path" } — Truthy check
  • { "and": [...] } — All conditions true
  • { "or": [...] } — Any condition true
  • { "not": {...} } — Negation
  • { "eq": [a, b] } — Equality

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:

  1. Embeds the UITree JSON
  2. Imports the renderer from assets/renderer.js (inline it)
  3. 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

  • assets/template.html — Complete artifact template with embedded renderer
  • assets/catalog.json — Machine-readable component schemas
  • references/uitree-format.md — Detailed UITree specification

Score

Total Score

65/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon