Skip to content

feat(home): redesign homepage as a type specimen#42

Merged
ronaldtse merged 18 commits into
mainfrom
design/type-specimen-homepage
Jun 22, 2026
Merged

feat(home): redesign homepage as a type specimen#42
ronaldtse merged 18 commits into
mainfrom
design/type-specimen-homepage

Conversation

@ronaldtse

Copy link
Copy Markdown
Contributor

Redesigns the fontist.org homepage from a generic VitePress-template landing into a type specimen / editorial treatment — making typography the design engine, which is both the most on-brand direction for a font project and the most differentiated from generic dev-tool sites.

This is the implementation of Direction A from the design analysis. A standalone HTML prototype was reviewed first; this PR ports it into the real VitePress/Vue codebase.

What changed

Replaces the centered hero + 3-equal-card product grid + stat-counter row + feature cards with a specimen-book composition:

  • Masthead — "FONTIST ● A Specimen for Cross-Platform Font Management ● Vol. 01 / MMXXVI", tracked mono, like a publication's running head.
  • HeroFonts for the modern workflow. set huge (up to 196px) in Fraunces (variable opsz 144), with "modern" italic + rose. On load, the words set themselves (staggered rise). A monospace spec line, two CTAs, and the terminal mockup reframed as a "Specimen Plate — Live" with a stacked-paper shadow. A faint italic ghost-numeral bleeds off the edge.
  • The Instrumentarium — three products as asymmetric specimen plates (not equal cards), each with the name set enormous, an italic role tag, mono spec, and a link. Hover shifts the variable-font weight and blooms the name to rose.
  • Colophon stats — the numbers rendered as typographic prose ("Indexed in 2,175 formulae, spanning 14,500 styles, since MMXX") instead of a counter row.
  • Why Fontist — editorial paragraph in Fraunces with a giant rose drop cap.
  • Footer colophon — "Set in Fraunces, IBM Plex & JetBrains Mono."

Design system

Token Light Dark
Paper #f1ece1 warm cream #161513 warm ink
Ink #1c1a18 #ecdfd0
Rose (accent) #b8475f #d4718a
  • Type: Fraunces (variable serif, opsz 9–144) for display, IBM Plex Sans for body, IBM Plex Mono for labels/terminal.
  • Texture: subtle SVG paper grain overlay (multiply blend).
  • Motion: CSS-only — hero headline words rise from below the baseline with staggered delays; product plates shift variable-font weight on hover.
  • Dark mode: full light + dark palette pair, scoped to the homepage via pageClass: specimen-home.

Files

File Change
.vitepress/components/HomePage.vue Full rewrite — specimen template + scoped styles
.vitepress/config.ts Google Fonts (preconnect + Fraunces/IBM Plex/Sans/Mono) in head
.vitepress/theme/style.css specimen-home palette vars (light + dark), scoped to the pageClass
index.md pageClass: specimen-home

