# Your statics do not interpolate and never will

> Convert a static font to a variable font by making every weight interpolable, then merging with fontmake. The free static-to-variable CLI does the merge.

*Product & craft*

Published Jul 28th, 2026

Updated Sep 5th, 2026

Going from a variable font to statics is one command in a loop. Going the other way means making hundreds of glyphs match across every weight before anything can merge, and almost everything written about variable fonts answers the easy direction.

Based on building static-to-variable, an open-source CLI for converting static font families into variable fonts.

A variable font stores one drawing of each glyph, meaning every letter, digit and symbol in the font, plus a note of how far every point moves as it gets bolder. For that to work, every weight has to be drawn the same way: same number of points, same order, same direction round the outline, starting from the same spot. I built [static-to-variable](/static-to-variable) to get a folder of separately drawn weights into that state.

Fonts drawn one weight at a time have no reason to match like that, and mostly don’t. The designer drew a Bold. They didn’t draw a Bold whose e has the same number of points as the Regular’s e.

## The hard direction

The merge was never the problem. fontmake does the merge. The time goes on making 700-odd glyphs match across every weight without changing how any of them look.

Some of what breaks is obvious once you see it. A glyph exists in the Light and not in the Black. An outline runs clockwise in one weight and anticlockwise in another. Both are cheap to spot and cheap to fix.

The ones that cost me days looked fine. A B has two holes in it, and at ExtraBlack they swap places in the file. Same number of outlines, same number of points, same direction, so every simple check passes. Then one hole blends into the other and the letter collapses halfway between the weights.

The shape itself changes too. A ¢ loses a hole at the heavy weights, because the gap in the middle fills in with ink. So the heavy weights get a fake hole shrunk to almost nothing, and the real one closes up gradually instead of vanishing between one weight and the next.

## The invisible one

The worst kind is a wrong start point, because nothing structural can see it. An o is all curves whichever point you start from, so it reads the same no matter where the outline begins. Compare two weights and nothing looks wrong. Blend them and every point pairs up with the wrong one.

Where the point counts disagree, the outline gets redrawn with points added until they match, pinned at the corners so the shape doesn’t shift. Only the outlines that disagree get touched, because every redraw loses a little.

One broken glyph fails the whole build, so the scale of it only shows up in the rebuild log. 755 glyphs came out of the original files and 641 of them had to be reconstructed before anything would merge. That is about 85%. That is not a handful of broken glyphs. That is the normal condition of independently drawn statics.

All of that structural work to produce a font that, on screen, is identical to what the designer drew.

## A frozen cent sign

Every rebuild has to be checked, because a bad one is worse than none at all. Matching structure isn’t enough on its own, and neither is measuring the ink: a twist that folds an outline through itself keeps exactly the same amount.

The line I settled on is 10%: if a rebuilt glyph gains or loses more than a tenth of its ink at any weight, it fails. Good rebuilds come in under 6% and genuinely mangled ones sit above 20%, with almost nothing in between. That empty gap is why 10% is the number.

A glyph that fails every check gets frozen to the Regular’s drawing. It renders correctly at every weight, it just doesn’t get bolder. Turns out that’s the tool working rather than the tool failing. A frozen ¢ is fine. A ¢ that folds inside out at weight 550 is not.

The loop around all of it runs up to 40 times. Build the font, generate it at every weight and halfway between each pair, freeze whatever collapses, build again, until nothing new breaks.

If you have permission to modify the font, the free [Static to Variable CLI](/static-to-variable) runs that loop from a folder of separate weights:

```bash
npm install -g static-to-variable
static-to-variable init
static-to-variable build
static-to-variable release
```

`init` finds the weights and writes `stv.config.json`. `release` puts the final TTF and WOFF2 in `build/`. Run `static-to-variable doctor` if a stage stops, then use the [CLI docs](https://github.com/mblode/static-to-variable/tree/main/packages/cli) for the full flags and configuration. Try the converter on a font you own or have permission to modify.

Then you open it in Figma, where variables attach to named styles rather than axes, so a variable font is a static font with extra steps.

It took a week to get a cent sign to sit still.

## Related

- [Static to Variable](https://blode.co/static-to-variable)
- [Static to Variable CLI docs](https://github.com/mblode/static-to-variable/tree/main/packages/cli)
- [Glide](https://blode.co/glide)
- [You don’t have to make AI slop](https://blode.co/writing/you-dont-have-to-make-ai-slop)
- [Projects](https://blode.co/projects)
