Literal font family names
In @theme inline, name fonts literally, not by runtime variable.
From shadcn (Vercel plugin): Component Gotchas, Geist font in Next.js.
Three font declarations
Switch the --font-sans line; two of three fall back.
globals.cssSource
RenderedBad
<html>
<body class="geist.variable antialiased">
Revenue up 18% this quarter
Net margin held at 22% on flat headcount.
Where the variable class lives
Move the class chip between <html> and <body>.
Bad
<html class="">
<body class=" antialiased">
- <h1>Revenue up 18%
- <p>Plain paragraph text
- .font-sansApprove bill
- .font-monoINV-2041
/* globals.css */
@theme inline {
--font-sans: "Geist", "Geist Fallback", ui-sans-serif, system-ui, sans-serif;
--font-mono: "Geist Mono", "Geist Mono Fallback", ui-monospace, monospace;
}
// app/layout.tsx
<html lang="en" className={`${geistSans.variable} ${geistMono.variable}`}>
<body className="antialiased">{children}</body>
</html>
Why it matters, pros and cons
Why it matters
@theme inline bakes values in at build; runtime variables resolve to nothing.
Pros
- Resolves wherever the classes land.
- Devtools shows the real font stack.
- Survives
shadcn initrewrites.
Cons
- The family name now lives in two places.
- A custom
localFontfallback name may differ. - Plain
@themewith classes on<html>also works.