Chapter 03
Typography
Five typefaces, and not one of them is decoration. Each has a single job, and the discipline is in never letting one do another's work.
Built with
- next/font
- Fraunces
- Synonym
- JetBrains Mono
The cast
Five voices, each with exactly one job.
The headline
Fraunces
var(--font-display)
Considered work, quietly shipped
Section headings, project and company titles, every display moment.
The voice
Synonym
var(--font-sans)
Body copy sits in Synonym: a quiet humanist sans that stays out of the way of the words.
Body copy, navigation and buttons. The default for everything that is not a heading.
The lead
Amulya
var(--font-lead)
A lead paragraph is a half-step warmer than body, and a little larger.
The paragraph under a heading that says what the section is about.
The stamp
Bespoke Stencil
var(--font-hero)
Sanjeev
The hero name lockup, and nowhere else. Too distinctive for anything longer than a few words.
The label
JetBrains Mono
var(--font-mono)
Software Engineer · 2026
Eyebrows, dates, tech badges and any small piece of interface chrome.
Together
Anatomy of a section heading.
Three of the voices meet in almost every section: a mono eyebrow to name it, a serif heading to state it, and a lead to explain it. This chapter's own opening is built exactly that way.
What I do
Quiet work, done carefully.
A lead paragraph that says what the section is about in a sentence.
- EyebrowJetBrains Mono, uppercase, wide tracking
- HeadingFraunces, tight leading, a hair of negative tracking
- LeadAmulya at the lead size
Sizes
Every size has a name.
Each size is a fluid clamp() kept in one config. If a size does not exist yet, it is added there, not written inline in a component.
heroTitle
clamp(2.75rem, 8.5vw, 6.5rem)
The hero name lockup.
Sanjeev
heroTitleCompact
clamp(2.25rem, 5.4vw, 4.25rem)
The hero name lockup beside the portrait and the at-a-glance strip.
Sanjeev
sectionTitle
clamp(2.75rem, 6.5vw, 4.5rem)
Section headings.
Seven chapters
subTitle
clamp(1.5rem, 3vw, 2.25rem)
Sub-headings inside a section.
A project title
entryTitle
clamp(1.2rem, 2.5vw, 1.5rem)
Small entry headings in lists.
A company name
contactTitle
clamp(2rem, 4vw, 3rem)
The conversational contact headline.
Let us talk about it
lead
clamp(1.125rem, 2.4vw, 1.375rem)
Lead paragraphs.
The line under a heading
heroLead
clamp(1.125rem, 2.4vw, 1.5rem)
The hero lead, one step above a standard lead.
The passion statement
body
1rem
Everything else.
Standard paragraph text
Under the hood
How the fonts load.
Two faces come from Google through next/font; three are self-hosted as woff2. Each exposes a CSS variable, display: swap keeps text visible while they arrive, and the stylesheet maps every variable to a role, with a system fallback behind it.
// src/app/layout.tsx — self-hosted faces use localFont, Google faces use next/fontconst synonym = localFont({ src: [ { path: "../fonts/synonym/Synonym-Regular.woff2", weight: "400", style: "normal" }, { path: "../fonts/synonym/Synonym-Medium.woff2", weight: "500", style: "normal" }, ], variable: "--font-synonym", display: "swap",}); const fraunces = Fraunces({ subsets: ["latin"], variable: "--font-playfair-display", display: "swap",}); // globals.css maps each variable to a role, inside @theme inline--font-sans: var(--font-synonym), ui-sans-serif, system-ui, sans-serif;--font-display: var(--font-playfair-display), ui-serif, Georgia, serif;--font-lead: var(--font-amulya), ui-sans-serif, system-ui, sans-serif;--font-hero: var(--font-bespoke-stencil), ui-sans-serif, system-ui, sans-serif;--font-mono: var(--font-jetbrains-mono), ui-monospace, monospace;