A palette and plug-and-play React/MDX figure system for editorial data stories.
An open-source editorial system by La Matemaga.
Sterling is for people who publish charts inside Markdown and do not want every post to reinvent its visual language. A single figure shell keeps hierarchy, a QED-like title mark, captions, source treatment, exports, colour grammar, and accessible chart labels consistent across an entire blog or documentation site. Chart primitives draw the data; the shell keeps the editorial contract.
The name is associated with little star and with the standard of precious metals: a useful metaphor for visualizations that aspire to clarity, consistency, and care.
Status: pre-release extraction. The package source is ready to become independent; it has not been published to npm yet.
- A reusable
SterlingFigurewrapper for React and MDX. - D3/SVG chart primitives: bars, scatterplots, lines, histograms, boxplots, violins, heatmaps, correlation matrices, lollipops, pie/donut, chord, Sankey, candlestick, radar, ridgeline, treemap, network, dendrogram, volcano, Manhattan, expression, geographic map, and more.
- A colour system with categorical, sequential, diverging, heat, and per-category sequential ramps.
- A
createTailwindSterlingPalettehelper for Tailwind-style100–950colour scales. Tailwind itself stays optional. - MDX registration, localized English/Spanish interface copy, title/caption conventions, and inline legends.
- Image copy, PNG export, Web Share support where available, and CSV export of the processed rows behind a figure.
Sterling intentionally does not include La Matemaga’s original datasets, site pages, images, or visual examples. It is the reusable library layer only.
Using an AI coding agent? Start with
AGENTS.md. It gives agents an editorial/data contract, the questions to ask before generating a figure, configuration rules, and a reproducible export workflow for slide-deck assets.
- Sterling: a palette for data with a voice of its own is the construction chronicle: why the system exists, how its editorial and statistical decisions were made, and what it means to publish data stories that are shareable, traceable, and worth revisiting.
- The live visualization catalog lets you explore Sterling’s current chart species in context. It is the visual reference for the system; this README remains the source for installation and implementation details.
- The deployed consumer smoke test is a minimal Vite report that imports the published package, renders all 150 iris observations, and switches the whole report among Sterling, Tableau, Power BI, Matplotlib, and Base R themes. Its source is intentionally small enough to copy as an installation reference.
npm install @lamatemaga/sterlingnpm install ../sterlingSterling requires React and React DOM 18.2 or later (React 18 and 19 are supported). D3 modules, html-to-image, lucide-react, and topojson-client are normal package dependencies and install with Sterling. The local package's prepare script builds dist during installation; Next.js, MDX, and Tailwind are optional integrations.
Import the base styles once in your app entry point:
import "@lamatemaga/sterling/styles.css";The package root is an explicit React client boundary: use it for figures, MDX registration, and browser actions. Static SVG primitives, palette helpers, CSV helpers, and types are also available from the server-safe subpath:
import { defineSterlingPalette, SterlingScatterPlot } from "@lamatemaga/sterling/server";import {
SterlingBarChart,
SterlingFigure,
sterlingCredit,
type SterlingDataExport,
} from "@lamatemaga/sterling";
const rows = [
{ treatment: "A", mean: 14.5 },
{ treatment: "B", mean: 15.3 },
{ treatment: "C", mean: 2.1 },
];
export function TreatmentMeans() {
return (
<SterlingFigure
labelPrimary="Bars"
labelSecondary="Categorical"
title="Treatment means at a glance"
subtitle="Means calculated from the complete processed dataset."
source="Your published source"
size="wide"
signature={sterlingCredit({ author: "Your name" })}
dataExport={{ rows, fileName: "treatment-means" } satisfies SterlingDataExport}
>
<SterlingBarChart
data={rows.map(({ treatment, mean }) => ({ label: treatment, value: mean }))}
ariaLabel="Mean value by treatment"
/>
</SterlingFigure>
);
}size is optional and defaults to medium. Use compact, medium, wide, or full. Every figure also accepts palette, editorial, signature, sourceLabel, titleMarkHref, className, and style; omitted fields keep Sterling’s defaults.
Register the components once. Dataset-backed wrapper components stay in your own project, which lets your data and source citations live wherever your publishing workflow needs them.
import { createSterlingMdxComponents, sterlingCredit } from "@lamatemaga/sterling";
import { IrisScatterFigure } from "./IrisScatterFigure";
export const mdxComponents = createSterlingMdxComponents({
locale: "en",
figureDefaults: {
editorial: { titleMark: "." },
signature: sterlingCredit({ author: "Ada Lovelace" }),
},
additionalComponents: { IrisScatterFigure },
});Then use it in an .mdx file:
<IrisScatterFigure />Sterling’s defaults are intentionally portable:
- The title gets a non-linking
.by default; it can be removed or linked. - The default caption credit is a link to Sterling:
Made with Sterling ✦. - Set the credit to your own author with
sterlingCredit({ author: "Your name" }), which becomesMade by Your name with Sterling ✦. - Consumers may remove or replace the credit entirely. The link is a useful attribution default, not a lock-in.
<SterlingFigure
// Everything below is optional.
editorial={{
titleMark: "∎",
titleMarkHref: "/",
titleMarkLabel: "Back to home",
sourceLabel: "Data source",
}}
signature={false}
{...figureProps}
/>To preserve the original La Matemaga treatment, set your own signature and editorial in the consuming site; the library contains no site-specific branding.
Sterling starts in light mode. Add data-sterling-theme="dark" or .sterling-theme-dark on an ancestor for its dark surface. The package uses local CSS variables, so it does not change your site’s global theme.
<main data-sterling-theme="dark">
<TreatmentMeans />
</main>The base stylesheet stays neutral and inherits your publication's type system.
For Sterling's complete editorial treatment, import the optional stylesheet after
the base one. It bundles Fraunces SemiBold and JetBrains Mono under their OFL
licenses; see assets/fonts/NOTICE.md.
import "@lamatemaga/sterling/styles.css";
import "@lamatemaga/sterling/editorial.css";Or load your own display, sans, and mono fonts, then map them:
:root {
--sterling-font-display: "Fraunces", Georgia, serif;
--sterling-font-sans: "Inter", system-ui, sans-serif;
--sterling-font-mono: "JetBrains Mono", ui-monospace, monospace;
}Pass palette to a figure to override only the parts you need. defineSterlingPalette preserves literal values and provides TypeScript autocomplete.
Sterling includes colour-vision-tested categorical subsets; it is deliberately not presented as a universally safe eight-colour palette. The full default palette passes simulations for protanomaly, deuteranomaly, tritanomaly, and achromatomaly. For simulated full dichromacy, use the validated reduced subsets: six colours for protanopia, and seven colours for deuteranopia or tritanopia. Achromatopsia is the most restrictive case and requires a validated four-colour subset.
These limits are part of the reading contract, not an afterthought. When categories carry meaning, pair colour with a clear inline legend, labels, shape, position, or another redundant cue. If your audience includes people with a specific colour-vision deficiency, select and test the appropriate subset rather than assuming that any arbitrary selection of Sterling colours will remain distinguishable.
import { defineSterlingPalette } from "@lamatemaga/sterling";
const studioPalette = defineSterlingPalette({
surface: { paper: "#fffdf8", plot: "#fff", text: "#18211e", grid: "#dae2dc" },
categorical: ["#7c3aed", "#0f766e", "#db2777", "#d97706"],
legend: ["#5b21b6", "#115e59", "#9d174d", "#92400e"],
});
<SterlingFigure palette={studioPalette} {...figureProps} />Use Tailwind’s colour objects without adding Tailwind as a Sterling runtime dependency. Categorical 500 values become marks, 700 values become inline-legend text, 100–950 become sequential/diverging/heat stops, and 200–800 become per-category ramps.
import { amber, blue, fuchsia, lime, rose, slate, teal, violet } from "tailwindcss/colors";
import { createTailwindSterlingPalette } from "@lamatemaga/sterling";
const tailwindPalette = createTailwindSterlingPalette({
categorical: [violet, teal, fuchsia, amber, blue, rose, lime, slate],
divergent: teal,
heat: amber,
surface: {
paper: slate[50], plot: "#ffffff", plotAlt: slate[100], text: slate[950],
muted: slate[600], grid: slate[200], edge: slate[300], period: violet[600],
},
});The helper is deliberately a starting point: choose a divergent scale for values around a meaningful midpoint, a sequential scale for ordered magnitude, and a categorical palette only for distinct groups. For an otherwise neutral visualization with one highlighted region, pass a neutral surface/series palette and a deliberate color on the selected mark or wrapper component.
Provide dataExport={{ rows }} with the exact processed data rendered by the figure. Sterling turns those rows into a UTF-8 CSV from its action menu; it does not pretend to redistribute an original source dataset. This makes the summarized table inspectable without asking readers to reverse-engineer pixels.
Every primitive requires an ariaLabel. Keep source text in the figure caption, use legends in the subtitle for categorical colour/shape encodings, and retain meaningful field names in dataExport whenever possible.
The top-right controls intentionally remain compact:
- Copy image is always visible.
- Export or share opens PNG download, processed CSV download, and native system sharing on compatible devices.
When installed from npm:
npm update @lamatemaga/sterlingFor intentional major-version updates:
npm install @lamatemaga/sterling@latestWhen installed from a local checkout, pull the desired commit in the Sterling folder, run npm install there, and reinstall the local path in the consuming app. prepare rebuilds the package automatically:
git pull
npm install
cd ../your-site
npm install ../sterlingRead the release notes before upgrading a major version. Keep the stylesheet import in place; a package update does not add it automatically.
npm install
npm run typecheck
npm run build
npm run test:consumer
npm pack --dry-runThe public client entry point is src/index.ts; src/server.ts exposes the
server-safe static API. Do not import internal source files from applications.
Keep all chart geometry inside primitives, and keep editorial decisions in
SterlingFigure or your own wrapper. A change to shared tokens should make all
affected chart types more consistent, not merely improve one example.
Sterling is designed to grow in the open. Contributions are welcome, especially when they preserve the package’s editorial grammar and data integrity.
- Additional chart primitives and small-multiple/composition layouts.
- A first-class scale selector: categorical, sequential, diverging, and neutral-with-highlight modes.
- A neutral-scale/highlight API for calling out an interval, region, or observation without turning the entire chart categorical.
- More accessible descriptions, keyboard affordances, and export test coverage.
- A visual regression suite for light, dark, and print surfaces, beginning with five high-risk specimens (violin, correlogram, heatmap, scatterplot, and exported figure) across the three modes.
- Framework adapters and downloadable palette artifacts for R, Python, Julia, and other visualization ecosystems. These are explicitly future work, not part of this initial package.
Use the feature request form to propose a component or capability. Bring the reading task, a public or synthetic data shape, accessibility considerations, and success criteria; a sketch or reference is welcome. For a pull request, keep the data transformation explicit, add a focused fixture, maintain the shared opacity/outline tokens, and document any new public prop. See CONTRIBUTING.md for the full guide.
- Read CONTRIBUTING.md before opening a pull request.
- Use the feature request form for a component or capability, or the bug report form for reproducible behavior that differs from the documented contract.
- Contributions follow the Code of Conduct.
- Report vulnerabilities through private vulnerability reporting, not in a public issue. See SECURITY.md.
Sterling is licensed under the MIT License. Release history follows Semantic Versioning in the changelog.
Sterling was conceived, art-directed, and reviewed by La Matemaga. Product, brand, and data-visualization decisions remained under that direction throughout implementation.
- OpenAI Codex: GPT-5.6 Sol High was the principal implementation collaborator through the core-system build; GPT-5.6 Terra High carried final fidelity corrections, open-source extraction, package hardening, and release verification. Both worked under La Matemaga's product, art direction, and review.
- Anthropic Claude: Opus 4.8 for a data-visualization correctness pass—auditing the component set against the v1.5 reference, using R/ggplot2 as the verification oracle, building the shared D3 axis foundation, and porting the clustered expression matrix from the original implementation. It was used after Fable blocked work involving bioinformatics charts. Directed and reviewed by La Matemaga.
- R: transformed source datasets into JSON and served as the verification oracle. Canonical ggplot2 renders were compared with the React implementation to validate distributions, outliers, palette ramps, and scales.
- Skills/methods:
design-taste-frontend(editorial anti-slop interface discipline) andvisualize(data visualization exploration). - Product demo video: a Full HD 16:9 Sterling demo was produced in Cursor with Remotion. It uses live Sterling figures and source data—not mock charts—to move from the article and embedded legends through MDX installation, responsive figure sizing, exports and sharing, theme comparison, and the portfolio visualization catalog. Its production used
appshot-videosfor the Remotion/Appshot workflow,frontend-designfor typography and visual QA, andhallmarkfor editorial-composition review and anti-slop cleanup. The main implementation/design agent was GPT-5.6 Terra; no model-specific subagents were run.
The original site and live system are documented at lamatemaga.com/sterling.
Codex was used as an implementation collaborator under La Matemaga's product, art-direction, and data-visualization review—not as a substitute for those decisions.
GPT-5.6 Sol High — core system build. Sol was the principal Codex implementation collaborator for the work that turned the v1.5 field tests into a working editorial system. Under La Matemaga’s direction, it helped establish reusable visual tokens and figure contracts; build the shared React/MDX figure shell; and integrate the palette, chart primitives, localized interface copy, inline legends, source and caption treatment, responsive editorial widths, and export interactions. It also supported the live Sterling article, portfolio feature, and visualization catalog that made the system inspectable in context. The important architectural result was that a correction to hierarchy, captioning, palette, or interaction could propagate across every installed figure rather than being redone chart by chart.
GPT-5.6 Terra High — fidelity, extraction, and release hardening. Terra handled the exacting last mile: preserving the site’s editorial typography and light/dark behavior; unifying opacity and outline decisions while retaining semantic exceptions such as the violin’s interquartile interval; refining portable component APIs and their documentation; and separating Sterling from the La Matemaga website into an installable package. It defined the public client/server entry points, stylesheet and font boundary, configurable palette and attribution helpers, Tailwind-scale helper, consumer smoke test, package build, and publishable tarball verification. This was not cosmetic cleanup: it made the system safer to adopt in another Markdown/React site without inheriting the originating website’s code or branding.
All generated work was directed and reviewed by La Matemaga. R/ggplot2 checks, comparison against the v1.5 reference, and visual review of the live site were used to validate the resulting implementation.
