Q2 revenue {l:20,45,60,80,95} is trending up — and that chart is just text.
Datatype is an open-source variable font that renders bar, line, and pie charts from plain text. The headline above contains the literal characters {l:20,45,60,80,95} — the font's ligatures turn them into a sparkline. No JavaScript, no SVG, no images.
Three chart types, one ligature trick
Wrap values in a curly-brace expression and set the font. OpenType contextual alternates (calt/liga — on by default in every modern browser) substitute the characters with chart glyphs.
Syntax & axes
| Type | Syntax | Rules | Example |
|---|---|---|---|
| Bar | {b:v,v,v,…} |
values 0–100, up to 20 bars | {b:25,50,75,100} |
| Line | {l:v,v,v,…} |
values 0–100, up to 20 points | {l:80,60,70,40,50,20} |
| Pie | {p:v} |
single value 0–100 (% filled) | {p:75} |
Two variable axes restyle every chart — the same way you'd restyle text:
Width wdth 50–150 controls density (how much horizontal room each point gets):
Weight wght 100–900 controls stroke thickness:
Practical floor: sparklines get muddy below ~14px — keep inline charts at body size or larger. Charts inherit color, so styling is plain CSS.
Agentic analytics: the LLM only has to emit text
Charts in AI answers normally require a rendering pipeline — the model calls a tool, something generates an image or a chart spec, the client knows how to display it. With Datatype, the model just writes characters. If the answer surface sets one font, every chart below is free:
Acme Industrial's parts orders climbed steadily through Q2 {l:32,38,35,44,51,49,58,63,61,72,78,84} — up 38% over Q1, with three of the last four weeks setting new highs.
The growth is concentrated in hydraulic assemblies {b:20,35,55,80}, which now make up 41% of their mix {p:41}. Electrical components held flat {l:50,52,49,51,50,48,51}, and everything else tracked seasonal norms.
If the current pace holds, Acme finishes the quarter about 22% above plan. Want me to break the hydraulics jump down by SKU?
Now the exact same bytes, in any other font — this is everything the model actually generated:
Acme Industrial's parts orders climbed steadily through Q2 {l:32,38,35,44,51,49,58,63,61,72,78,84} — up 38% over Q1, with three of the last four weeks setting new highs.
The growth is concentrated in hydraulic assemblies {b:20,35,55,80}, which now make up 41% of their mix {p:41}. Electrical components held flat {l:50,52,49,51,50,48,51}, and everything else tracked seasonal norms.
That's the whole trick. The chart payload is valid plain text, so it survives every layer that text survives: streaming tokens, markdown pipelines, copy-paste, logs, diffs, emails. The renderer is the font file — there is no renderer to build, version, or break.
Two declarations and a span
@font-face {
font-family: 'Datatype';
src: url('/fonts/Datatype[wdth,wght].woff2') format('woff2');
font-weight: 100 900;
font-stretch: 50% 150%;
font-display: swap;
}
.chart { font-family: 'Datatype', monospace; }
<p>Orders are up
<span class="chart">{l:20,45,60,80,95}</span>
38% this quarter.</p>
Ligatures are on by default, so no font-feature-settings are needed. To show the raw syntax (like this page's left-hand panels), disable them with font-variant-ligatures: none.
Font + source: github.com/franktisellano/datatype · docs: franktisellano.github.io/datatype