# Self-hosting the proxy

> What the proxy will and won't do, the endpoints it serves, and how to deploy your own.

The proxy is a small Nitro app in the [`proxy/`](https://github.com/unjs/unifont/tree/main/proxy) directory of the `unifont` repository. Provider APIs send no CORS headers, so it's how [browsers and web containers](/docs/browser) reach them at all.

Deploy your own if you resolve fonts in a browser or a web container at runtime and you need that to keep working. Nothing else needs it: on a server, in a worker, in CI, or at build time (what `@nuxt/fonts` and `fontless` do) the provider APIs are called directly.

## What it will and won't do

It's read-only, and narrow on purpose:

- `GET` and `HEAD` only, and only the routes below. Anything else is a `404`.
- Only the query parameters named per route. Everything else is dropped before the upstream call.
- Only the upstream `content-type` is carried back. No other upstream header is replayed.
- No credentials, no cookies, no auth, in either direction.
- Font files never go through it. They come from the provider's own CDN, which already allows cross-origin requests.

## Endpoints

`GET /` returns the endpoint list as JSON. Every route is versioned:

| Route | Upstream | Query |
| --- | --- | --- |
| `/adobe/v1/kit/:id` | `typekit.com/api/v1/json/kits/:id/published` | |
| `/adobe/v1/kit-css/:id` | `use.typekit.net/:id.css` | |
| `/bunny/v1/list` | `fonts.bunny.net/list` | |
| `/bunny/v1/css` | `fonts.bunny.net/css` | `family` |
| `/fontshare/v1/fonts` | `api.fontshare.com/v2/fonts` | `offset`, `limit` |
| `/fontshare/v1/css` | `api.fontshare.com/v2/css` | `f[]` |
| `/fontsource/v1/fonts` | `api.fontsource.org/v1/fonts` | |
| `/fontsource/v1/fonts/:id` | `api.fontsource.org/v1/fonts/:id` | |
| `/fontsource/v1/variable/:id` | `api.fontsource.org/v1/variable/:id` | |
| `/google/v1/fonts` | `fonts.google.com/metadata/fonts` | |
| `/google/v1/css` | `fonts.googleapis.com/css2` | `family`, `text`, `icon_names`, `format` |
| `/google/v1/icons` | `fonts.google.com/metadata/icons` | |
| `/google/v1/icon` | `fonts.googleapis.com/icon` | `family`, `format` |

`format` is one of `woff2` (the default), `woff`, `ttf` or `eot`. Each one maps to the user agent Google expects for that format.

Responses carry `cache-control` (`public`, `max-age` = `s-maxage`, plus `stale-while-revalidate`), an `etag`, and `304` support. Metadata is cached for six hours, generated CSS for a day, Adobe kits for five minutes.

## Deploying it

Nothing here needs a database, credentials or environment variables.

- **Vercel, Netlify, Cloudflare:** create a project with `proxy/` as the root directory. Nitro picks up the preset from the environment, and the build command is `pnpm build`.
- **Node:** `pnpm build`, then run `.output/server/index.mjs`.

Once it's up, `GET /` should return the endpoint list. Pointing `apiBase` at it is the only change your application needs:

```ts
const unifont = await createUnifont([providers.google()], {
  apiBase: 'https://fonts.example.com',
})
```

A fresh deployment is cold, so the first request for each endpoint waits on the upstream. The cache lives in the process, which on a serverless host means most of the work is done by the CDN in front. That's what the `cache-control` headers are for.
