zelto.

Docs

Install fonts like components.

Quick start

Pick a font from the catalog and run the add command in your project root:

$ npx zelto-fonts add inter

The CLI detects your setup, downloads the .woff2 files into your project, and generates ready-to-use code. No package dependency, no external requests at runtime — you own the files.

Next.js (App Router)

Font files land in app/fonts/<name>/ and a module is generated at app/fonts/<name>.ts using next/font/local:

import { inter } from "./fonts/inter";

// app/layout.tsx
<html className={inter.variable}>

Then wire it into Tailwind v4 in globals.css:

@theme inline {
  --font-sans: var(--font-inter);
}

React / Vite

Files land in public/fonts/<name>/ with an @font-face stylesheet at src/styles/fonts/<name>.css:

// src/main.tsx
import "./styles/fonts/inter.css";

/* anywhere in CSS */
font-family: var(--font-inter);

CLI reference

npx zelto-fonts add <name>     install a font
  --force                      overwrite existing files
  --dir <path>                 override the font files directory
  --registry <url>             use a different registry

npx zelto-fonts list           list all available fonts

Registry API

The registry is plain static JSON — usable by anything, not just the CLI:

GET https://fonts.zelto.app/r/registry.json      full catalog
GET https://fonts.zelto.app/r/<name>.json        single font
GET https://fonts.zelto.app/r/fonts/<name>/*     woff2 files + license

Self-hosting

Point the CLI at your own mirror with --registry or the ZELTO_REGISTRY_URL environment variable. File URLs in the registry JSON are relative, so a full mirror is just a copy of /r.

Licenses

Every font in the registry uses the SIL Open Font License (or equivalent). The license text is downloaded next to the font files — keep it there; the OFL requires it to accompany the fonts.