Mmcp.market

visualize skill

by Classic298·Classic298/open-webui-plugins·568 stars·BSD-3-Clause

Render rich interactive visuals — SVG diagrams, HTML widgets, Chart.js charts, interactive explainers — directly inline in chat using the render_visualization tool. Use whenever the user asks to visualize, diagram, chart, draw, map out, or illustrate something, or when a topic has spatial, sequential, or systemic relationships a diagram would clarify better than prose. Also use proactively for data comparisons, metrics, architecture, processes, or mechanisms that benefit from a visual.

A100/100content scan

Is the visualize skill safe?

Clean: nothing in its files matched our rules. We read 3 files in the folder on 2026-09-28.

No findings.

Install the visualize skill

A skill is a folder. Copy it into your agent's skills folder and the agent loads it when the task matches its description.

git clone --depth 1 https://github.com/Classic298/open-webui-plugins.git /tmp/open-webui-plugins
mkdir -p ~/.claude/skills
cp -r /tmp/open-webui-plugins/inline-visualizer ~/.claude/skills/visualize
available in every project

In the Claude apps, zip the folder and upload it from the Skills settings. The folder on GitHub

The instructions your agent would load

SKILL.md as published, without the frontmatter. Read it on GitHub

Inline Visualizer

Render rich interactive visuals directly inline in chat using render_visualization.

How to use

  1. Call rendervisualization(htmlcode, title) with an HTML or SVG content fragment
  2. Do NOT include <!DOCTYPE>, , , or — the tool wraps your content automatically
  3. Structure: first (prefer inline styles) → visible content → last
  4. The tool auto-injects: theme CSS, SVG classes, color ramps, height reporting, sendPrompt() bridge, and openLink() bridge
  5. Consider making diagrams conversational with sendPrompt() — see the sendPrompt bridge section for patterns and examples

Output rules

