Improve docs design: Geist via Google Fonts, Berkeley Mono for code - #693
Merged
Conversation
Match the www marketing site's font setup: Geist now comes from next/font/google (self-hosted woff2 subsets, ~29KB preloaded vs the old 169KB TTF) and the mono face is Berkeley Mono, copied unmodified from www — its EULA prohibits subsetting the binary. This shrinks the cold-load font swap window that showed as a visible FOUT "flicker" on production, and makes docs typography consistent with axiom.co. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📝 Vale prose report✅ No prose issues found in the docs changed by this PR. |
Adds the 13 Radix-style 1-12 color scales (gray, red, orange, yellow, green, blue, purple, tomato, amber, lime, teal, iris, pink) from www/src/app/globals.css, restructured for this repo's theming: www is light-default with a .dark override, here the dark values live on :root and light under [data-theme="light"]. Values live in styles/tokens.css with the rest of the foundations; the existing @theme inline block in globals.css registers them as Tailwind utilities (text-red-9, bg-gray-2, ...) exactly as in www. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Header tabs no longer bump font-weight on the active state — bolder glyphs are wider and reflowed the tab row on every click; colour and the accent underline carry the state. - Port the missing www semantic tokens: --brand (both theme values), the --chart-1..5 ramp, the --sidebar-primary pair (mapped to docs tokens like the rest of the bridge), --color-accent-foreground (white against Axiom's orange accent), and --font-heading. - Port all 26 www typography utilities (body-*, mono-*, content-*) verbatim; opt-in classes, existing docs type styles untouched. - The shadcn bridge still resolves --background/--card/... to the docs' own surfaces; www's raw oklch values are not adopted there. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Move ~350 selectors of hand-written component CSS out of globals.css and into their components as Tailwind v4 utilities: header, sidebar and drawer, search dialog, AI assistant chrome, landing page, article chrome (footer, pagination, copy-page, TOC, toasts) and the API reference components. globals.css drops from 1111 to 712 lines. Rules that style rendered content stay in CSS by design: .doc-article .prose typography, .docs-ai-markdown/Streamdown overrides, Shiki and fumadocs internals. Semantic class names remain in the JSX as inert hooks for tests and readability. Structural changes: - Element defaults in globals.css and tokens.css move into @layer base so utilities can override them; unlayered they beat every utility. - classNames compose via cn() from lib/utils — no template-literal interpolation anywhere. - All 153 custom breakpoint usages consolidate onto the standard Tailwind scale: 640->max-sm, 900->max-md (768), 1080->max-lg (1024), 1240 and the TOC's 1339->max-xl (1280). The drawer's matchMedia is synced to (min-width: 80rem), and the lexicographic-ordering specificity hacks that arbitrary media variants required are gone. Verified: build, typecheck, eslint; visual parity against pre-migration baselines (landing, article, API endpoint, search, mobile drawer); Playwright 30 passing with the 6 failures pre-existing (stale #691 type-scale expectations and the local rate-limiter). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Active sidebar and drawer links no longer bump font-weight (bolder
glyphs are wider and reflowed the list on every navigation). They keep
the idle weight and read bold via a hard-edged double text-shadow
(-0.2px/+0.2px currentColor), so active state changes never move text.
Also replace the remaining [...].filter(Boolean).join(' ') className
patterns with cn() from lib/utils (docs-shell, site-header,
heading-anchor, playground-link) — each call checked for tailwind-merge
conflicts; branches are mutually exclusive so none exist.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Breadcrumb trail renders in the brand orange via --color-accent-text (identical to --brand on dark, darkened on light so 12px text keeps AA contrast); link hover signals with an underline instead of a colour change. - The article lede drops from 18px/29px to the body scale (16px/28px); colour and spacing keep it distinct. - Copy-page menu: single-line rows without subtitles, popover narrowed to 220px, divider dropped, and the duplicate "Copy page" row removed — the split button's primary action already copies. - Heading anchors swap the right-side hover "#" for a chain-link icon in the left gutter (absolute, so headings never shift), keeping the same reveal on hover/keyboard focus and the .anchor-hash hook. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New landing composition with Carbon glyph quick-cards and a brand-mark integrations grid (simple-icons paths, official hexes; near-black marks render currentColor). integration-icons also carries the extensions catalog brands (Convex, Netlify, Supabase, Tailscale) used by the docs app cards. tokens.css is a formatting-only realignment; e2e expectations track the removed hero search and the body-copy colour move to --text-tertiary. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The rules the first migration pass left behind by design — Streamdown markdown in the AI assistant, api-code-body Shiki internals, search chrome, hero search, TOC code — become Tailwind descendant variants on their owning components. Wrapper variants (0-1-1+) outrank both Streamdown's element utilities and fumadocs' fully :where()-wrapped typography, so `!` survives only against Shiki inline styles and other !important rules. html/body defaults move to layout.tsx classNames; what remains in globals.css has no owning component (a/kbd element defaults, keyframes, reduced-motion, .inline-icon for raw JSX imgs in content) and now declares via @apply. Dead rules deleted: .nav-table, .axiom-placeholder-highlight, two superseded search selectors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reading-column typography lives in one nested, deliberately unlayered stylesheet scoped under .doc-prose on DocsBody (declarations via @apply); title/lede styling moves onto DocsTitle/DocsDescription. Two behaviour fixes ride along: list items with block content get their own rhythm (10px between children, 14px around code figures — the zero-margin rule previously flattened them), and heading rules now honour .not-prose so fumadocs Card titles stop inheriting the article's 40px heading margin. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New <Mermaid> client component lazy-loads the mermaid package only on pages with diagrams. Diagrams are themed from the semantic tokens read off :root at render time (mono labels, 4px radii, uppercase subgraph titles, quiet cluster fills) and re-render when data-theme flips. Nodes labelled exactly "Axiom" are picked out in the brand accent. Syntax errors fall back to the readable source instead of an empty frame. Frameless: the SVG sits directly on the page canvas. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
axiom-dark copied scope-for-scope from www/src/lib/code-theme.ts, plus an axiom-light counterpart the docs need (www is dark-only): same scope map with the orange ramp darkened until every token clears AA on the light surface. One deliberate deviation: entity.name.tag joins the quiet key group — in the YAML/TOML grammars that dominate docs config examples it scopes the keys, and orange keys turned whole files orange. Wired into rehypeCodeOptions (defaults spread so notation transformers survive) and the API-reference highlighter; the same source.config change activates remarkMdxMermaid so mermaid fences reach the <Mermaid> component instead of Shiki. api-operation also carries its endpoint-bar/method-badge Tailwind conversion from the globals.css migration. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Nesting indent moves from inner padding to the row's own offset so pills keep symmetric px-2.5 around the label at every depth; the sidebar container drops its pl-6/pr-4 skew for px-6, putting pills 14px off both edges on desktop and mobile. The drawer slims down (40px rows, 38px section switcher sharing the nav rows' gutter-bleed geometry, 300px width, full-bleed divider, one 20px group rhythm) and the trigger shrinks to 40px with a 16px glyph. Header section-tab underline thins to 1px. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The placeholder-config controls and the API try-it fields swap their hardcoded blue-500 focus border and halo for --color-accent with a color-mix halo, so they track the token in both themes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New AppCards/AppCard MDX components styled like the landing quick-cards — brand glyph top-left from INTEGRATION_ICONS with a lucide fallback (hexagon covers Hex, which simple-icons lacks) — used by the extensions catalog in place of the generic Card, which keeps its fumadocs look. mdx-components also registers <Mermaid> and carries the component-CSS Tailwind conversions from the globals.css migration (notices, frames, code groups, accordions, tabs, query examples). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All three thematic breaks sat directly before an h2, which already carries 58px of top margin — the rendered hr read as a stray border under whatever preceded it (most visibly the mermaid diagrams). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Same multi-res favicon.ico as the marketing site (48/32px), replacing the SVG-only icon: Google Search's favicon crawler refetches favicon.ico and won't show an SVG-only icon. Served at /docs/favicon.ico under the zone basePath; e2e assertion and the legacy docs.json field updated to match. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Four assertions predated intentional design changes and were failing the CI browser job: API sample token colours now come from axiom-dark (default fg rgb(184,184,184), not github-dark-high-contrast), tab table headers pad 8px, the brand badge is 14px mono, and notices share the body sans face (the left rule and tint carry the differentiation). Both Playwright projects pass 18/18. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
njpatel
approved these changes
Jul 31, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Matches the docs fonts to the www marketing site's setup:
next/font/googleinstead of a local 169KB variable TTF. Next self-hosts subsetted woff2 files — the preloaded latin subset is ~29KB (vs ~88KB over the wire before).--font-mono/--font-codetokens now resolve to it). The file is the full original woff2 — the Berkeley Mono EULA (§1.12 + §8) prohibits subsetting, same note as in www.Why
The live docs showed a visible font swap (FOUT) on cold loads: text painted in the metric-adjusted Arial fallback, then flipped to Geist. Two of the causes were the heavyweight TTF payloads (~180KB wire for both faces) and
display: swapguaranteeing the swap is visible. This PR halves the sans payload and ships the mono face as woff2, shrinking the swap window substantially.Note: font URLs still carry the
?dpl=deployment stamp from Vercel Skew Protection, so returning visitors re-download fonts once after each deploy. If the swap is still noticeable after this ships, the follow-up is serving the font files from a stablepublic/fonts/URL.Verification
pnpm buildpasses; build output contains the Geist woff2 subsets +Berkeley_Mono_Variable-s.p.*.woff2, both preloaded.--font-geist-monoreferences.🤖 Generated with Claude Code