visualize skill
Render 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
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-v2 ~/.claude/skills/visualize
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
This is the handbook/tutorial on how to use the visualizer tool. The visualizer tool can render rich interactive visuals directly inline in chat using visualize.
How to use
you called the view_skill() tool to read the tutorial/handbook about this tool. Read the entire handbook carefully and follow the rules closely, otherwise the visualizations might end up not rendering properly or being entirely broken. This tutorial/handbook shows you how to actually use the tool and build beautiful visualizations.
- Call visualize(title="…") - YOU MUST CALL THE TOOL, otherwise the visualization you output will not be rendered in the chat.
- Calling the tool, an iFrame wrapper sandbox will immediately appear inside the chat (visible only to the user). This iFrame sandbox will AUTOMATICALLY paint/render everything you output within the tags after you called the tool.
- After calling the tool, start with the opening tag @@@VIZ-START on its own line
- Next, after the opening tag, emit the HTML/SVG content (no <!DOCTYPE>, , , )
- Once you are done writing the code for the visualization, immediately close with @@@VIZ-END on its own line, followed by ONE EMPTY LINE. Without the empty line, markdown in your follow-up text (bold, lists, links) is not rendered.
- Done! The visualization is complete. Continue with any follow-up text to the user.
The raw markers + SVG source are auto-hidden from the chat — users see only the rendered iframe filling in live.
Example response structure:
""" I'll visualize the attention mechanism for you.
@@@VIZ-START <!-- content streams here, renders live --> @@@VIZ-END
As you can see, each query token attends to all key tokens simultaneously. """
Streaming rules:
- Use the delimiters EXACTLY @@@VIZ-START and @@@VIZ-END — case-sensitive, on their own lines, with an empty line after @@@VIZ-END before any follow-up text. Do NOT put the content inside , ~~~, or ::: fences or any codeblock or other markdown.
- Do NOT wrap in HTML tags like or — only the text markers are detected.
- Emit exactly ONE @@@VIZ-START … @@@VIZ-END pair per tool call. For multiple visualizations, call the tool multiple times.
- Structure the content as always: first → visible content → last.
- Do NOT describe the HTML source in prose — users don't see it. Describe what the visualization shows.
- Requires iframe Sandbox Allow Same Origin in Open WebUI Settings → Interface. If disabled, the wrapper shows a notice — and the user won't see the visualization itself, just the notice.
- Any you include runs once, after the full block has streamed in.
What's auto-injected
- Theme CSS, SVG classes, color ramps, height reporting, sendPrompt() bridge, and openLink() bridge
- Pre-styled bare-tag form elements (see below) — saves tokens on simple forms
- Consider making diagrams conversational with sendPrompt() — see the "sendPrompt bridge" section further below for patterns and examples
Pre-styled form elements
These tags get theme-aware default styling when emitted without a class or inline style attribute. Other attributes (placeholder, value, id, aria-*, min/max, etc.) are fine — they don't disable the defaults. Adding class or style is treated as an opt-out: the default is suppressed and you can style it from scratch. Useful for short forms or quick UIs where the design doesn't need to deviate.
Pre-styled elements included in the tool:
- — themed button. Use it for actions.
- — themed text input. Use it where a user types or picks a value.
- — slider. Use it for "from–to" picks, intensity dials, or any continuous value where exact precision doesn't matter.
- , — multi-pick / single-pick. Self-explanatory.
- — multi-line text input.
- — dropdown. Use it when a list of choices is too long for radios.
- , , — form structure. Group related inputs and label them.
- — keyboard-key cap. Use it whenever you mention a shortcut, so the key visually pops as a key.
- Mac: ⌘K
- Windows / Linux: CtrlK
- — horizontal divider. Separate sections inside a card or between groups of content.
- / — collapsible disclosure. Use it for progressive disclosure: hide secondary detail behind a clickable summary so the surface stays clean.
Bonus on bare elements:
- aria-invalid="true" paints a danger-colored border on input/textarea/select
- :focus-visible keyboard focus draws a clear --accent outline (mouse focus stays subtle)
Accent color palette
The default accent is purple. Switch to one of the other ramps via the data-accent attribute. The chosen color drives --accent and --accent-foreground, which in turn power focus rings, checkbox/radio fills, and any var(--accent) reference you write yourself. The same nine names match the chart color ramps, so a teal-accented form sits naturally next to a teal-accented chart.
Available values: purple (default), teal, coral, pink, gray, blue, green, amber, red
To apply an accent color globally to the whole visualization: wrap the entire content in a single root . Every supported element inside inherits the chosen accent.
/ CSS / …all focus rings, checkboxes, and var(--accent) consumers go teal…
To apply an accent color to a specific section: set data-accent on any inner container to recolor just its subtree:
Save <!-- teal focus ring --> <!-- teal accent --> Cancel <!-- still default purple -->
To apply an accent color to a single element: set directly on an element to recolor just it:
Approve Reject
Both light and dark themes are handled — accent values track per-theme ramp stops automatically, and foreground text color flips for legibility in dark mode. No manual override needed.
Pick an accent that matches the topic: green for finance/positive, red for warnings/critical actions, blue for informational dashboards, amber for attention/caution, etc. Default to purple for neutral or multi-purpose visualizations.
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)
- Prefer no emojis, instead 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
- Keep long-form explanation in the prose response. Use concise labels, captions, legends, helper text, and short annotations inside the visual when they improve comprehension.
- Build ambitiously when the topic supports it. Treat each visualization like a small product surface, not a single static graphic. Combine multiple elements: a chart paired with a metric strip, a diagram with collapsible deep-dives, a comparison card with sliders that let the user explore tradeoffs. Use animation, hover, and click interactions where they help the reader notice or explore something — not for decoration. If the user asked for "a chart" and the topic naturally extends into a small dashboard, build the dashboard. Restraint is for cases where extra structure would distract; default to richness, not minimalism.
Design system
CSS variables (auto-injected — prefer these so light/dark mode just works)
The tool injects theme-aware CSS variables that adapt to light/dark mode automatically. Use them by default for text, surface, and border colors; reach for a specific hex only when the design genuinely calls for a fixed color (a brand mark, a deliberate accent that shouldn't track the theme).
Color ramps (9 ramps, auto light/dark)
Each ramp provides fill, stroke, and text variants that adapt to the theme automatically via CSS classes.
Chart dataset colors (use 400 stops)
For area/line fills, use same color at 20% opacity.
SVG setup
If you want to build a beautiful SVG to be rendered inside the chat, follow these rules too: Always use this SVG boilerplate:
- 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)
Drop these on SVG elements instead of writing inline fill, stroke, or font-size. They track the theme automatically.
Sizing text inside boxes
Browsers don't auto-size SVG boxes to text. To pick a width, estimate the rendered glyph width per character and size the box from the longest line.
- 14px text (.t, .th) → ~8 px / character
- 12px text (.ts) → ~7 px / character
- boxwidth = max(titlechars × 8, subtitle_chars × 7) + 24 (12 px padding each side)
Centering text in boxes
defaults to dominant-baseline="alphabetic" — y is the text's baseline, not its center, so a label placed at the vertical midpoint of a box actually sits ~4 px too high. For text inside a node, callout, or any rounded rect, add dominant-baseline="central" and put y at the box midpoint.
Keep the default (no dominant-baseline) for text that's meant to sit on a baseline: axis tick labels (resting on the axis line), legend labels (aligned to the swatch baseline), and anything where the bottom edge of the glyphs is the visual anchor. Setting central on those will make them look ~4 px low instead.
Diagram types
Flowchart — sequential steps, decisions
- 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:
Label
Two-line node:
Title Subtitle
Architecture — nested regions, layered systems
More skills from Classic298/open-webui-plugins
- AvisualizeRender 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.