# Finding a typeface by its character, and shipping it

> `osy font find` searches ~1,900 open-source families by what they are like — calm, playful, geometric, humanist, a didone, handwritten — and shows each one's weights and licence. `osy font add --fontsource <id>` fetches the one you chose, vendors it into the project with its licence, and pins it, under the family's real name.

<!-- id: local-finding-a-font · area: local · stability: stable · html: https://osysharp.com/reference/local/finding-a-font/ -->

## Summary        {#summary}

Choosing a face on purpose ("a rounded geometric sans for both", "a high-contrast didone over a grotesque" —
[[ui-design#direction]]) needs a catalogue you can ask by character, and shipping it needs the file and its licence in
your project. `osy font find` is the first; `osy font add --fontsource` is the second. Nothing is downloaded by hand,
and the CSS family name is the catalogue's, never a guess from a file name.

## Signature      {#signature}

```console
osy font find "<character>" [--limit <n>] [--json]
osy font add --fontsource <id> [--weight 400,700] [--style italic] [--subset <subset>] [--axis opsz] [--family "<name>"]
```

## Description    {#description}

### Finding a face    {#find}

Give it the words you would use about the face. Each word is matched against the family's name, its category (serif,
sans, display, handwriting, monospace) and its **character** — Google Fonts' own classification, which scores every
Google family 0–100 on qualities such as *Calm*, *Playful*, *Sophisticated*, *Vintage*, *Futuristic* and on kinds such as
*Geometric*, *Humanist*, *Grotesque*, *Rounded*, *Didone*, *Slab*, *Handwritten*. Families with every word come first,
strongest first:

```console
$ osy font find "rounded geometric"
╭───────────┬──────────────┬──────────────────┬─────────┬───────────────────────────────────────╮
│ Family    │ --fontsource │ Weights          │ Licence │ Why                                   │
├───────────┼──────────────┼──────────────────┼─────────┼───────────────────────────────────────┤
│ Comfortaa │ comfortaa    │ 300–700 variable │ OFL-1.1 │ Sans/Rounded 100 · Sans/Geometric 100 │
│ Fredoka   │ fredoka      │ 300–700 variable │ OFL-1.1 │ Sans/Rounded 100 · Sans/Geometric 100 │
│ Quicksand │ quicksand    │ 300–700 variable │ OFL-1.1 │ Sans/Rounded 100 · Sans/Geometric 100 │
╰───────────┴──────────────┴──────────────────┴─────────┴───────────────────────────────────────╯
  Ship one: osy font add --fontsource comfortaa — its files and its licence, pinned.
```

A family that matched only some words says how many (`(1/2)`). A family outside Google Fonts has no character scores
and is found by its name and category only. The catalogue comes from [Fontsource](https://fontsource.org) and the
character scores from Google Fonts' published tag file; both are kept in `~/.osy/fonts/` for a day, and an unreachable
source answers from the last copy, saying how old it is. `--json` prints the matches for a tool.

### Shipping it    {#add}

```console
$ osy font add --fontsource fraunces
✓ Registered Fraunces (7f9d191d9993…) → model/fonts/fraunces-latin-variable-normal.woff2 — a variable font, weights 100–900
  …
  From Fontsource (OFL-1.1); its licence is beside it as fraunces-LICENSE.txt — keep it with the font.
```

A family that has a **variable** file arrives as that one file, covering every weight it has. A family without one
arrives as a file per weight — **400 and 700** unless `--weight` names others (`--weight 300,500,800`, which also asks
for static files of a variable family). `--style italic` takes the italic, `--subset` a character set other than the
family's own (usually `latin`; `latin-ext` for more European letters). The project is the current one, or the folder
given after the options.

**A family drawn with more than a weight axis** — an optical size (Inter, Fraunces), a width, a slant — has a second
variable file that carries it. `--axis opsz` (or `wdth`, `slnt`, `full` for every axis) takes that file instead:

```console
$ osy font add --fontsource inter --axis opsz
✓ Registered Inter (2c295d99e26d…) → model/fonts/inter-latin-opsz-variable-normal.woff2 — a variable font, weights 100–900
```

With the optical-size axis in the file the browser draws large text in the family's display cut and small text in its
text cut by itself, and `fontVariationSettings: "'opsz' 32"` sets it by hand. Without it both do nothing, and nothing
says so — which is why the axis is asked for by name and a family that has no such file is refused rather than given
its weight-only one.

What happens next is exactly [web fonts — shipping a typeface with your app](https://osysharp.com/reference/ui/web-fonts/): the file is pinned in `osyrin.lock`, every compile ships it, and the
printed hint shows the `Font { Sans = … }` line that makes every control use it. The licence text is written beside the
file — the full text when Fontsource publishes it, otherwise a note naming the licence and where the font came from.

## See also       {#see-also}
- [web fonts — shipping a typeface with your app](https://osysharp.com/reference/ui/web-fonts/) — what a registered font does, and naming it in the theme
- [Designing an app that looks designed — direction, type, colour, composition and motion](https://osysharp.com/reference/ui/design/) — choosing a type pairing on purpose
- [Looking at a reference site before you design](https://osysharp.com/reference/local/looking-at-a-reference/) — `osy design look`: see which faces a reference site loads
- [theme tokens](https://osysharp.com/reference/ui/theming/) — the `Font` tokens
