Kern
Font pairing scored against measured type data, not vibes.

468
Families measured in a real browser
5
Roles: display, text, UI, mono, accent
4
Scored dimensions per pairing
0
Runtime font loads needed to score
Why this exists at all.
Pairing tools show two typefaces on a card and wish you luck. The recommendation comes from a hand-maintained list of pairs somebody liked, which cannot explain itself, cannot be checked, and cannot tell you why a third face would break the set.
What a build actually needs is a type system: two to five roles, working together, exportable as something a stylesheet or an agent can consume directly.
The decisions, and what they rule out.
Measure the catalogue once, in a real browser
Every family was rendered and measured, x-height ratio, character width, ink density, and the numbers ship inside the bundle. Where a family carries no metrics, they are derived from `actualBoundingBoxAscent` on a live canvas. No runtime font loading to compute a score, and no guessing from a name.
Score on relationships, then show the reasoning
A pairing scores on classification contrast, x-height rhythm, width rhythm and typographic colour. The reasoning is worn openly: chips under the display slot read things like 'x-height rhythm 0.89 · close' and 'width rhythm 1.05'. A score with no visible derivation is an opinion with a number stuck on it.
Deal, don't recommend
Repeat calls return different pairs by design. The tool is not claiming one correct answer exists; it is claiming these pairs satisfy the measured constraints, and here are the numbers so you can disagree.
The things thinking about it did not catch.
Every item below is a real defect, found by measurement, with a commit behind it. They are here because the failures are more informative than the features.
Mood words cannot promise typographic classification
The catalogue carries usage tags, not classifications. A 'geometric' filter therefore means sans-over-sans, not geometrically-classified faces, and until that was caught, the tool was making a promise its data could not keep. It now states the rule each mood actually applied, without implying a precision it does not have.
The engine's own advice was checked against the engine
This studio's site needed a free stand-in for a commercially licensed grotesque. Instead of picking by eye, the catalogue was queried and the substitute chosen on measured x-height: 0.750 against the mono's 0.746, a ratio of 0.995. That is the calculation the tool exists to perform, and it held up when used in anger.
Superfamilies are the reliable deal
Faces designed together as a family score consistently well, which is unsurprising and worth encoding rather than rediscovering. They were added as a distinct category in the hand rather than left to emerge from the general scoring.
- TypeScript
- Vite
- Canvas metrics
- Google Fonts + Fontshare
Nothing outstanding. It does what it was built to do, and the known limits are described above rather than parked here.
Free, no account, running right now.
kern-fonts.vercel.app