Skip to content

Foundations

Typography

One typeface, eleven steps. Display and documentation headings use regular weight, creating a calm editorial voice; functional labels add weight only where hierarchy needs it.

The typefacePermalink to this section

Inter, loaded through next/font so it is self-hosted, preloaded and free of layout shift. The stack is a token, so a preset can change the system's voice without any component knowing which face is active.

Aa

Inter · variable · regular headings · latin subset

ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789

src/app/layout.tsx
import { Inter } from "next/font/google";

// Self-hosted, preloaded, no third-party request and no
// layout shift on first paint. Exposed as --font-inter,
// which the font-family-sans design token consumes.
const inter = Inter({
  subsets: ["latin"],
  display: "swap",
  variable: "--font-inter",
});

The scalePermalink to this section

Every step is a utility class. Choosing a visual level is separate from choosing a heading rank, so a page can keep a correct heading order without being forced into a particular size.

.type-display

Build interfaces with one shared language.

.type-h1

Typography

.type-h2

The type scale

.type-h3

Choosing a step

.type-h4

Line length and measure

.type-body-lg

Foundations, components, motion and accessibility guidelines for building consistent product experiences.

.type-body

The default step for running text. Fifteen pixels on a twenty-four pixel line box, which keeps documentation dense without becoming tiring.

.type-body-sm

Supporting copy, table cells and anywhere density matters more than comfort.

.type-label

Deployment region

.type-caption

Last updated 2 hours ago

.type-code

--brand-primary: var(--brand-600);

SpecificationPermalink to this section

Values are given as desktop / mobile where the step is responsive. Sizes are in pixels.

TokenSizeLine heightWeightTrackingUse for
.type-display64 / 4464 / 48font-weight-regulartracking-tightestMarketing hero only.
.type-h148 / 3650 / 40font-weight-regulartracking-tighterPage title, one per page.
.type-h240 / 3044 / 34font-weight-regulartracking-tightMajor section.
.type-h328 / 2432 / 30font-weight-regulartracking-snugDocumentation section.
.type-h42026font-weight-mediumtracking-normalSubsection and card title.
.type-body-lg1828font-weight-regularnormalPage introductions.
.type-body1524font-weight-regularnormalDefault running text.
.type-body-sm1320font-weight-regularnormalSupporting copy and dense UI.
.type-label1318font-weight-strongnormalForm labels and table headers.
.type-caption1218font-weight-regularnormalMetadata and help text.
.type-code12.521font-weight-regularnormalCode and token names.

WeightsPermalink to this section

Regular weight carries headings and prose. In-between weights are reserved for compact functional UI where size alone cannot carry hierarchy.

Regular400Display, headings and running text
Book450Small headings and restrained emphasis
Medium550Labels, buttons and active navigation
Semi560Compact component titles
Strong590Wordmark and rare brand emphasis
Bold700Not used — regular headings are the voice

TrackingPermalink to this section

Negative letter spacing tightens large text that would otherwise look loose. Applied to small text it destroys legibility, so the scale removes it as sizes drop.

Build with one shared language

Dotighten large text

At 30px and above, −0.018em to −0.028em closes gaps that only become visible at display sizes.

Tokens are documented in three layers, starting with the primitive scale.

Don'ttighten body text

Below 17px, negative tracking collides letterforms and slows reading — most noticeably for dyslexic readers.

MeasurePermalink to this section

Line length matters more than font size for reading comfort. Documentation body text is capped at 68 characters.

Comfortable — max-w-[68ch]

Tokens are documented in three layers. Start with the primitive scale, then see how semantic tokens give those values meaning, and finally how component tokens let a single component be re-themed without touching the brand.

Too wide — no measure limit

Tokens are documented in three layers. Start with the primitive scale, then see how semantic tokens give those values meaning, and finally how component tokens let a single component be re-themed without touching the brand. Past about 75 characters the eye struggles to find the start of the next line.

Rules of thumb

Body text: 60–70 characters. Captions and supporting copy: up to 80, since they are read in short bursts. Headings: no limit, but break them by meaning rather than letting them wrap arbitrarily.

Using the scalePermalink to this section

Heading rank and visual size are chosen separately, which is the whole reason the scale is expressed as classes.

app/projects/page.tsx
// The h2 is correct for the document outline.
// type-h3 is correct for how it should look.
// Keeping these independent is what lets a page stay
// accessible without being visually rigid.
<section>
  <h2 className="type-h3 text-ink">Recent deployments</h2>
  <p className="type-body-sm text-ink-muted">
    The last 30 days across every region.
  </p>
</section>