Blog
D3.js for Presentations: Static Charts vs. Shareable Pages
D3.js is, by a wide margin, the most capable charting tool most analysts will ever touch. It's also the tool most likely to leave you with a beautiful visualization and no good way to actually get it in front of someone.
This isn't a knock on D3 — quite the opposite. It's a low-level, unopinionated library, and that's exactly why it's worth learning. But "unopinionated" cuts both ways: D3 has strong opinions about how you build a chart and none at all about what happens next.
What D3 is actually good at
D3 doesn't give you chart types. It gives you data-to-DOM bindings, scales, and a small set of primitives for turning arrays into shapes. That's a deliberate design choice — it means there's no chart D3 can't make, at the cost of every chart taking longer to build than it would in a higher-level library.
A basic scatter plot in D3 looks like this:
const svg = d3
.select("#chart")
.append("svg")
.attr("viewBox", [0, 0, width, height]);
const x = d3
.scaleLinear()
.domain(d3.extent(data, (d) => d.orderDate))
.range([margin.left, width - margin.right]);
const y = d3
.scaleLinear()
.domain([0, d3.max(data, (d) => d.revenue)])
.range([height - margin.bottom, margin.top]);
svg
.selectAll("circle")
.data(data)
.join("circle")
.attr("cx", (d) => x(d.orderDate))
.attr("cy", (d) => y(d.revenue))
.attr("r", 4);
That's maybe a third of what you'd need for axes, transitions, and interaction. It's real work. And once it's done, what you have is a chart living in a <div> in a local dev environment, or a notebook cell, or a CodePen.
The part D3 doesn't solve
None of the above tells you how the chart gets to a stakeholder. The usual paths are:
- Screenshot it and paste into a slide — loses interactivity, goes stale immediately
- Export the whole page as a PDF — inherits whatever layout quirks the dev environment has
- Send a link to a locally-running app — breaks the moment you close your laptop
- Build a small internal tool to host it — now you're maintaining infrastructure for one chart
Every one of these adds friction between "the chart is done" and "someone can actually see it." For a chart you built to answer one specific question, that friction is disproportionate.
Treating D3 as a node, not a whole app
The more durable pattern is to treat a D3 chart as one component in a document, not the entire deliverable. That means the chart needs to live somewhere that already handles: layout around it, a way to publish or embed it without extra tooling, and a way for someone without a dev environment to open it.
Infigured treats raw SVG output — including D3's — as a first-class node type alongside markdown, SQL, and Python, on a flat scene graph. You write the D3 code, it renders against whatever query backs it, and the same node exists whether you're looking at it on a canvas, a presentation slide, or a published page. There's no export step where the chart gets flattened into an image and loses its identity.
// same D3 code as above, but the data comes from
// a workspace query object instead of a local array
const data = await query("quarterly_revenue_by_region");
Where this actually helps
If you're already comfortable with D3, the value isn't a new charting API to learn — it's removing the five steps between "chart works locally" and "chart is something I can send someone." That gap is usually the actual bottleneck, not the charting code itself.
Related: Turning a Jupyter Notebook Into Something You Can Actually Send Someone
Continue the workflow
Explore related guides
Next step
Move from insight to a stakeholder-ready story.
Infigure helps teams replace the export-to-slides loop with one connected reporting workflow for analysis, narrative, and delivery.