Skip to main content
Forme includes three standard PDF font families by default: Helvetica, Times, and Courier (each with regular, bold, italic, and bold italic variants), plus Noto Sans (regular and bold) as a builtin Unicode fallback for non-Latin scripts. For any other typeface, register a TrueType (.ttf) font file. Registered fonts are automatically subsetted — only glyphs used in the document are embedded, keeping file sizes small.

Font.register()

Register fonts globally. Works like react-pdf’s Font.register().
Then use the font by name in any style:

Options

Font.clear()

Remove all globally registered fonts. Useful in tests.

Multiple weights in one call

You can register multiple weights for the same family using the fonts array syntax:

Google Fonts

You can register fonts directly from a URL. Google Fonts .woff2 URLs work:
To find the direct .woff2 URL for a Google Font, open https://fonts.googleapis.com/css2?family=Inter:wght@400;700 in your browser and copy the url() value from the CSS.

Font fallback chains

Specify multiple font families separated by commas. Forme tries each family in order per character, so mixed-script text (e.g., English + Arabic) works automatically:
If a character isn’t covered by Inter, Forme tries Noto Sans. If no font in the chain covers the character, the builtin Noto Sans is used as a final fallback.

Document fonts prop

Register fonts per-document instead of globally:
Document fonts and global fonts are merged. If both register the same family + weight + style combination, the document font wins.

Font sources

The src option accepts three formats: File paths are resolved relative to the template file in the CLI dev server (forme dev), or relative to the working directory in renderDocument().

Standard fonts

These fonts are always available without registration: Automatic fallback: When a character is not covered by your chosen font (e.g., Cyrillic or Greek text with Helvetica), Forme automatically falls back to Noto Sans. This means non-Latin text works out of the box without registering any fonts. If a fontFamily is not found, Forme falls back to Helvetica.

Example: Multiple weights

Troubleshooting

Text renders in Helvetica instead of my custom font

The fontFamily in your style must exactly match the family you passed to Font.register(). Font names are case-sensitive.

Bold or italic text falls back to Helvetica

You need to register each weight and style variant separately. If you register only the regular weight and use fontWeight: 700, Forme will look for a bold variant, not find one, and fall back.

Non-Latin characters show as boxes or question marks

The font you’re using doesn’t cover those characters. Either:
  1. Register a font that covers them (e.g., Noto Sans for broad Unicode support)
  2. Use a font fallback chain: fontFamily: 'Inter, Noto Sans'
  3. Do nothing — Forme’s builtin Noto Sans provides automatic fallback for most scripts