Both story #2 charts, rendered the way they were (a hand-written SVG generator) and the way the line-charts bake-off recommends (Observable Plot). Same data, same palette, same deployment: a committed .svg file embedded as a Markdown image. Plot is rendered to that SVG in Node at build time — no JavaScript runs on the published page.
Outcome: Plot wins. It is now the near-term standard for story and enrich charts — see docs/charting.md. This page is kept as the record of the comparison.
Same
data, computed values, palette, sort order, the 16.6× clip, the "beyond" row, the deploy model
New cost
@observablehq/plot + jsdom, build-only, scoped to site/stories/package.json
Code
scoreboard generator: ~120 lines hand-rolled → ~45 with Plot
Rough edge
Plot's Node render estimates text width (no browser layout) — tick margins can be a few px off a real browser
01The scoreboard
Twelve indicators, framework-normalised so the pre-industrial state is 0 and the boundary is 1×. Six of nine boundaries crossed; genetic diversity runs off the axis at 16.6×.
planetary-boundaries-scoreboard — horizontal bars, reference rule at 1×, tinted safe zone, rows sorted by overshoot
was — hand-rolled~120 loc
now — Observable Plot~45 loc
What Plot changed
The x-axis, ticks, gridlines, sorted rows and the tinted safe zone are all declarative — that is where ~75 lines went.
Bar thickness, the reference rule, the clipped-bar treatment and the "safe operating space" caption carried over with one setting each.
Plot puts its axis label along the bottom centre rather than as a caption; values and colours are identical.
02Ozone
Seven benchmark years from the source compilation. The line dips toward the 276 DU boundary around 1990, then recovers after the Montreal Protocol.
The y-ticks are named (270, 276, 282 …) so the 276 DU boundary lands on a gridline, same as before.
Axis titles sit at the top-left and bottom-right — Plot's placement — rather than a rotated y-title. The direction arrows Plot adds by default are switched off.
Gridlines, the line join and the point markers come for free and match.
03The trade
Hand-rolled SVG
Observable Plot
Scoreboard generator
~120 lines
~45 lines
Axis / ticks / grid / sort
written by hand each time
declarative, free
Pixel-level control
total
Plot's defaults, then override
Axis-label placement
fully yours
Plot's, unless overridden
New dependency
none
@observablehq/plot + jsdom, build-only
Published page
static SVG, no JS
static SVG, no JS
Chart types ahead (ranged bars, small multiples, dot plots for enrich)
each one hand-built
one mark call
Chosen — Observable Plot
Near-term standard for story and enrich charts, rendered to static SVG at build time. planetary-boundaries-make-charts.mjs is the reference. Closes the near-term half of #11.
Still hand-rolled
A genuinely bespoke one-off visual, where fighting Plot's grammar costs more than writing the SVG. And the Keeling Curve charts, until they're next touched (#12).