Datatype · variable font · raylytics dev showcase

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.

How it works

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.

You type — bar
{b:15,45,80,30,60,90,20}
Browser renders
{b:15,45,80,30,60,90,20}
You type — line (sparkline)
{l:10,40,25,70,50,90,35,60}
Browser renders
{l:10,40,25,70,50,90,35,60}
You type — pie
{p:62}
Browser renders
{p:62}
Cheatsheet

Syntax & axes

TypeSyntaxRulesExample
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):

{l:10,60,30,80,50,95,40}wdth 50 — condensed
{l:10,60,30,80,50,95,40}wdth 100 — default
{l:10,60,30,80,50,95,40}wdth 150 — expanded

Weight wght 100–900 controls stroke thickness:

{l:10,60,30,80,50,95,40}wght 200
{l:10,60,30,80,50,95,40}wght 400
{l:10,60,30,80,50,95,40}wght 800

Practical floor: sparklines get muddy below ~14px — keep inline charts at body size or larger. Charts inherit color, so styling is plain CSS.

The pitch

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:

analytics assistantwith datatype
VP, Service Ops
How did Acme Industrial's parts orders trend this quarter?
Assistant

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:

analytics assistantwithout datatype — same text
Assistant

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.

Integration

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

Playground

Try it

{l:10,40,25,70,50,90,35}