# Getting started

> Install unifont, resolve a family, and turn the answer into CSS.

`unifont` is ESM-only, and has no peer dependencies.

```bash
npm i unifont
```

## Create an instance

`createUnifont()` takes an array of providers. Order matters. They're tried in turn, and the first one that knows the family wins.

```ts
import { createUnifont, providers } from 'unifont'

const unifont = await createUnifont([
  providers.google(),
  providers.fontshare(),
  providers.fontsource(),
])
```

## Ask what a family has

`getFontProperties()` tells you what a family publishes before you resolve anything. It returns `undefined` if no provider recognises the name.

```ts
const properties = await unifont.getFontProperties('Newsreader')

properties?.weights   // ['200 800'], a variable range
properties?.styles    // ['normal', 'italic']
properties?.subsets   // ['cyrillic', 'greek', 'latin', 'latin-ext', 'vietnamese']
properties?.provider  // 'google'
```

A missing field means the provider doesn't publish that information.

Variable families report a range as one `'<min> <max>'` string, rather than listing every weight.

## Resolve the faces

```ts
const { fonts, fallbacks, provider } = await unifont.resolveFont('Newsreader', {
  weights: ['400', '600'],
  styles: ['normal'],
  subsets: ['latin'],
})
```

`fonts` is an array of `@font-face` descriptors: `src`, `weight`, `style`, `unicodeRange`, and a `meta.subset` label if the provider gave one.

`fallbacks` holds the generic family the provider suggests (`serif`, `sans-serif`). (That's what you need if you're generating metric-adjusted fallbacks.)

## Turn it into CSS

`unifont` stops at the data. Writing it out takes a few lines, and doing it yourself means the CSS comes out the way you want it:

```ts
const css = fonts.map((face) => {
  const src = face.src
    .map(source => 'name' in source
      ? `local("${source.name}")`
      : `url("${source.url}")${source.format ? ` format("${source.format}")` : ''}`)
    .join(', ')

  return [
    '@font-face {',
    `  font-family: "Newsreader";`,
    `  src: ${src};`,
    face.weight ? `  font-weight: ${Array.isArray(face.weight) ? face.weight.join(' ') : face.weight};` : '',
    `  font-style: ${face.style ?? 'normal'};`,
    `  font-display: ${face.display ?? 'swap'};`,
    face.unicodeRange ? `  unicode-range: ${face.unicodeRange.join(', ')};` : '',
    '}',
  ].filter(Boolean).join('\n')
}).join('\n\n')
```

Or don't bother. Every family page on this site serves the same CSS at `/api/v1/fonts/<family>/css`, and the [API reference](/api) lists the parameters.

## Errors

If a provider fails, `unifont` logs it and carries on, so one dead API doesn't break your build. Pass `throwOnError` if you'd rather it stopped:

```ts
const unifont = await createUnifont([providers.google()], { throwOnError: true })
```
