Agent D3js Skill
Dokhacgiakhoa/Agent-Skills-4-Vibe-Coding-CLI
Creating interactive data visualisations using d3.js. An agent skill from Dokhacgiakhoa/Agent-Skills-4-Vibe-Coding-CLI.
Creating interactive data visualisations using d3.js. An agent skill from calesthio/OpenMontage.
$ npx skills add calesthio/OpenMontage --skill d3-viz -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install calesthio/OpenMontage d3-viz --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/calesthio/OpenMontage.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/d3-viz .claude/skills/d3-viz && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "d3-viz" agent skill from https://github.com/calesthio/OpenMontage/tree/main/.agents/skills/d3-viz into .claude/skills/d3-viz/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "d3-viz", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/calesthio/OpenMontage/tree/main/.agents/skills/d3-vizType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add calesthio/OpenMontage --skill d3-viz -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install calesthio/OpenMontage d3-viz --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/calesthio/OpenMontage.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/d3-viz .agents/skills/d3-viz && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "d3-viz" agent skill from https://github.com/calesthio/OpenMontage/tree/main/.agents/skills/d3-viz into .agents/skills/d3-viz/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "d3-viz", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add calesthio/OpenMontage --skill d3-viz -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install calesthio/OpenMontage d3-viz --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/calesthio/OpenMontage.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/d3-viz .cursor/skills/d3-viz && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "d3-viz" agent skill from https://github.com/calesthio/OpenMontage/tree/main/.agents/skills/d3-viz into .cursor/skills/d3-viz/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "d3-viz", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/calesthio/OpenMontage.git --path .agents/skills/d3-viz--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add calesthio/OpenMontage --skill d3-viz -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install calesthio/OpenMontage d3-viz --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/calesthio/OpenMontage.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/d3-viz .gemini/skills/d3-viz && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "d3-viz" agent skill from https://github.com/calesthio/OpenMontage/tree/main/.agents/skills/d3-viz into .gemini/skills/d3-viz/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "d3-viz", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install calesthio/OpenMontage d3-vizInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add calesthio/OpenMontage --skill d3-viz -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/calesthio/OpenMontage.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/d3-viz .github/skills/d3-viz && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "d3-viz" agent skill from https://github.com/calesthio/OpenMontage/tree/main/.agents/skills/d3-viz into .github/skills/d3-viz/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "d3-viz", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add calesthio/OpenMontage --skill d3-viz -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install calesthio/OpenMontage d3-viz --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/calesthio/OpenMontage.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/d3-viz .opencode/skills/d3-viz && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "d3-viz" agent skill from https://github.com/calesthio/OpenMontage/tree/main/.agents/skills/d3-viz into .opencode/skills/d3-viz/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "d3-viz", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
d3-vizCreating interactive data visualisations using d3.js. An agent skill from calesthio/OpenMontage.
D3 Viz is an agent skill from calesthio/OpenMontage. Creating interactive data visualisations using d3.js. This skill should be used when creating custom charts, graphs, network diagrams, geographic visualisations, or any complex SVG-based data visualisation that requires fine-grained control over visual elements, transitions, or interactions. Use this for bespoke visualisations beyond standard charting libraries, whether in React, Vue, Svelte, vanilla JavaScript, or any other environment.
Its SKILL.md is about 5.4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 8 other files, including reference files and assets (for example `assets/sample-data.json`, `references/colour-schemes.md` and `references/d3-patterns.md`).
It sits in Data & Analytics, covering Data visualization and Diagrams. It works with D3.js, JavaScript, React and Svelte. The repository describes itself as: World's first open-source, agentic video production system. 12 production pipelines, 100+ tools, 700+ agent skill and production-knowledge files. Turn your AI coding assistant… The licence is AGPL-3.0.
4 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 9327439. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are javascript and html).
From the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
d3js.orgFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
D3 Viz loads about 5.4k tokens when it runs, and up to ~17k if it reads all its reference files. Until then it costs about 112 tokens; SKILL.md has 569 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from calesthio/OpenMontage at commit 9327439, republished under its AGPL-3.0 licence (© calesthio). 569 words, ~5,441 tokens.
.claude/skills/d3-viz/SKILL.md (or your agent's skills folder). This skill also uses 6 other files; get the full folder from GitHub.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.
Use d3.js for:
Consider alternatives for:
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.
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 dataUse 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.
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);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 removedOr 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();
}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'));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);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);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");
}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);
}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);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;
}// 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");
});const zoom = d3.zoom()
.scaleExtent([0.5, 10])
.on("zoom", (event) => {
g.attr("transform", event.transform);
});
svg.call(zoom);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 }));
});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);// 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]);// 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 colour scale
const colourScale = d3.scaleSequential(d3.interpolateBlues)
.domain([0, 100]);
// Diverging colour scale
const divScale = d3.scaleDiverging(d3.interpolateRdBu)
.domain([-10, 0, 10]);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)
}));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 animationsMake 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 alternativeUse 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");Issue: Axes not appearing
Issue: Transitions not working
.transition() before attribute changesIssue: Responsive sizing not working
Issue: Performance problems
.join() instead of separate enter/update/exit selectionsContains 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 recommendationsContains boilerplate templates:
chart-template.js - Starter template for basic chartinteractive-template.js - Template with tooltips, zoom, and interactionssample-data.json - Example datasets for testingThese 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.
© calesthio, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 6 other files (references, assets) in .agents/skills/d3-viz of calesthio/OpenMontage.
Open the folder on GitHubat commit 9327439
We found 4 copies of this SKILL.md (exact, near-identical or edited) in other folders, from 3 other GitHub owners. This page covers the copy in calesthio/OpenMontage, which our catalogue first saw on October 7, 2026.
D3 Viz next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| D3 Viz this skillcalesthio/OpenMontage | 66k | 3 repos | ~5.4k | Automated safety check: Pass | AGPL-3.0 | |
| Agent D3js SkillDokhacgiakhoa/Agent-Skills-4-Vibe-Coding-CLI | 508 | — | ~753 | Automated safety check: Pass | Custom licence | |
| Claude D3js Skillaiskillstore/marketplace | 430 | 4 repos | ~5.4k | Automated safety check: Pass | None | |
| Microsim Generatordmccreary/ibook-skills | 105 | — | ~11k | Automated safety check: Pass | None | |
| GSAP Core Animationgreensock/gsap-skills | 16k | 4 repos | ~3.7k | Automated safety check: Pass | MIT | |
| Markstream Custom ComponentsSimon-He95/markstream-vue | 3k | — | ~955 | Automated safety check: Pass | MIT |
Dokhacgiakhoa/Agent-Skills-4-Vibe-Coding-CLI
Creating interactive data visualisations using d3.js. An agent skill from Dokhacgiakhoa/Agent-Skills-4-Vibe-Coding-CLI.
aiskillstore/marketplace
Creating interactive data visualisations using d3.js. An agent skill from aiskillstore/marketplace.
dmccreary/ibook-skills
Creates interactive educational MicroSims, routing to the best-matched generator - p5.js, Chart.js, Plotly, Mermaid, vis-network, timelines, maps, Venn, causal-loop/feedback-loop diagrams (CLD)…
greensock/gsap-skills
Covers the GSAP core API for tweens, easing, staggers, defaults and matchMedia, and when to choose GSAP over CSS animations or other JavaScript animation libraries.
Simon-He95/markstream-vue
Override built-in Markstream node renderers and add trusted custom tags across Vue, React, Svelte, and Angular.
live-codes/livecodes
Use SDK with React, Vue, Svelte, Solid, Preact, and Web Components.
calesthio/OpenMontage
Understand video content locally using ffmpeg frame extraction and Whisper transcription.
calesthio/OpenMontage
Create AI avatar videos with precise control over avatars, voices, scripts, scenes, and backgrounds using HeyGen's v2 API.
calesthio/OpenMontage
Create videos from a text prompt using HeyGen's Video Agent.
calesthio/OpenMontage
Build deterministic, editable, free-viewpoint Three.js worlds from text or structured briefs.
calesthio/OpenMontage
Edit videos locally using ffmpeg. An agent skill from calesthio/OpenMontage.
calesthio/OpenMontage
Create, extract, and apply portable visual design systems via visual-style.md files.
Works with
Categories
Creating interactive data visualisations using d3.js. An agent skill from calesthio/OpenMontage. D3 Viz is an agent skill from calesthio/OpenMontage.js.
D3 Viz fits situations like: tasks that involve Data visualization; tasks that involve Diagrams.
Run `npx skills add calesthio/OpenMontage --skill d3-viz -a claude-code`. Or copy the skill folder (.agents/skills/d3-viz in calesthio/OpenMontage) into .claude/skills/d3-viz in your project. Claude Code loads it when a task matches its description.
Run `npx skills add calesthio/OpenMontage --skill d3-viz -a codex`. Or copy the skill folder (.agents/skills/d3-viz in calesthio/OpenMontage) into .agents/skills/d3-viz in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add calesthio/OpenMontage --skill d3-viz -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/d3-viz, .gemini/skills/d3-viz, .github/skills/d3-viz and .opencode/skills/d3-viz in your project.
SKILL.md names no scripts, command-line tools or credentials: D3 Viz is instructions for the agent only.
SKILL.md names 1 domain. In commands or code: d3js.org; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
D3 Viz is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.4k tokens (SKILL.md is roughly 22k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 12k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with D3 Viz: Agent D3js Skill (Dokhacgiakhoa/Agent-Skills-4-Vibe-Coding-CLI, 508 stars), Claude D3js Skill (aiskillstore/marketplace, 430 stars), Microsim Generator (dmccreary/ibook-skills, 105 stars) and GSAP Core Animation (greensock/gsap-skills, 16k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
calesthio (a GitHub user) maintains it in calesthio/OpenMontage, which has 65,614 GitHub stars. The repository holds 41 skills in this directory. The repository was last updated on October 3, 2026.
Source: calesthio/OpenMontage on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.