Verification

  • npm run build passes (dirify + all post-build steps).
  • check:subsite-links guard passes — all subsite <a> carry target="_self".
  • Playwright on the dev server: all three webfonts load; Fraunces variable opsz 144 applied at 162px; cream/ink palette live in light mode; dark mode swaps correctly (warm dark paper #161513, cream text #ecdfd0, deep-dark terminal #0d0c0c); zero console errors; full page renders.

Notes

  • The VitePress nav/footer chrome is preserved (the specimen lives in the content area).
  • This is a bold visual change to the live homepage — opening as a PR for review, not auto-merging. Request any tweaks (palette intensity, type pairing, layout density, motion speed, copy) and I'll iterate.

ronaldtse added 18 commits June 18, 2026 16:46
Replace the generic VitePress-template landing (centered hero, 3-equal-card product grid, stat-counter row, feature cards) with a type-specimen / editorial treatment that makes typography the design engine — the most on-brand direction for a font project and the most differentiated from generic dev-tool sites.

Design: warm cream paper + ink, rose as a single printer's-ink accent, SVG paper grain overlay, Fraunces (variable opsz) for display, IBM Plex Sans for body, IBM Plex Mono for labels/terminal. The hero reads like a specimen spread (massive headline with the keyword italic+rose, a mono spec line, a terminal 'specimen plate', a faint ghost numeral). Products become asymmetric specimen plates with variable-font hover. Stats render as typographic colophon prose. The 'why' block has a giant rose drop cap.

Engineering: per-page palette via pageClass (specimen-home) in theme/style.css with a full light+dark pair (cream paper / warm ink paper); Google Fonts loaded in config.ts head; all subsite links carry target="_self" (build guard passes); on-load motion is CSS-only (words set themselves with staggered delays).

Verified via Playwright on the dev server: all three webfonts load, variable opsz 144 applied, cream/ink palette live in light mode, dark mode swaps correctly to warm dark paper, zero console errors, full page renders. Build + subsite-link guard pass.
…av leak

Three improvements based on review feedback:

1. Site-wide design system: the specimen palette (cream paper + ink + rose), paper grain, Fraunces/IBM Plex typography, and restyled VPNav/VPFooter/.vp-doc now apply GLOBALLY (theme/style.css) — every page (home, about, blog, docs) shares one design language instead of the homepage being skinned in isolation. The nav is transparent-over-paper with mono labels and a hairline rule.

2. Specimens vs Instruments: the three products (Fontist/Fontisan/Formulas) are tools, not typefaces — so rendering them as 'specimens' was incoherent. Split into two honest sections: 'Specimens' (real typefaces from the registry — Roboto, Fraunces, IBM Plex, Source Serif, JetBrains Mono — shown at display size in their own face, the genuine specimen move) and 'The Instruments' (the tools, presented functionally).

3. Fixes: removed the redundant 'Fontist' word from the homepage masthead (already in the nav logo); removed the not-useful 'Set in Fraunces, variable opsz 9-144' meta-row; made the nav background opaque (paper) so scrolled content no longer leaks through the transparent bar.

Verified via Playwright: nav opaque at scrollY=800 (rgb(241,236,225), no leak); masthead and meta-row fixes confirmed; all fonts load; global typography (Fraunces headings, IBM Plex body) applies on both homepage and /about/.
… 404

Applies the specimen design language to every remaining surface so the whole site is visually consistent:

- BlogIndex.vue: editorial article list (hairline-separated rows, Fraunces titles, mono dates, no rounded cards).

- BlogByline.vue: specimen metadata bar (mono, hairline borders, no icons, no rounded card).

- about.md: bespoke <style> block replaced — removed all border-radius and bg-soft cards; use-cases and get-started links are now hairline grids; tagline/mission in Fraunces italic; all colors use specimen vars.

- style.css: 404 page styled (massive italic Fraunces '404' at 280px, mono labels, rose accent, cream paper).

Verified via Playwright: blog index (8 rows, Fraunces+mono, no rounded cards), blog post byline (mono, hairline, 0px radius), about page (0px radius everywhere, Fraunces italic tagline, no bg-soft), 404 (280px italic Fraunces code, mono labels).
…rk terminal)

