| name | font-picker |
| description | Pick great free fonts for websites and apps from fonts.zander.wtf's hand-curated catalog of 71 typefaces. Use this whenever the user is choosing typography — a font for a new site, landing page, UI, blog, portfolio, docs site, or app; a code/terminal font; a pixel or retro font; a font pairing (heading + body); or asks for "a nice font", "something like Inter/Helvetica", "an interesting typeface", or alternatives to a commercial font. Also use it when scaffolding a new site's CSS and typography hasn't been decided yet. |
Font Picker
Recommend fonts from a curated, opinionated catalog of 71 free typefaces (fonts.zander.wtf) instead of defaulting to the same handful of overused Google Fonts. Every font in the catalog is free for commercial use, personally vetted, and has a live specimen page the user can look at — with interactive weight/axis sliders and OpenType feature toggles so they can try the font before committing.
Data sources
references/catalog.md — the bundled catalog, grouped by category (sans-serif, serif, mono, pixel, display). Read the relevant category sections before recommending anything.
https://fonts.zander.wtf/fonts.json — live JSON with the same data plus any fonts added since this skill was packaged, including fields the catalog summarises: weights, axesRanges (min/max/default per axis), features (OpenType toggles), fontsource (npm package), and googleFontsSpec (full css2 spec). Fetch it when network is available; fall back to the bundled catalog when it isn't.
- Specimen pages — every font has one at
https://fonts.zander.wtf/fonts/<slug>/. Always include specimen links in recommendations so the user can see the font before committing.
Workflow
- Pin down the job. What is the font for — UI text, long-form reading, headlines, code, branding, retro effect? What's the vibe (neutral, warm, technical, playful, elegant, brutalist)? If the user gave a reference ("like Stripe", "like a terminal"), translate that into category + vibe. Don't interrogate the user if context makes it obvious; infer and state your assumption.
- Read the matching category in the catalog (or filter the live JSON). Categories map to jobs:
- UI / product / marketing body → sans-serif
- Long-form articles / editorial / elegant branding → serif
- Code, terminals, tabular data, technical branding → mono
- Retro / game / lo-fi / CRT aesthetics → pixel (display sizes only — never body text)
- Big personality headlines → display (pair with a quieter text face)
- Shortlist 2–3 candidates, not one and not ten. For each, give one sentence on why it fits this project, and link its specimen page. Lead with your top pick and say so.
- Recommend a pairing when the project needs more than one role (most sites do): heading + body, and code font if relevant. Pairing heuristics:
- Contrast in category, harmony in mood: display or serif headlines + workhorse sans body; or a single variable font across roles using weight/optical-size axes.
- A characterful font gets one job only. Two loud fonts fight.
- When in doubt, one variable sans (e.g. one with
wght + opsz) covers headings and body cleanly.
- Implement it if the user is building: pick an install method (Google Fonts embed, Fontsource npm package, or self-host), give loading code, fallback stack, and licence note. See below.
Implementation
There are three ways to install a font — pick by the project's setup, then check the catalog entry's metadata for what's available:
-
Google Fonts (entry has Google Fonts: "Name") — zero-build, good for plain HTML/static pages. Use the entry's css2 spec verbatim (it encodes every weight and axis range, with spaces as + in the URL); trim it to the weights actually needed:
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Family+Name:wght@400..700&display=swap"
rel="stylesheet"
/>
For variable fonts request an axis range (wght@400..700), not comma-separated static weights.
-
Fontsource (entry lists a Fontsource npm package) — npm package, the best default for any project with a bundler (Vite, Next, Astro…): self-hosted output, versioned, no third-party requests. Prefer this over the Google Fonts embed when there's a build step.
npm install @fontsource-variable/family-name
import "@fontsource-variable/family-name";
body {
font-family: "Family Name Variable", sans-serif;
}
@fontsource-variable/* packages register the family as "<Name> Variable" and cover the full weight range. Static @fontsource/* packages load weight 400 by default — import extra weights as "@fontsource/family-name/700.css" and use the plain family name.
-
Self-host (entries marked self-host only, or whenever OpenType features matter — see below). Download from the entry's linked website/source, then:
@font-face {
font-family: "Family Name";
src: url("/fonts/family-name.woff2") format("woff2");
font-weight: 100 900;
font-display: swap;
}
Always:
- Give a real fallback stack, e.g.
font-family: "Inter", system-ui, sans-serif; (or ui-monospace, monospace for mono).
- Use
font-display: swap (or &display=swap).
- For variable fonts, mention the useful axes from the catalog entry — e.g. Fraunces'
SOFT/WONK, optical sizing via font-optical-sizing: auto. Every axis's min/max/default is in the live JSON's axesRanges.
- Note the licence (almost all are OFL; a few differ — the catalog flags them). If the entry lists a non-standard licence (CC BY, custom, freeware), tell the user to check terms for their use case.
OpenType features
Some entries list OpenType feature toggles (e.g. Inter's slashed zero zero, tabular numbers tnum, stylistic sets ss01…) — the same toggles are interactive on the font's specimen page. Enable them in CSS with:
font-feature-settings:
"zero" 1,
"ss01" 1;
Prefer the high-level properties where one exists (font-variant-numeric: tabular-nums slashed-zero;, font-variant-ligatures), since font-feature-settings is low-level and all-or-nothing per declaration.
Critical gotcha: Google Fonts and Fontsource serve stripped builds — most OpenType features are removed from the woff2 (Inter arrives with little more than pnum/tnum; zero, ss01, dlig, frac, case are gone). If the design needs a font's features, self-host the original files from the foundry/source instead. When in doubt, verify what a file actually contains with fontTools (pyftsubset/ttx) before promising a feature works.
Recommendation format
Keep it scannable — for each candidate:
Font Name — one sentence on why it fits. Specimen
Then the pairing suggestion and implementation snippet for the top pick. Don't dump the whole catalog on the user; curate.
Judgment notes
- Body text needs a workhorse: tall x-height, low contrast, tested at small sizes. The catalog descriptions call these out ("workhorse", "legible", "UI typeface").
- Accessibility ask (low vision, dyslexia-friendly) → Atkinson Hyperlegible is the purpose-built answer.
- "Something interesting / not Inter" is a request for character — reach for the less obvious entries, and say what makes them distinctive.
- Pixel fonts and heavy display faces at body sizes are a mistake; steer the user to a legible companion instead of just complying.
- The catalog is curated but small. If nothing genuinely fits (e.g. user needs Arabic script support, a specific corporate look), say so and recommend outside it — don't force a bad match.