DEV Community

Cover image for From st-core.fscss to ProvChart: Same CSS-Paint Idea, Built for Real Data
FSCSS tutorial for FSCSS tutorial

Posted on

From st-core.fscss to ProvChart: Same CSS-Paint Idea, Built for Real Data

st-core.fscss started as an FSCSS module with a clear bet: charts can be browser paint, not a JavaScript chart runtime. No canvas. No SVG dependency for the line. Data lives in CSS custom properties; shapes are clip-path: polygon(); optional JS only writes numbers. Compiled, it’s on the order of ~0.5 kb of CSS—not a 40–150 kb chart library.

That idea spread—writeups, demos, dashboard experiments—because it matched what performance-minded frontends already wanted: first paint is the chart, crawlers see markup, updates can be variable writes with free CSS transitions.

ProvChart is not a rejection of that model. It’s what you build when the same philosophy has to survive arbitrary series lengths, multi-series layouts, and a server-side compile step—without asking every team to hand-author mixins per dataset.


What st-core actually nailed

st-core’s contract is intentionally tight and easy to teach:

  • Eight points: --st-p1--st-p8
  • Fixed X stops: 0% 14% 28% 42% 57% 71% 85% 100%
  • Mixins like @st-chart-points, @st-chart-line, @st-chart-fill, dots, stats
  • Optional JS: element.style.setProperty('--st-p3', '42%') → browser repaints the polygon
.chart {
  position: relative;
  height: 200px;
  /* FSCSS: @st-chart-points(20, 35, 33, 30, 48, 35, 66, 37) */
}
Enter fullscreen mode Exit fullscreen mode

That is still a strong starter library for hand-built cards, marketing strips, and demos where eight samples are enough. It maximizes what the browser already does well. Nothing about ProvChart throws that away.


Where a fixed eight-point contract stops fitting

Real product data rarely arrives as “exactly eight numbers”:

  • Days in a month, weeks in a year, irregular sensor samples
  • Several series on one frame (revenue vs cost, traffic vs signups)
  • Automation: JSON from an API, not a mixin edited in a stylesheet

st-core’s elegance is that compile-time contract. ProvChart’s job is to keep data → variables → CSS geometry → paint when the point count and series count are decided per request, not per mixin signature.


What ProvChart changes (and what it doesn’t)

st-core.fscss ProvChart
Paint model CSS variables + clip-path / native CSS Same family of ideas
Point count Eight fixed slots Length of series[].points (no eight-slot ceiling)
Series Hand composition / multi-line patterns in FSCSS First-class multi-series, combo, bar, hbar, gauge, …
Authoring Mixins in source / FSCSS compile JSON → builder or Developer API
Client chart library None None for paint
Docs embeds Manual / CSS Optional generate-svg
Interaction Hand dots / attr() patterns Optional provchart-runtime

Unchanged belief: the chart is CSS. JavaScript should not be required to draw the shape.

Changed machinery: compilation can run on a server; geometry is generated for the payload you sent; roots are instance-scoped (classes like pc-… and variables such as --pc-{id}-s{series}-p{index}) so many charts can share a page without colliding.

There is no marketed “must be ≤ 200 points” product rule in this writeup. Practical limits are the usual ones: payload size, CSS complexity, and what stays smooth in real browsers—not an eight-argument mixin.


Server compile instead of only a <style> mixin

st-core path: FSCSS CLI or in-browser compile → you ship CSS you authored.

ProvChart path: send JSON, get markup:

const res = await fetch("https://provchart-api.devtem.org/api/v1/generate", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": process.env.PROVCHART_API_KEY,
  },
  body: JSON.stringify({
    type: "line",
    series: [
      { name: "Revenue", color: "#8b7bff", points: [20, 35, 45, 30, 50] },
    ],
    axisX: ["Jan", "Feb", "Mar", "Apr", "May"],
  }),
});

const data = await res.json();
// data.html + data.css → inject; first paint is the chart
Enter fullscreen mode Exit fullscreen mode

Five points or fifty—it’s the same call shape. For README and Markdown surfaces, POST /api/v1/generate-svg returns SVG / data URI without requiring a chart runtime on the doc page.


provchart-runtime: interaction without owning paint

st-core already showed the interaction seed: a dot, a tooltip, data on the element, CSS doing the rest.

provchart-runtime (MIT, npm provchart-runtime) generalizes that for generated HTML charts:

  • Finds [data-provchart]
  • Skips pure SVG exports when configured
  • Scroll reveal, legend focus, per-point tooltips (reading generated custom properties where present)
  • MutationObserver for charts injected after load
<script>
  window.ProvChartRuntimeConfig = {
    tooltips: true,
    perPointTooltips: true,
    observe: true,
    excludeSvg: true,
  };
</script>
<script
  src="https://cdn.jsdelivr.net/npm/provchart-runtime@1.0.0/dist/provchart-runtime.min.js"
  defer
></script>
Enter fullscreen mode Exit fullscreen mode

Additive on purpose: generate output does not depend on the runtime; the runtime does not replace the engine.


The stack, honestly drawn

st-core.fscss (open source, viral pure-CSS chart idea)
  --st-p1…p8 · fixed X-stops · mixins · ~0.5kb compiled CSS
  JS optional: write variables, CSS transitions animate polygons
        │
        ▼
ProvChart (chart.devtem.org)
  Same paint philosophy · variable-length series · multi-series types
  Builder + Developer API → static HTML/CSS (and SVG for docs)
        │
        ▼
provchart-runtime (optional)
  Tooltips / motion / legend UX on HTML charts only
Enter fullscreen mode Exit fullscreen mode

When to use which

Use st-core when… Use ProvChart when…
You want full control in FSCSS/CSS source Data is JSON from backends, CI, or agents
Eight points (or st-core’s patterns) fit the story Series length and count change per view
You’re deep in the FSCSS module ecosystem You want API keys, quotas, SVG export, dashboard builder
Maximum clarity for teaching pure CSS charts Production multi-series, combo, gauge, automation

Many teams will use both: st-core for crafted marketing cards; ProvChart when the dataset refuses to stay eight samples long.


st-core.fscss proved a viral, high-performance idea—browser-native paint, minimal JS, no chart-library tax. ProvChart keeps that idea and removes the fixed-slot ceiling so the same belief works when the numbers come from a database, not a mixin call.


Top comments (0)