mcpbeat Sign in

Generative UI Skill for Claude

> Design system and guidelines for Claude's built-in generative UI — the show_widget tool that renders interactive HTML/SVG widgets inline in claude.ai conversations. This skill provides the complete Anthropic "Imagine" design system so Claude produces high-quality widgets without needing to call read_me first. Use this skill whenever the user asks to visualize data, create an interactive chart, build a dashboard, render a diagram, draw a flowchart, show a mockup, create an interactive explainer, "draw", "chart", "dashboard", "diagram", "flowchart", "widget", "interactive", "mockup", "illustrate", "explain how X works" (with visual), or any request for visual/interactive output. Also triggers when the user wants to display financial data visually, create comparison grids, or build tools with sliders, toggles, or live-updating displays.

9k tokens
context cost
the whole folder, loaded on every use
5
files
instructions only
0
copies elsewhere
how many repositories repackaged it
3109
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/himself65/finance-skills --skill generative-ui

The instruction itself

15 sections, as written by the author

Generative UI Skill

This skill contains the complete design system for Claude's built-in show_widget tool — the generative UI feature that renders interactive HTML/SVG widgets inline in claude.ai conversations. The guidelines below are the actual Anthropic "Imagine — Visual Creation Suite" design rules, extracted so you can produce high-quality widgets directly without needing the read_me setup call.

How it works: On claude.ai, Claude has access to the show_widget tool which renders raw HTML/SVG fragments inline in the conversation. This skill provides the design system, templates, and patterns to use it well.


Step 1: Pick the Right Visual Type

Route on the verb, not the noun. Same subject, different visual depending on what was asked:

| User says | Type | Format |

|---|---|---|

| "how does X work" | Illustrative diagram | SVG |

| "X architecture" | Structural diagram | SVG |

| "what are the steps" | Flowchart | SVG |

| "explain compound interest" | Interactive explainer | HTML |

| "compare these options" | Comparison grid | HTML |

| "show revenue chart" | Chart.js chart | HTML |

| "create a contact card" | Data record | HTML |

| "draw a sunset" | Art/illustration | SVG |


Step 2: Build the Widget

Structure (strict order)

<style>  →  HTML content  →  <script>

Output streams token-by-token. Styles must exist before the elements they target, and scripts must run after the DOM is ready.

Philosophy

  • Seamless: Users shouldn't notice where the host UI ends and your widget begins
  • Flat: No gradients, mesh backgrounds, noise textures, or decorative effects. Clean flat surfaces
  • Compact: Show the essential inline. Explain the rest in text
  • Text goes in your response, visuals go in the tool — all explanatory text, descriptions, and summaries must be written as normal response text OUTSIDE the tool call. The tool output should contain ONLY the visual element

Core Rules

  • No <!-- comments --> or /* comments */ (waste tokens, break streaming)
  • No font-size below 11px
  • No emoji — use CSS shapes or SVG paths
  • No gradients, drop shadows, blur, glow, or neon effects
  • No dark/colored backgrounds on outer containers (transparent only — host provides the bg)
  • Typography: two weights only: 400 regular, 500 medium. Never use 600 or 700. Headings: h1=22px, h2=18px, h3=16px — all font-weight 500. Body text=16px, weight 400, line-height 1.7
  • Sentence case always. Never Title Case, never ALL CAPS
  • No mid-sentence bolding — entity names go in code style not bold
  • No <!DOCTYPE>, <html>, <head>, or <body> — just content fragments
  • No position: fixed — use normal-flow layouts
  • No tabs, carousels, or display: none sections during streaming
  • No nested scrolling — auto-fit height
  • Corners: border-radius: var(--border-radius-lg) for cards, var(--border-radius-md) for elements
  • No rounded corners on single-sided borders (border-left, border-top)
  • Round every displayed number — use Math.round(), .toFixed(n), or Intl.NumberFormat

CDN Allowlist (CSP-enforced)

External resources may ONLY load from:

  • cdnjs.cloudflare.com
  • cdn.jsdelivr.net
  • unpkg.com
  • esm.sh

All other origins are blocked — the request silently fails.

CSS Variables

Backgrounds: --color-background-primary (white), -secondary (surfaces), -tertiary (page bg), -info, -danger, -success, -warning

Text: --color-text-primary (black), -secondary (muted), -tertiary (hints), -info, -danger, -success, -warning

Borders: --color-border-tertiary (0.15α, default), -secondary (0.3α, hover), -primary (0.4α), semantic -info/-danger/-success/-warning

Typography: --font-sans, --font-serif, --font-mono

Layout: --border-radius-md (8px), --border-radius-lg (12px), --border-radius-xl (16px)

All auto-adapt to light/dark mode.