Code blocks were using var(--spec-term-bg) (#1c1a18, near-black) in BOTH light and dark mode. In light mode, VitePress's Shiki syntax highlighter uses light-theme token colors (dark text designed for a light background), making them unreadable on the dark panel. Now: light mode uses var(--spec-paper-deep) (#e7e0d1, warm cream); dark mode keeps the terminal ink bg via the html.dark override.

Verified: 11 code blocks on /integrations/github-actions/ all show rgb(231,224,209) bg in light mode (isDark: false).
…, and hero clipping

Four fixes from review feedback:

- Font: replaced Fraunces (user found VERY UGLY) with Newsreader — a clean, refined editorial serif with optical sizing (opsz 6-72). Swapped across config.ts, style.css, HomePage.vue, BlogIndex.vue, and about.md.

- Integrations dropdown: VitePress renders dropdown nav items as .VPNavBarMenuGroup, not .VPNavBarMenuLink. Added .VPNavBarMenuGroup to the mono/uppercase/tracked styling so the Integrations nav item matches the others.

- Hero word spacing: Vue's production template compiler strips whitespace between inline-block spans, causing 'Fontsforthe' (one word). Fixed with margin-right: 0.25em on .word spans. Verified: 40px gaps between words (marginRight: 40.5px, gap01: 40px).

- Hero top clipping: .line's overflow:hidden (for the rise-in animation) + line-height: 0.92 was clipping Newsreader's serif ascenders. Fixed with padding-top: 0.12em on .line. Verified: wordExtendsAboveLine: false, clipGap: -19px.
Reorders the homepage sections per feedback that tools are more important than font samples:

- The Instruments (Fontist / Fontisan / Formulas) is now the FIRST content section after the hero — this is what visitors need: what the tools do and how to get them.

- Specimens (font samples) moved to SECOND position with a divider, heading changed to 'Available type.', lede shortened to one line.

- Specimen sample font-size shrunk from clamp(56px, 11vw, 152px) to clamp(22px, 2.5vw, 34px) — a 4.5x reduction. They're now a compact reference strip, not a spectacle.

- Specimen row padding reduced from clamp(24px, 4vw, 44px) to clamp(12px, 1.5vw, 18px).

Verified: sectionOrder = [hero, instruments, specimens, colophon, story]; instrumentsBeforeSpecimens = true; specSampleSize = 30px (was 152px).
VitePress styles the inner .button element of VPNavBarMenuGroup directly, so font-size and text-transform inherited from the container were overridden (Integrations showed as 13.33px + lowercase instead of 12px + uppercase). Now targeting .VPNavBarMenuGroup .button directly with the specimen mono/12px/uppercase styling.

Verified: buttonText=INTEGRATIONS, buttonSize=12px, buttonTransform=uppercase, matches=true (identical to regular VPNavBarMenuLink items).
…v styling

The Integrations dropdown button had line-height 24px (VitePress default) vs 64px on regular nav links, making it sit at a different vertical position. Now both the dropdown button and the ellipsis (VPNavBarExtra) button have line-height: 64px to match.

Also styled the entire VPMenu flyout panel (shared by both the Integrations dropdown and the ellipsis extra menu): paper background, hairline border, no border-radius, mono/uppercase menu items, rose hover.

Verified: linkLineHeight=64px, buttonLineHeight=64px, buttonMatchesLink=true, extraButton all matching (mono/12px/uppercase/64px).
VitePress renders the visible text of dropdown/flyout buttons in an inner <span class="text"> with its own font-size: 14px and color. My .button-level !important couldn't cascade because direct rules on the child element override inherited values. Now targeting .button .text directly with font-size: 12px and color: ink-soft.

Verified: ALL nav items now identical — fontSize=12px, color=rgb(74,71,68) for every item including INTEGRATIONS (was 14px + rgb(28,26,24)).
The flyout menu items (GitHub Actions link, Appearance label) were still 14px + ink color despite !important — VitePress's .VPLink.link selector (specificity 0-2-0) was beating my .VPMenuLink a (0-1-1). Chaining .VPMenu as parent bumps to 0-2-1, which wins.

Verified: githubActionsSpan fontSize=12px color=rgb(74,71,68); appearanceLabel font=IBM Plex Mono transform=uppercase; both match regular nav links exactly.
Rotating messages of the day in the hero — clever, witty, contradictory, truthful, indicating the fontist/fontisan suite benefits humanity. Types character-by-character with natural jitter, pauses, erases, then types the next. Rose cursor blinks continuously. Click to skip.

Messages: 'Installing fonts so humanity doesn't have to.' / '2,175 openly-licensed typefaces. One command. Zero headaches.' / 'Making type accessible — because everyone deserves good fonts.' / 'Stop worrying about fonts. We already did.' / 'The font pipeline that runs while you sleep.' / 'Automating typography for a more beautiful web.'
…t counts

Two changes per user feedback:

1. The hero IS the MOTD now — the big headline itself rotates through clever messages with a typewriter effect and blinking cursor (was a static 'Fonts for the modern workflow' with a tiny subtitle below). Font size reduced from clamp(56px,13.5vw,196px) to clamp(32px,5.5vw,76px) — was 'too big'.

2. All formula/font counts auto-generated at build time via formula-count.data.ts, which fetches stats.json from the formulas subsite. Returns formulaCount (total: 4,283) and openSourceCount (2,143). Zero hardcoded '2,175' or '14,500' remain anywhere in the page. The colophon, instruments spec, specimens lede, and MOTD messages all use the live numbers.

MOTD messages: 'Installing fonts so humanity doesn't have to.' / '<count> fonts. One command.' / 'Stop worrying about fonts. We already did.' / 'Making type accessible for everyone.' / 'The font pipeline that runs while you sleep.' / 'Automating typography for a better web.'

Verified: heroSize=66px (was ~162px), colophonText='4,283 formulae — 2,143 openly licensed', hasHardcoded2175=false, hasHardcoded14500=false, cursor blinks, typewriter actively types.
…e blockquotes

Three content-page layout improvements:

1. Double-rule fix: <hr> was full-width (competing with .vp-doc h2's full-width border-top), creating adjacent duplicate lines on about/blog pages. Now <hr> is a short 48px centered editorial break — visually distinct from the h2's structural full-width separator.

2. Drop cap: .vp-doc > p:first-of-type::first-letter gets a rose Newsreader italic initial (3.4em, opsz 72, wght 520) — the classic editorial specimen detail on every content page.

3. Blockquotes refined: larger (1.25em from 1.15em), 3px rose left border (was 2px), more generous padding and margins.
…dry promotion

Reworked the suite section per deep review of actual capabilities:

- Heading: 'Engineer. Manage. Discover.' (was 'Three tools. One pipeline.' — wrong: not tools, not a pipeline)

- Reordered: Fontisan FIRST (the powerhouse, not Fontist). Fontisan is the most comprehensive open-source font processor — pure Ruby, every major format from legacy Type 1 to modern WOFF2, from Apple DFONT to web SVG. Full format list: TTF, OTF, WOFF/WOFF2, Type 1, TTC/OTC, DFONT, SVG, variable.

- Fontist positioned as POWERED BY Fontisan: 'Installs and manages fonts from a library of 4,283 openly-licensed typefaces.' Links the two: Fontisan is the engine, Fontist is the distribution layer.

- Formulas promotes foundries: 'featuring type from Google, SIL, IBM, Adobe, and independent foundries.' Shows the breadth of the registry's sources.

- Lede: 'Fontisan processes every font format. Fontist installs them across every platform. Formulas indexes every openly-licensed typeface.'
Reordered instruments: Fontist (01) → Fontisan (02) → Formulas (03). Updated lede to match.
Five architecture improvements from the codebase review:

C1 (HomePage.vue CSS extraction): moved 129 lines of shared layout primitives (.wrap, .section, .divider, .eyebrow, .lede, .head, .btn-ink/ghost, .foot, masthead) from scoped CSS into style.css under .specimen scope. HomePage.vue: 649→520 lines. The section vocabulary is now available to any page that uses the specimen container.

C2 (nav consistency test): added tests/nav-consistency.spec.ts — 6 Playwright tests verifying every VitePress nav element (links, dropdown button, ellipsis button, flyout menu items, Appearance label) matches the specimen styling (12px, mono, uppercase, ink-soft). Also tests nav bar opacity (no scroll leak). Catches regressions on VitePress upgrades.

C4 (about.md inline styles): moved 111 lines of <style> from about.md into style.css. about.md: 345→232 lines. CSS now lives in stylesheets, content in Markdown.

C5 (build script tests): added tests/dirify.test.mjs — 8 unit tests for the dirify logic using Node's built-in test runner. Creates a fake dist structure and verifies file-routes are correctly moved to directory form, root files (index.html, 404.html) are kept, and non-HTML files are untouched.

C3 (cross-repo): deferred — the .specimen-scoped section vocabulary in style.css is the foundation for a future shared design-tokens package, but creating @fontist/site-toolkit requires coordinating 4 repos and is a separate effort.

Verified: build passes, 8/8 unit tests pass, subsite guard passes.
Two fixes:

1. Display font: Newsreader → Spectral (Production Type variable serif, opsz 7-72, wght 200-800). Spectral has more personality at display sizes, better italic forms, and optical sizing that adapts to every size the design system uses (hero 76px, card titles 38px, drop caps 3.4em, section headings 68px).

2. Critical: VitePress bundles Inter and applies it via --vp-font-family-base to every element (nav, sidebar, footer, search, body). Without overriding this variable, any element not explicitly targeted by our CSS falls back to Inter. Now setting --vp-font-family-base and --vp-font-family-mono in :root, which propagates to ALL VitePress elements automatically.
@ronaldtse ronaldtse merged commit eb20f7a into main Jun 22, 2026
5 checks passed
@ronaldtse ronaldtse deleted the design/type-specimen-homepage branch June 22, 2026 06:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant