<!--
SPDX-FileCopyrightText: 2026 Andre Anjos (github:anjos)

SPDX-License-Identifier: LPPL-1.3c
-->

# geist-font — LaTeX support for the Geist, Geist Mono and Geist Serif typefaces

The `geist-font` CTAN distribution provides the `geist`, `geistmono` and
`geistserif` LaTeX packages for [Geist](https://github.com/vercel/geist-font),
the sans-serif, monospaced and serif typeface family designed by Vercel. Geist
and Geist Mono are covered in all nine weights (Thin through Black) with
matching italics; Geist Serif, a display serif, in its four variants.

The packages work with **pdfLaTeX**, **XeLaTeX** and **LuaLaTeX**. Under XeLaTeX
and LuaLaTeX the fonts are used directly through `fontspec`. Under pdfLaTeX
the packages use metrics generated with `autoinst`: Geist and Geist Mono come
as Type1 fonts, because pdfTeX cannot subset CFF-flavoured OpenType, while
Geist Serif's TrueType fonts are embedded as they are.

## Usage

```latex
\usepackage{geist}      % Geist as the sans-serif family
\usepackage{geistmono}  % Geist Mono as the typewriter family
\usepackage{geistserif} % Geist Serif as the roman family
```

To set Geist as the document's main font:

```latex
\usepackage{geist}
\renewcommand{\familydefault}{\sfdefault}
```

Geist ships nine weights, more than NFSS's traditional series axis exposes. The
usual `\textbf` and `\textit` work as expected, and the additional weights are
reachable through `\fontseries`; see the package documentation for the full
weight table.

Geist Serif comes in four variants that differ only in the shape of their dots:
`regular`, `square`, `triangle` and `heart`. Pick one with
`\usepackage[variant=heart]{geistserif}`, or switch locally with
`\geistserifvariant{heart}`. Each variant has a single regular weight and no
italic, so `\textbf` and `\textit` fall back to the upright regular face.

## Fonts included

| Family      | Font version | Faces                                  |
| ----------- | ------------ | -------------------------------------- |
| Geist       | 1.900        | 9 weights + italics (18 faces)         |
| Geist Mono  | 1.900        | 9 weights + italics (18 faces)         |
| Geist Serif | 1.003        | 4 variants, regular weight only (4)    |

Taken from the upstream `vercel/geist-font` release **v1.9.2**.

The version of this distribution follows the upstream release it packages. A
change to the LaTeX support alone, on the same fonts, adds a fourth component,
as in 1.9.2.1.

Geist Pixel, a set of five decorative display faces in the same upstream
release, is not packaged. It has no weight or shape axis to map onto NFSS and no
obvious use in a document body. Open an issue if you want it.

## License

- The fonts, and everything derived from them (the Type1 fonts, metrics and
  encodings generated during packaging), are licensed under the
  **SIL Open Font License, Version 1.1** — see `OFL.txt`. Geist declares no
  Reserved Font Name.
- The LaTeX support files (`.sty`, `.fd`) and the documentation are licensed
  under the **LaTeX Project Public License, version 1.3c** or later.

## Building from source

Support files are generated with `autoinst` from the CTAN `fontools` package,
which in turn drives `otftotfm` from the LCDF TypeTools. Neither is needed to
*use* the package, only to rebuild it.

```
./build.sh    # regenerate everything into build/ and dist/
./verify.sh   # install the flat dist/geist-font tree into a throwaway texmf
              # tree and compile with pdflatex, xelatex and lualatex
```

The CTAN upload is `dist/geist-font.zip`. It contains only the flat
`geist-font/` package tree, whose top-level directory matches the CTAN package
ID as required. TeX Live constructs its installation layout from
that tree.

`build.sh` downloads `autoinst` from the CTAN `fontools` package and needs
`otftotfm` (LCDF TypeTools) and either `tectonic` or `xelatex` to build the
documentation. `verify.sh` needs a full TeX Live. The `texlive/texlive`
container has everything both need, so nothing has to be installed locally:

```
docker run --rm -v "$PWD:/pkg" -w /pkg -u "$(id -u):$(id -g)" -e HOME=/tmp \
    texlive/texlive:latest ./build.sh    # likewise for ./verify.sh
```

Running as your own user keeps `build/` and `dist/` owned by you; `HOME=/tmp`
gives `updmap-user` and the TeX caches somewhere writable.

The package is generated in OT1 and T1 only. `autoinst` turns its encoding list
into a `\RequirePackage{fontenc}` call whose last entry becomes the document's
current encoding, and with LY1 in that list every family lacking an LY1 shape —
Computer Modern, so anything still using `\rmfamily` — is silently substituted
with Times. T1 covers the same ground without that side effect.