These rules keep visuals clean, accessible, and consistent with the host UI:

  • Flat design — no gradients, drop shadows, blur, glow, or noise textures (the host UI is flat; matching it prevents visual jarring)
  • No emoji — use CSS shapes or SVG paths for icons (emoji render inconsistently across platforms)
  • Sentence case — all labels and headings
  • Round displayed numbers — use Math.round, toLocaleString, or Intl.NumberFormat
  • Min font size 11px — smaller becomes unreadable on most screens
  • Text weights — 400 regular, 500 for emphasis only
  • All explanatory text goes in your prose response, not inside the visual (keeps visuals data-dense and lets the model's response provide context)

Design system

CSS variables (auto-injected — always use these, never hardcode colors)

The tool injects theme-aware CSS variables that automatically adapt to light/dark mode. Hardcoding hex colors will break in one mode or the other.

Color ramps (9 ramps, auto light/dark)

Each ramp provides fill, stroke, and text variants that adapt to the theme automatically via CSS classes.

Color assignment rules:

  • Color encodes meaning, not sequence — don't cycle like a rainbow
  • Group nodes by category — same type shares one color
  • Use gray for neutral/structural nodes (start, end, generic)
  • Use 2–3 colors max per diagram
  • Reserve blue/green/amber/red for semantic meaning (info/success/warning/error)

Chart dataset colors (use 400 stops)

For area/line fills, use same color at 20% opacity.

SVG setup

Always use this SVG boilerplate:

<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>
</svg>
  • viewBox width always 680 — set H to tightly fit content (last element bottom + 40px). Never oversize — calculate the actual bottom of your last SVG element and add 40px. An SVG with content ending at y=180 must use H=220, not 500
  • Safe area: x=40 to x=640
  • Background transparent — host provides container

SVG classes (auto-injected)

Font width calibration

  • 14px: ~8px per character
  • 12px: ~7px per character
  • Box width = max(titlechars × 8, subtitlechars × 7) + 24

Text positioning

Every text inside a box needs dominant-baseline="central" with y at the vertical center of its slot. Without this, text sits ~4px too high and looks misaligned.

Diagram types

Flowchart — sequential steps, decisions

When: "walk me through the steps", "what's the process"

  • Max 4–5 nodes per diagram — 6+ → decompose into overview + sub-flows
  • Box spacing: 60px between boxes, 24px padding inside
  • Single-line node: height 44px, two-line: 56px
  • Arrows must not cross any box — use L-bends if needed
  • Use marker-end="url(#arrow)" on arrow paths

Single-line node:

<g class="node c-teal" onclick="sendPrompt('Tell me about X')">
  <rect x="100" y="20" width="180" height="44" rx="8"/>
  <text class="th" x="190" y="42" text-anchor="middle" dominant-baseline="central">Label</text>
</g>

Two-line node:

<g class="node c-teal">
  <rect x="100" y="20" width="200" height="56" rx="8"/>
  <text class="th" x="200" y="38" text-anchor="middle" dominant-baseline="central">Title</text>
  <text class="ts" x="200" y="56" text-anchor="middle" dominant-baseline="central">Subtitle</text>
</g>

Structural — containment, architecture

When: "what's the architecture", "where does X live"

  • Outermost container: rx=20–24, lightest fill (50 stop), 0.5px stroke
  • Inner regions: rx=8–12, next shade, different ramp if semantically different
  • 20px min padding inside containers
  • Max 2–3 nesting levels

Illustrative — spatial metaphors, mechanisms

When: "how does X actually work", "explain X" (spatial concept)

  • Draw the mechanism, not a diagram about it
  • Shapes are freeform — paths, ellipses, polygons, curves
  • Color encodes intensity (warm = active, cool = calm, gray = inert)
  • Labels: outside the object with leader lines, reserve 140px margin
  • Prefer interactive over static — if the system has a control, give the diagram that control

Charts (Chart.js)

Load Chart.js in your HTML fragment:

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.min.js"></script>

Setup pattern:

<div style="position: relative; height: 300px;">
  <canvas id="chart"></canvas>
</div>
<script>
const ctx = document.getElementById('chart').getContext('2d');
const s = getComputedStyle(document.documentElement);
const textColor = s.getPropertyValue('--color-text-secondary').trim();
const gridColor = s.getPropertyValue('--color-border-tertiary').trim();

new Chart(ctx, {
  type: 'bar',
  data: {
    labels: ['Q1','Q2','Q3','Q4'],
    datasets: [{ label: 'Revenue', data: [12,19,8,15],
      backgroundColor: '#1D9E75', borderRadius: 4, borderSkipped: false }]
  },
  options: {
    responsive: true, maintainAspectRatio: false,
    plugins: { legend: { labels: { color: textColor, font: { size: 12 } } } },
    scales: {
      x: { grid: { display: false }, ticks: { color: textColor, font: { size: 12 } }, border: { color: gridColor } },
      y: { grid: { color: gridColor }, ticks: { color: textColor, font: { size: 12 } }, border: { display: false } }
    }
  }
});
</script>

Chart rules:

  • Wrap canvas in container with position: relative and explicit height
  • Always responsive: true, maintainAspectRatio: false
  • Read CSS variables for text/border colors — never hardcode
  • borderRadius: 4 on bars
  • Line charts: tension: 0.3 for smooth curves
  • Doughnut: cutout: '60%' — never use pie

Chart type selection:

Inline SVG charts (no library)

Horizontal bar:

<svg width="100%" viewBox="0 0 680 80">
  <text class="ts" x="40" y="30">Category A</text>
  <rect x="160" y="16" width="360" height="20" rx="4" fill="#1D9E75" opacity="0.8"/>
  <text class="ts" x="530" y="30">72%</text>
</svg>

Component patterns

Metric cards

<div style="display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:12px;">
  <div style="background:var(--color-bg-secondary); border:0.5px solid var(--color-border-tertiary);
    border-radius:var(--radius-lg); padding:16px;">
    <div style="font-size:12px; color:var(--color-text-secondary);">Label</div>
    <div style="font-size:28px; font-weight:500; color:var(--color-text-primary); margin-top:4px;">$3,870</div>
  </div>
  <!-- repeat -->
</div>

Comparison layout

Side-by-side cards with a shared header row, metrics in each column.

Interactive explainer

Sliders or buttons that update visible state via JavaScript. Example: a slider controlling a variable with a live-updating SVG or value display.

sendPrompt bridge — conversational diagrams

sendPrompt(text) is the function that makes visualizations conversational. When called, it injects the given text into the chat input field and submits it — exactly as if the user had typed and sent it themselves. The model then receives that message and responds normally, creating a feedback loop between the visual and the conversation.

This is what separates a static diagram from an exploration interface. A user sees a system architecture diagram, clicks on the "Load Balancer" node, and the model receives "Tell me more about the load balancer — how does it distribute traffic across the backend services?" as a user message. The model then responds with details, and could even generate a new sub-diagram showing the load balancer internals. The user never had to type anything — they just clicked.

More skills from Classic298/open-webui-plugins

  • AvisualizeRender rich interactive visuals — SVG diagrams, HTML widgets, Chart.js charts, and interactive explainers — directly inline in chat using visualize(). Use only when the user explicitly asks for a visualization, diagram, chart, graph, drawing, map, dashboard, or similar visual artifact. Do not use for ordinary markdown, code blocks, file previews, or answer formatting

All agent skills → · MCP servers