All skills
oaustegard avatar

/json-render-ui

@4b31e7d

Generate guardrailed UI from natural language. Emits constrained JSON that a Preact runtime renders. Use when the request is for a dashboard with metrics, charts, or tables; an admin panel; a data visualization interface; or a form-based application.

Use this Skill: https://skilld.dev/gh/oaustegard/claude-skills/json-render-ui

This session only. Nothing lands on disk.

SKILL.md

β‰ˆ67 tokens always: the name and description. β‰ˆ1.9k when used: this file. β‰ˆ2.9k more on demand in 3 files.

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

Component Props Children Description
Card title?, description?, padding?: sm|md|lg Yes Container with optional header
Grid columns?: 1-4, gap?: sm|md|lg Yes CSS grid layout
Stack direction?: horizontal|vertical, gap?: sm|md|lg, align?: start|center|end|stretch Yes Flexbox stack

Data Display

Component Props Children Description
Metric label, valuePath, format?: number|currency|percent, trend?: up|down|neutral, trendValue? No Single KPI display
Chart type: bar|line|pie|area, dataPath, title?, height? No Data visualization
Table dataPath, columns: [{key, label, format?: text|currency|date|badge}] No Tabular data
List dataPath, emptyMessage? Yes Rendered list from array

Interactive

Component Props Children Description
Button label, action, variant?: primary|secondary|danger|ghost, size?: sm|md|lg, disabled? No Clickable action
Select label?, bindPath, options: [{value, label}], placeholder? No Dropdown select
DatePicker label?, bindPath, placeholder? No Date input

Typography

Component Props Children Description
Heading text, level?: h1|h2|h3|h4 No Section heading
Text content, variant?: body|caption|label, color?: default|muted|success|warning|danger No Text paragraph

Status

Component Props Children Description
Badge text, variant?: default|success|warning|danger|info No Status indicator
Alert type: info|success|warning|error, title, message?, dismissible? No Notification banner

Special

Component Props Children Description
Divider label? No Visual separator
Empty title, description?, action?, actionLabel? No Empty state

Data Binding

Props ending in Path (e.g., valuePath, dataPath, bindPath) reference the data model using JSON Pointer syntax:

  • /revenue β†’ data.revenue
  • /users/0/name β†’ data.users[0].name
  • /filters/dateRange β†’ data.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. Renders the UI

Start from assets/template.html, which already carries the embedded renderer β€” there is no separate renderer.js to inline.

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

Source: SKILL.md on GitHub

1 warning2mo3 checks Β· Risk SAFE
  • Gen Agent Trust Hub2mo

    This skill provides a framework for generating interactive UI dashboards from natural language. It works by converting user requests into a constrained JSON structure which is then rendered by a safe, Preact-based runtime inside an HTML artifact. The design prioritizes security by using a strict component catalog and leveraging well-known CDN services for its frontend dependencies.

  • Socket2mo

    No alerts

  • Snyk2mo

    Risk: MEDIUM Β· 1 issue

Signed by skilld at 4b31e7d. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 2 months ago
metadata
{
  "version": "0.0.2"
}

README badge

README badge for oaustegard/claude-skills/json-render-ui