D3.js Visualizations
Visualization skill, available on Zeplik
D3.js Visualizations is a ready-to-run diagrams and visualization skill on Zeplik. js visualizations: networks, chord diagrams, maps, custom SVG with transitions and zoom. Ask in plain language and Zeplik applies the skill's method for you inside the conversation, on whichever AI model you prefer. It returns a structured diagram you can keep and reuse: Diagram artifact -- labeled nodes/edges, declared kind, deliberate layout (see artifact-templates/diagram.md).
The D3.js Visualizations skill loads automatically when your request matches it, or you can invoke it directly by typing /d3-viz in any chat. It works with attachments, connectors, and any model that supports the task, so you get the same expert method every time without setting anything up.
What the D3.js Visualizations skill can do
- Build custom interactive d3.js visualizations with SVG and transitions
- Construct network, chord, hierarchy, and force-directed graph layouts
- Create geographic maps with custom projections and zoom or pan behavior
- Deliver runnable single-file HTML or framework components from raw data
Try these prompts on Zeplik
Pick a prompt to open it in the Zeplik app. If you are not signed in yet, your prompt is waiting for you the moment you do.
How the D3.js Visualizations skill works
/d3-viz
Overview
This skill provides guidance for creating sophisticated, interactive data visualisations using d3.js. D3.js (Data-Driven Documents) excels at binding data to DOM elements and applying data-driven transformations to create custom, publication-quality visualisations with precise control over every visual element. The techniques work across any JavaScript environment, including vanilla JavaScript, React, Vue, Svelte, and other frameworks. The user pastes or uploads their data (JSON/CSV) or describes it; deliver a complete, runnable visualization (single-file HTML or a framework component) as a chat artifact.
When to use d3.js
Use d3.js for:
- Custom visualisations requiring unique visual encodings or layouts
- Interactive explorations with complex pan, zoom, or brush behaviours
- Network/graph visualisations (force-directed layouts, tree diagrams, hierarchies, chord diagrams)
- Geographic visualisations with custom projections
- Visualisations requiring smooth, choreographed transitions
- Publication-quality graphics with fine-grained styling control
- Novel chart types not available in standard libraries
Consider alternatives for:
- Quick standard charts (basic bar, line, pie with no custom behavior) - use create-viz instead
- 3D visualisations - use Three.js instead
Core workflow
1. Set up d3.js
Import d3 at the top of your script:
import * as d3 from 'd3';
Or use the CDN version (7.x):
<script src="https://d3js.org/d3.v7.min.js"></script>
All modules (scales, axes, shapes, transitions, etc.) are accessible through the d3 namespace.
2. Choose the integration pattern
Pattern A: Direct DOM manipulation (recommended for most cases) Use d3 to select DOM elements and manipulate them imperatively. This works in any JavaScript environment:
function drawChart(data) {
if (!data || data.length === 0) return;
const svg = d3.select('#chart'); // Select by ID, class, or DOM element
// Clear previous content
svg.selectAll("*").remove();
// Set up dimensions
const width = 800;
const height = 400;
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
// Create scales, axes, and draw visualisation
// ... d3 code here ...
}
// Call when data changes
drawChart(myData);
Pattern B: Declarative rendering (for frameworks with templating) Use d3 for data calculations (scales, layouts) but render elements via your framework:
function getChartElements(data) {
const xScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([0, 400]);
return data.map((d, i) => ({
x: 50,
y: i * 30,
width: xScale(d.value),
height: 25
}));
}
// In React: {getChartElements(data).map((d, i) => <rect key={i} {...d} fill="steelblue" />)}
// In Vue: v-for directive over the returned array
// In vanilla JS: Create elements manually from the returned data
Use Pattern A for complex visualisations with transitions, interactions, or when leveraging d3's full capabilities. Use Pattern B for simpler visualisations or when your framework prefers declarative rendering.
3. Structure the visualisation code
Follow this standard structure in your drawing function:
function drawVisualization(data) {
if (!data || data.length === 0) return;
const svg = d3.select('#chart'); // Or pass a selector/element
svg.selectAll("*").remove(); // Clear previous render
// 1. Define dimensions
const width = 800;
const height = 400;
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
// 2. Create main group with margins
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
// 3. Create scales
const xScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.x)])
.range([0, innerWidth]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.y)])
.range([innerHeight, 0]); // Note: inverted for SVG coordinates
// 4. Create and append axes
const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale);
g.append("g")
.attr("transform", `translate(0,${innerHeight})`)
.call(xAxis);
g.append("g")
.call(yAxis);
// 5. Bind data and create visual elements
g.selectAll("circle")
.data(data)
.join("circle")
.attr("cx", d => xScale(d.x))
.attr("cy", d => yScale(d.y))
.attr("r", 5)
.attr("fill", "steelblue");
}
// Call when data changes
drawVisualization(myData);
4. Implement responsive sizing
Make visualisations responsive to container size:
function setupResponsiveChart(containerId, data) {
const container = document.getElementById(containerId);
const svg = d3.select(`#${containerId}`).append('svg');
function updateChart() {
const { width, height } = container.getBoundingClientRect();
svg.attr('width', width).attr('height', height);
// Redraw visualisation with new dimensions
drawChart(data, svg, width, height);
}
// Update on initial load
updateChart();
// Update on window resize
window.addEventListener('resize', updateChart);
// Return cleanup function
return () => window.removeEventListener('resize', updateChart);
}
// Usage:
// const cleanup = setupResponsiveChart('chart-container', myData);
// cleanup(); // Call when component unmounts or element removed
Or use ResizeObserver for more direct container monitoring:
function setupResponsiveChartWithObserver(svgElement, data) {
const observer = new ResizeObserver(() => {
const { width, height } = svgElement.getBoundingClientRect();
d3.select(svgElement)
.attr('width', width)
.attr('height', height);
// Redraw visualisation
drawChart(data, d3.select(svgElement), width, height);
});
observer.observe(svgElement.parentElement);
return () => observer.disconnect();
}
Common visualisation patterns
Bar chart
function drawBarChart(data, svgElement) {
if (!data || data.length === 0) return;
const svg = d3.select(svgElement);
svg.selectAll("*").remove();
const width = 800;
const height = 400;
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
const xScale = d3.scaleBand()
.domain(data.map(d => d.category))
.range([0, innerWidth])
.padding(0.1);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([innerHeight, 0]);
g.append("g")
.attr("transform", `translate(0,${innerHeight})`)
.call(d3.axisBottom(xScale));
g.append("g")
.call(d3.axisLeft(yScale));
g.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => xScale(d.category))
.attr("y", d => yScale(d.value))
.attr("width", xScale.bandwidth())
.attr("height", d => innerHeight - yScale(d.value))
.attr("fill", "steelblue");
}
// Usage:
// drawBarChart(myData, document.getElementById('chart'));
Line chart
const line = d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.value))
.curve(d3.curveMonotoneX); // Smooth curve
g.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 2)
.attr("d", line);
Scatter plot
g.selectAll("circle")
.data(data)
.join("circle")
.attr("cx", d => xScale(d.x))
.attr("cy", d => yScale(d.y))
.attr("r", d => sizeScale(d.size)) // Optional: size encoding
.attr("fill", d => colourScale(d.category)) // Optional: colour encoding
.attr("opacity", 0.7);
Chord diagram
A chord diagram shows relationships between entities in a circular layout, with ribbons representing flows between them:
function drawChordDiagram(data) {
// data format: array of objects with source, target, and value
// Example: [{ source: 'A', target: 'B', value: 10 }, ...]
if (!data || data.length === 0) return;
const svg = d3.select('#chart');
svg.selectAll("*").remove();
const width = 600;
const height = 600;
const innerRadius = Math.min(width, height) * 0.3;
const outerRadius = innerRadius + 30;
// Create matrix from data
const nodes = Array.from(new Set(data.flatMap(d => [d.source, d.target])));
const matrix = Array.from({ length: nodes.length }, () => Array(nodes.length).fill(0));
data.forEach(d => {
const i = nodes.indexOf(d.source);
const j = nodes.indexOf(d.target);
matrix[i][j] += d.value;
matrix[j][i] += d.value;
});
// Create chord layout
const chord = d3.chord()
.padAngle(0.05)
.sortSubgroups(d3.descending);
const arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
const ribbon = d3.ribbon()
.source(d => d.source)
.target(d => d.target);
const colourScale = d3.scaleOrdinal(d3.schemeCategory10)
.domain(nodes);
const g = svg.append("g")
.attr("transform", `translate(${width / 2},${height / 2})`);
const chords = chord(matrix);
// Draw ribbons
g.append("g")
.attr("fill-opacity", 0.67)
.selectAll("path")
.data(chords)
.join("path")
.attr("d", ribbon)
.attr("fill", d => colourScale(nodes[d.source.index]))
.attr("stroke", d => d3.rgb(colourScale(nodes[d.source.index])).darker());
// Draw groups (arcs)
const group = g.append("g")
.selectAll("g")
.data(chords.groups)
.join("g");
group.append("path")
.attr("d", arc)
.attr("fill", d => colourScale(nodes[d.index]))
.attr("stroke", d => d3.rgb(colourScale(nodes[d.index])).darker());
// Add labels
group.append("text")
.each(d => { d.angle = (d.startAngle + d.endAngle) / 2; })
.attr("dy", "0.31em")
.attr("transform", d => `rotate(${(d.angle * 180 / Math.PI) - 90})translate(${outerRadius + 30})${d.angle > Math.PI ? "rotate(180)" : ""}`)
.attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
.text((d, i) => nodes[i])
.style("font-size", "12px");
}
Heatmap
A heatmap uses colour to encode values in a two-dimensional grid, useful for showing patterns across categories:
function drawHeatmap(data) {
// data format: array of objects with row, column, and value
// Example: [{ row: 'A', column: 'X', value: 10 }, ...]
if (!data || data.length === 0) return;
const svg = d3.select('#chart');
svg.selectAll("*").remove();
const width = 800;
const height = 600;
const margin = { top: 100, right: 30, bottom: 30, left: 100 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
// Get unique rows and columns
const rows = Array.from(new Set(data.map(d => d.row)));
const columns = Array.from(new Set(data.map(d => d.column)));
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
// Create scales
const xScale = d3.scaleBand()
.domain(columns)
.range([0, innerWidth])
.padding(0.01);
const yScale = d3.scaleBand()
.domain(rows)
.range([0, innerHeight])
.padding(0.01);
// Colour scale for values
const colourScale = d3.scaleSequential(d3.interpolateYlOrRd)
.domain([0, d3.max(data, d => d.value)]);
// Draw rectangles
g.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => xScale(d.column))
.attr("y", d => yScale(d.row))
.attr("width", xScale.bandwidth())
.attr("height", yScale.bandwidth())
.attr("fill", d => colourScale(d.value));
// Add x-axis labels
svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`)
.selectAll("text")
.data(columns)
.join("text")
.attr("x", d => xScale(d) + xScale.bandwidth() / 2)
.attr("y", -10)
.attr("text-anchor", "middle")
.text(d => d)
.style("font-size", "12px");
// Add y-axis labels
svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`)
.selectAll("text")
.data(rows)
.join("text")
.attr("x", -10)
.attr("y", d => yScale(d) + yScale.bandwidth() / 2)
.attr("dy", "0.35em")
.attr("text-anchor", "end")
.text(d => d)
.style("font-size", "12px");
// Add colour legend
const legendWidth = 20;
const legendHeight = 200;
const legend = svg.append("g")
.attr("transform", `translate(${width - 60},${margin.top})`);
const legendScale = d3.scaleLinear()
.domain(colourScale.domain())
.range([legendHeight, 0]);
const legendAxis = d3.axisRight(legendScale)
.ticks(5);
// Draw colour gradient in legend
for (let i = 0; i < legendHeight; i++) {
legend.append("rect")
.attr("y", i)
.attr("width", legendWidth)
.attr("height", 1)
.attr("fill", colourScale(legendScale.invert(i)));
}
legend.append("g")
.attr("transform", `translate(${legendWidth},0)`)
.call(legendAxis);
}
Pie chart
const pie = d3.pie()
.value(d => d.value)
.sort(null);
const arc = d3.arc()
.innerRadius(0)
.outerRadius(Math.min(width, height) / 2 - 20);
const colourScale = d3.scaleOrdinal(d3.schemeCategory10);
const g = svg.append("g")
.attr("transform", `translate(${width / 2},${height / 2})`);
g.selectAll("path")
.data(pie(data))
.join("path")
.attr("d", arc)
.attr("fill", (d, i) => colourScale(i))
.attr("stroke", "white")
.attr("stroke-width", 2);
Force-directed network
const simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).id(d => d.id).distance(100))
.force("charge", d3.forceManyBody().strength(-300))
.force("center", d3.forceCenter(width / 2, height / 2));
const link = g.selectAll("line")
.data(links)
.join("line")
.attr("stroke", "#999")
.attr("stroke-width", 1);
const node = g.selectAll("circle")
.data(nodes)
.join("circle")
.attr("r", 8)
.attr("fill", "steelblue")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
simulation.on("tick", () => {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node
.attr("cx", d => d.x)
.attr("cy", d => d.y);
});
function dragstarted(event) {
if (!event.active) simulation.alphaTarget(0.3).restart();
event.subject.fx = event.subject.x;
event.subject.fy = event.subject.y;
}
function dragged(event) {
event.subject.fx = event.x;
event.subject.fy = event.y;
}
function dragended(event) {
if (!event.active) simulation.alphaTarget(0);
event.subject.fx = null;
event.subject.fy = null;
}
Adding interactivity
Tooltips
// Create tooltip div (outside SVG)
const tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("visibility", "hidden")
.style("background-color", "white")
.style("border", "1px solid #ddd")
.style("padding", "10px")
.style("border-radius", "4px")
.style("pointer-events", "none");
// Add to elements
circles
.on("mouseover", function(event, d) {
d3.select(this).attr("opacity", 1);
tooltip
.style("visibility", "visible")
.html(`<strong>${d.label}</strong><br/>Value: ${d.value}`);
})
.on("mousemove", function(event) {
tooltip
.style("top", (event.pageY - 10) + "px")
.style("left", (event.pageX + 10) + "px");
})
.on("mouseout", function() {
d3.select(this).attr("opacity", 0.7);
tooltip.style("visibility", "hidden");
});
Zoom and pan
const zoom = d3.zoom()
.scaleExtent([0.5, 10])
.on("zoom", (event) => {
g.attr("transform", event.transform);
});
svg.call(zoom);
Click interactions
circles
.on("click", function(event, d) {
// Handle click (dispatch event, update app state, etc.)
console.log("Clicked:", d);
// Visual feedback
d3.selectAll("circle").attr("fill", "steelblue");
d3.select(this).attr("fill", "orange");
// Optional: dispatch custom event for your framework/app to listen to
// window.dispatchEvent(new CustomEvent('chartClick', { detail: d }));
});
Transitions and animations
Add smooth transitions to visual changes:
// Basic transition
circles
.transition()
.duration(750)
.attr("r", 10);
// Chained transitions
circles
.transition()
.duration(500)
.attr("fill", "orange")
.transition()
.duration(500)
.attr("r", 15);
// Staggered transitions
circles
.transition()
.delay((d, i) => i * 50)
.duration(500)
.attr("cy", d => yScale(d.value));
// Custom easing
circles
.transition()
.duration(1000)
.ease(d3.easeBounceOut)
.attr("r", 10);
Scales reference
Quantitative scales
// Linear scale
const xScale = d3.scaleLinear()
.domain([0, 100])
.range([0, 500]);
// Log scale (for exponential data)
const logScale = d3.scaleLog()
.domain([1, 1000])
.range([0, 500]);
// Power scale
const powScale = d3.scalePow()
.exponent(2)
.domain([0, 100])
.range([0, 500]);
// Time scale
const timeScale = d3.scaleTime()
.domain([new Date(2020, 0, 1), new Date(2024, 0, 1)])
.range([0, 500]);
Ordinal scales
// Band scale (for bar charts)
const bandScale = d3.scaleBand()
.domain(['A', 'B', 'C', 'D'])
.range([0, 400])
.padding(0.1);
// Point scale (for line/scatter categories)
const pointScale = d3.scalePoint()
.domain(['A', 'B', 'C', 'D'])
.range([0, 400]);
// Ordinal scale (for colours)
const colourScale = d3.scaleOrdinal(d3.schemeCategory10);
Sequential scales
// Sequential colour scale
const colourScale = d3.scaleSequential(d3.interpolateBlues)
.domain([0, 100]);
// Diverging colour scale
const divScale = d3.scaleDiverging(d3.interpolateRdBu)
.domain([-10, 0, 10]);
Best practices
Data preparation
Always validate and prepare data before visualisation:
// Filter invalid values
const cleanData = data.filter(d => d.value != null && !isNaN(d.value));
// Sort data if order matters
const sortedData = [...data].sort((a, b) => b.value - a.value);
// Parse dates
const parsedData = data.map(d => ({
...d,
date: d3.timeParse("%Y-%m-%d")(d.date)
}));
Performance optimisation
For large datasets (>1000 elements):
// Use canvas instead of SVG for many elements
// Use quadtree for collision detection
// Simplify paths with d3.line().curve(d3.curveStep)
// Implement virtual scrolling for large lists
// Use requestAnimationFrame for custom animations
Accessibility
Make visualisations accessible:
// Add ARIA labels
svg.attr("role", "img")
.attr("aria-label", "Bar chart showing quarterly revenue");
// Add title and description
svg.append("title").text("Quarterly Revenue 2024");
svg.append("desc").text("Bar chart showing revenue growth across four quarters");
// Ensure sufficient colour contrast
// Provide keyboard navigation for interactive elements
// Include data table alternative
Styling
Use consistent, professional styling:
// Define colour palettes upfront
const colours = {
primary: '#4A90E2',
secondary: '#7B68EE',
background: '#F5F7FA',
text: '#333333',
gridLines: '#E0E0E0'
};
// Apply consistent typography
svg.selectAll("text")
.style("font-family", "Inter, sans-serif")
.style("font-size", "12px");
// Use subtle grid lines
g.selectAll(".tick line")
.attr("stroke", colours.gridLines)
.attr("stroke-dasharray", "2,2");
Common issues and solutions
Issue: Axes not appearing
- Ensure scales have valid domains (check for NaN values)
- Verify axis is appended to correct group
- Check transform translations are correct
Issue: Transitions not working
- Call
.transition()before attribute changes - Ensure elements have unique keys for proper data binding
- Check that useEffect dependencies include all changing data
Issue: Responsive sizing not working
- Use ResizeObserver or window resize listener
- Update dimensions in state to trigger re-render
- Ensure SVG has width/height attributes or viewBox
Issue: Performance problems
- Limit number of DOM elements (consider canvas for >1000 items)
- Debounce resize handlers
- Use
.join()instead of separate enter/update/exit selections - Avoid unnecessary re-renders by checking dependencies
Resources
references/
Contains detailed reference materials:
d3-patterns.md- Comprehensive collection of visualisation patterns and code examplesscale-reference.md- Complete guide to d3 scales with examplescolour-schemes.md- D3 colour schemes and palette recommendations
assets/
Contains boilerplate templates:
chart-template.jsx- Starter template for basic chartinteractive-template.jsx- Template with tooltips, zoom, and interactionssample-data.json- Example datasets for testing
These templates work with vanilla JavaScript, React, Vue, Svelte, or any other JavaScript environment. Adapt them as needed for your specific framework.
To use these resources, read the relevant files when detailed guidance is needed for specific visualisation types or patterns.
Usage
/d3-viz $ARGUMENTS
How to use the D3.js Visualizations skill
Sign in to Zeplik
Create a free Zeplik account or sign in. New accounts start with free credits, so you can try the D3.js Visualizations skill right away.
Describe your diagrams and visualization task
Ask in plain language, or type /d3-viz to invoke the skill directly. Zeplik recognizes the D3.js Visualizations skill and applies its method.
Review and refine the result
Zeplik returns a structured diagram you can edit, download, and reuse. Ask follow-ups to refine it.
Source and credit
- Author
- davila7
- License
- MIT
Adapted from the open-source davila7/claude-code-templates project and tuned to run natively on Zeplik. View source on GitHub.
Frequently asked questions
- What is the D3.js Visualizations skill?
- D3.js Visualizations is a ready-to-run diagrams and visualization skill on Zeplik. js visualizations: networks, chord diagrams, maps, custom SVG with transitions and zoom. Ask in plain language and Zeplik applies the skill's method for you inside the conversation, on whichever AI model you prefer. It returns a structured diagram you can keep and reuse: Diagram artifact -- labeled nodes/edges, declared kind, deliberate layout (see artifact-templates/diagram.md).
- How do I use D3.js Visualizations on Zeplik?
- Sign in to Zeplik and ask in plain language, or type /d3-viz in any chat to invoke it directly. The skill applies its method and returns a result you can refine in the same conversation.
- Which AI model does the D3.js Visualizations skill use?
- Any model you choose. Zeplik works across every model in one chat, so the D3.js Visualizations skill runs on your preferred model for the task.
- Where does the D3.js Visualizations skill come from?
- The D3.js Visualizations skill is adapted from the open-source davila7/claude-code-templates project (MIT) and tuned to run natively on Zeplik. The original source is linked on this page.
- How much does the D3.js Visualizations skill cost?
- Using the skill is free to start. You only spend Zeplik credits when the assistant runs, and new accounts begin with free credits.
Related visualization skills
- C4 Architecture DiagramsUse when documenting software architecture as C4 model Mermaid diagrams: context, container, component, deployment, dynamic. Not for general diagrams (use diagram or mermaid-diagrams).
- Diagram & Flowchart MakerProduce a downloadable, editable draw.io/diagrams.net XML file the user opens at app.diagrams.net. Use ONLY when the user explicitly wants an editable draw.io / diagrams.net / .drawio deliverable (a canvas file to open in the draw.io editor). For a diagram the user just wants to SEE inline in the chat — a flowchart, architecture, ER, sequence, or state diagram — use mermaid-diagrams (it renders as a real diagram in the message); this draw.io file does not render inline. Not for hand-drawn whiteboard looks (use excalidraw).
- Draw.io DiagramsUse when creating, editing, or laying out .drawio XML diagrams, including AWS architecture icons. Not for hand-drawn-style sketch diagrams (use excalidraw).
- Excalidraw DiagramsUse when creating, editing, or explaining .excalidraw JSON diagrams with a hand-drawn look. Not for Markdown text diagrams (use mermaid-diagrams).
- Math Animation StudioUse when building mathematical or educational animations with Manim (Python) -- scenes, mobjects, LaTeX. Not for data charts or plots (use create-viz).
- Mermaid Diagram MakerThe DEFAULT for any diagram the user wants to SEE inline in chat — flowcharts, flow diagrams, sequence, class, ER/database schema, C4 architecture, state, and gantt. Renders as a real diagram right in the message (Markdown-embeddable Mermaid), so use it for generic "make/draw a flowchart / architecture diagram / diagram of X" requests. Switch to the draw.io diagram skill only when the user explicitly asks for an editable draw.io / diagrams.net file.
More on Zeplik
Try D3.js Visualizations on Zeplik
Every model, one chat. Bring the D3.js Visualizations skill into your next conversation and let the assistant do the work.