Dark mode is mandatory — every color must work in both modes:

  • In HTML: always use CSS variables for text. Never hardcode colors like color: #333
  • In SVG: use pre-built color classes (c-blue, c-teal, etc.) — they handle light/dark automatically
  • Mental test: if the background were near-black, would every text element still be readable?

sendPrompt(text)

A global function that sends a message to chat as if the user typed it. Use it when the user's next step benefits from Claude thinking. Handle filtering, sorting, toggling, and calculations in JS instead.


Step 3: Render with show_widget

The show_widget tool is built into claude.ai — no activation needed. Pass your widget code directly:

{
  "title": "snake_case_widget_name",
  "widget_code": "<style>...</style>\n<div>...</div>\n<script>...</script>"
}

| Parameter | Type | Required | Description |

|---|---|---|---|

| title | string | Yes | Snake_case identifier for the widget |

| widget_code | string | Yes | HTML or SVG code. For SVG: start with <svg>. For HTML: content fragment |

For SVG output: start widget_code with <svg — it will be auto-detected and wrapped appropriately.


Step 4: Chart.js Template

For charts, use onload callback pattern to handle script load ordering:

<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px;">
  <div style="background: var(--color-background-secondary); border-radius: var(--border-radius-md); padding: 1rem;">
    <div style="font-size: 13px; color: var(--color-text-secondary);">Label</div>
    <div style="font-size: 24px; font-weight: 500;" id="stat1">—</div>
  </div>
</div>

<div style="position: relative; width: 100%; height: 300px; margin-top: 1rem;">
  <canvas id="myChart"></canvas>
</div>

<div style="display: flex; align-items: center; gap: 12px; margin-top: 1rem;">
  <label style="font-size: 14px; color: var(--color-text-secondary);">Parameter</label>
  <input type="range" min="0" max="100" value="50" id="param" step="1" style="flex: 1;" />
  <span style="font-size: 14px; font-weight: 500; min-width: 32px;" id="param-out">50</span>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js" onload="initChart()"></script>
<script>
function initChart() {
  const slider = document.getElementById('param');
  const out = document.getElementById('param-out');
  let chart = null;

  function update() {
    const val = parseFloat(slider.value);
    out.textContent = val;
    document.getElementById('stat1').textContent = val.toFixed(1);

    const labels = [], data = [];
    for (let x = 0; x <= 100; x++) {
      labels.push(x);
      data.push(x * val / 100);
    }

    if (chart) chart.destroy();
    chart = new Chart(document.getElementById('myChart'), {
      type: 'line',
      data: { labels, datasets: [{ data, borderColor: '#7F77DD', borderWidth: 2, pointRadius: 0, fill: false }] },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        plugins: { legend: { display: false } },
        scales: { x: { grid: { display: false } } }
      }
    });
  }

  slider.addEventListener('input', update);
  update();
}
if (window.Chart) initChart();
</script>

Chart.js rules:

  • Canvas cannot resolve CSS variables — use hardcoded hex
  • Set height ONLY on the wrapper div, never on canvas itself
  • Always responsive: true, maintainAspectRatio: false
  • Always disable default legend, build custom HTML legends
  • Number formatting: -$5M not $-5M (negative sign before currency symbol)
  • Use onload="initChart()" on CDN script tag + if (window.Chart) initChart(); as fallback

Step 5: SVG Diagram Template

For flowcharts and diagrams, use SVG with pre-built classes:

<svg width="100%" viewBox="0 0 680 H">
  <defs>
    <marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
      <path d="M2 1L8 5L2 9" fill="none" stroke="context-stroke" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
    </marker>
  </defs>

  <!-- Single-line node (44px tall) -->
  <g class="node c-blue" onclick="sendPrompt('Tell me more about this')">
    <rect x="250" y="40" width="180" height="44" rx="8" stroke-width="0.5"/>
    <text class="th" x="340" y="62" text-anchor="middle" dominant-baseline="central">Step one</text>
  </g>

  <!-- Connector arrow -->
  <line x1="340" y1="84" x2="340" y2="120" class="arr" marker-end="url(#arrow)"/>

  <!-- Two-line node (56px tall) -->
  <g class="node c-teal" onclick="sendPrompt('Explain this step')">
    <rect x="230" y="120" width="220" height="56" rx="8" stroke-width="0.5"/>
    <text class="th" x="340" y="140" text-anchor="middle" dominant-baseline="central">Step two</text>
    <text class="ts" x="340" y="158" text-anchor="middle" dominant-baseline="central">Processes the input</text>
  </g>
</svg>

SVG rules:

  • ViewBox always 680px wide (viewBox="0 0 680 H"). Set H to fit content + 40px padding
  • Safe area: x=40 to x=640, y=40 to y=(H-40)
  • Pre-built classes: t (14px), ts (12px secondary), th (14px medium 500), box, node, arr, c-{color}
  • Every <text> element must carry a class (t, ts, or th)
  • Use dominant-baseline="central" for vertical text centering in boxes
  • Connector paths need fill="none" (SVG defaults to fill: black)
  • Stroke width: 0.5px for borders and edges
  • Make all nodes clickable: onclick="sendPrompt('...')"

