Docs
Next

Fonts

Font family tokens, the fallback stack every family carries, and weight names.

On this page

Font tokens in the font collection set each text style's family and weight. Two root families, the default body and heading families, are referenced by every other font token. This page covers the value format both need.

Fallback stacksLink to this section

A fontFamily token is emitted into CSS verbatim — font.default.body.fontFamily becomes --font-default-body-font-family, and every other font token in the system (font.h1, font.button.primary, font.chip, …) references one of the two roots:

font.default.body.fontFamily     →  --font-default-body-font-family
font.default.heading.fontFamily  →  --font-default-heading-font-family

So the value must be a complete CSS font-family list, not a bare family name. Webfonts load with font-display: swap (what next/font uses by default), which means the browser paints once before the face arrives. With a bare "Geist" there is nothing to paint with, so it falls back to its built-in serif — a visible Times New Roman flash on every cold load, worst on headings. Systhema's own defaults therefore ship a stack:

{
  "font": {
    "default": {
      "body": {
        "fontFamily": {
          "$type": "string",
          "$value": "Geist, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
        }
      }
    }
  }
}

When you swap in your own family, keep the tail and match the category of the face you picked — a serif brand font needs a serif tail, a mono needs a mono tail:

Brand font is…Tail to append
sanssystem-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif
serifGeorgia, 'Times New Roman', Times, serif
monoui-monospace, SFMono-Regular, Menlo, Consolas, monospace

Multi-word names go in quotes ('Segoe UI'); the Tailwind bridge reads the first entry as the family key, so font-geist still resolves the whole stack.

systhema upgrade back-propagates the stack onto projects still running the stock Geist default. A project that already customised the family is never rewritten — you own the tail from then on.

The Figma plugin appends the same stack on export.

Weight namesLink to this section

A fontWeight token may be a number (700) or the style name the family itself uses (Bold, SemiBold, Extra Bold). Names are resolved to the numeric CSS weight, and the separator is irrelevant — closed-up, spaced, hyphenated and underscored spellings of the same name all resolve identically, and an appended Italic sets font-style without changing the weight:

Token valuefont-weight
Thin / Hairline100
ExtraLight / Extra Light / UltraLight200
Light300
Regular / Normal / Book400
Medium500
SemiBold / Semi Bold / DemiBold600
Bold700
ExtraBold / Extra-Bold / UltraBold800
Black / Heavy900
ExtraBlack / Ultra Black950
750 (any bare number)750

A token reference ({font.h1.fontWeight}) is passed through untouched, and anything unrecognised falls back to 400.