Turn a folder of separate weights into one variable font that slides across everything in between
Point it at your thin, regular, and bold files and it redraws each weight onto a shared skeleton so the outlines interpolate.
Drag the weight axis on a font built by this pipeline.
npm install -g static-to-variableNeeds Node 24.11+, Python 3.11+, and uv, which the CLI uses to run the font toolchain.
From a folder holding your static font files:
static-to-variable init # finds the fonts, writes stv.config.json
static-to-variable build # variable font into build/
static-to-variable release # final TTF and WOFF2Run static-to-variable doctor if a stage fails.
| Command | Description |
|---|---|
static-to-variable init |
Scan the folder for fonts and write stv.config.json |
static-to-variable build |
Build the variable font into build/ |
static-to-variable release |
Produce the shippable TTF and WOFF2 |
static-to-variable split MyFamily-VF.ttf |
Reverse it, one static TTF and WOFF2 per weight step |
static-to-variable doctor |
Report readiness: node, python, uv, and config |
static-to-variable status |
Print the aggregate pipeline status report |
- Bundling static fonts into one file does not work, because their outlines do not correspond point for point. This redraws them instead, and skips any glyph it cannot convert cleanly rather than shipping a broken interpolation.
- Italics, named instances, and per-glyph fixes are config: see the schema and the Inter example.
- Teach your coding agent the CLI with
npx skills add mblode/static-to-variable. - The full flag reference lives in the CLI docs.
The code is MIT. Your fonts keep their own licenses, and that matters: converting a font counts as modifying it, which most commercial EULAs forbid, so you need the foundry's permission. Open licenses like the SIL OFL (most of Google Fonts) allow it. Your own fonts are fine.
Crafted by Matthew Blode