Step 6: Interactive Explainer Template

For interactive explainers (sliders, live calculations, inline SVG):

<div style="display: flex; align-items: center; gap: 12px; margin: 0 0 1.5rem;">
  <label style="font-size: 14px; color: var(--color-text-secondary);">Years</label>
  <input type="range" min="1" max="40" value="20" id="years" style="flex: 1;" />
  <span style="font-size: 14px; font-weight: 500; min-width: 24px;" id="years-out">20</span>
</div>

<div style="display: flex; align-items: baseline; gap: 8px; margin: 0 0 1.5rem;">
  <span style="font-size: 14px; color: var(--color-text-secondary);">$1,000 →</span>
  <span style="font-size: 24px; font-weight: 500;" id="result">$3,870</span>
</div>

<div style="margin: 2rem 0; position: relative; height: 240px;">
  <canvas id="chart"></canvas>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js" onload="initChart()"></script>
<script>
function initChart() {
  // slider logic, chart rendering, sendPrompt() for follow-ups
}
if (window.Chart) initChart();
</script>

Use sendPrompt() to let users ask follow-ups: sendPrompt('What if I increase the rate to 10%?')


Step 7: Respond to the User

After rendering the widget, briefly explain:

  • What the widget shows
  • How to interact with it (which controls do what)
  • One key insight from the data

Keep it concise — the widget speaks for itself.


Reference Files

  • references/design_system.md — Complete color palette (9 ramps × 7 stops), CSS variables, UI component patterns, metric cards, layout rules
  • references/svg_and_diagrams.md — SVG viewBox setup, font calibration, pre-built classes, flowchart/structural/illustrative diagram patterns with examples
  • references/chart_js.md — Chart.js configuration, script load ordering, canvas sizing, legend patterns, dashboard layout

Read the relevant reference file when you need specific design tokens, SVG coordinate math, or Chart.js configuration details.

Other skills for the same job

different authors, same section of the catalogue
Seaborn
by christophacham
×3

Statistical visualization with pandas integration. Use for quick exploration of distributions, relationships, and categorical comparisons with attractive defaults. Best for box plots, violin plots, pair plots, heatmaps. Built on matplotlib. For interactive plots use plotly; for publication styling use scientific-visualization.

21k tokens
Pitch Deck
by anthropics
vendor ×1

Populates investment banking pitch deck templates with data from source files. Use when: user provides a PowerPoint template to fill in, user has source data (Excel/CSV) to populate into slides, user mentions populating or filling a pitch deck template, or user needs to transfer data into existing slide layouts. Not for creating presentations from scratch.

14k tokens
Seaborn
by K-Dense-AI
×1

Statistical visualization with pandas integration. Use for quick exploration of distributions, relationships, and categorical comparisons with attractive defaults. Best for box plots, violin plots, pair plots, heatmaps. Built on matplotlib. For interactive plots use plotly; for publication styling use scientific-visualization.

22k tokens
Scientific Visualization
by zLanqing
×1

Meta-skill for publication-ready figures. Use when creating journal submission figures requiring multi-panel layouts, significance annotations, error bars, colorblind-safe palettes, and specific journal formatting (Nature, Science, Cell). Orchestrates matplotlib/seaborn/plotly with publication styles. For quick exploration use seaborn or plotly directly.

26k tokens scripts
Seaborn
by zLanqing
×1

Statistical visualization with pandas integration. Use for quick exploration of distributions, relationships, and categorical comparisons with attractive defaults. Best for box plots, violin plots, pair plots, heatmaps. Built on matplotlib. For interactive plots use plotly; for publication styling use scientific-visualization.

21k tokens
Presentation Design Enhancer
by nicepkg
×1

Transform text-heavy slides into visual storytelling. Suggest layout improvements, icon usage, and data visualization.

355 tokens
Edge Signal Aggregator
by BaggaT236
×1

Aggregate and rank signals from multiple edge-finding skills (edge-candidate-agent, theme-detector, sector-analyst, institutional-flow-tracker) into a prioritized conviction dashboard with weighted scoring, deduplication, and contradiction detection.

22k tokens scripts
Core Web Vitals
by christophacham
×1

Optimize Core Web Vitals (LCP, INP, CLS) for better page experience and search ranking. Use when asked to "improve Core Web Vitals", "fix LCP", "reduce CLS", "optimize INP", "page experience optimization", or "fix layout shifts". Focuses specifically on the three Core Web Vitals metrics. Do NOT use for general web performance (use perf-web-optimization), Lighthouse audits (use perf-lighthouse), or Astro-specific optimization (use perf-astro).

4k tokens

How to use it

Copy the folder

Take himself65/generative-ui from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.