Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .agents/skills/fonts/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ Every font is self-hosted through `next/font/local`. That loader is what generat
- The data table measures header labels from bundled metrics of the sans woff2, generated by `packages/scripts/src/data-table-metrics.ts` into `.generated/data-table-metrics.json` (in the web build, dev, and check-types chains). Swapping the sans re-measures automatically on the next run, but the script's `FONT` path must point at the new file: update it when the filename changes.
- Preload is scoped by import. Any font in `web/next/src/lib/fonts.ts` preloads on every page, because the root layout imports it. To scope a font to specific routes, declare it in a module only those routes import: author-only fonts live in `web/next/src/lib/marketing/fonts.ts`, with woff2 under `web/next/src/fonts/marketing/`.
- DM Sans vendors its italics: `src` is an array of `{ path, style }` entries under one top-level `weight`. Mono renders synthetic oblique for italics, by choice.
- A face used only in italic vendors just the italic file and sets `style: "italic"` beside `src`. Without it the face registers as upright, so an `italic` class slants the already-italic glyphs again.
- A non-variable font takes the per-weight files, with `src` as an array carrying a `weight` per entry.
- To remove a font, delete the woff2, its `localFont` definition, the `<html>` variable, and the `globals.css` role, then grep the variable name to catch stragglers.
2 changes: 1 addition & 1 deletion web/next/content/docs/manage/theming.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Fonts are self-hosted, not fetched at runtime, localized through `next/font/loca
- **DM Sans** → `--font-sans`: body and headings.
- **JetBrains Mono** → `--font-mono`: code.

**Caveat** and **Newsreader** (`--font-caveat`, `--font-newsreader`) are author-only accents for `/hire` and `/resume`, applied via their `.className`. They live in the fork-excluded `web/next/src/lib/marketing/fonts.ts` (`.woff2` in `web/next/src/fonts/marketing/`), kept out of `lib/fonts.ts` so their preload stays scoped to those two pages.
**Caveat** and **Lora** (`--font-caveat`, `--font-lora`) are author-only accents for `/hire` and `/resume`, applied via their `.className`. They live in the fork-excluded `web/next/src/lib/marketing/fonts.ts` (`.woff2` in `web/next/src/fonts/marketing/`), kept out of `lib/fonts.ts` so their preload stays scoped to those two pages.

Headings track `--font-sans` unless you repoint `--font-heading`. To add or swap a font, follow the [`fonts` skill](/docs/resources/ai-skills): it fetches the variable woff2 and wires the preload so you don't ship layout shift.

Expand Down
10 changes: 5 additions & 5 deletions web/next/src/app/(marketing)/hire/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type { Metadata } from "next"
import Link from "next/link"

import { config } from "@/lib/config"
import { caveat, newsreader } from "@/lib/marketing/fonts"
import { caveat, lora } from "@/lib/marketing/fonts"

const ogImageUrl = `${config.app.url}/og?${new URLSearchParams({
section: "Hire",
Expand Down Expand Up @@ -163,7 +163,7 @@ export default function Page() {
<p>
AI-native product engineer building SaaS products, developer tools, and agent
infrastructure.{" "}
<span className={cn(newsreader.className, "font-medium tracking-wide italic")}>
<span className={cn(lora.className, "font-medium tracking-wide italic")}>
I learn by shipping.
</span>
</p>
Expand All @@ -184,7 +184,7 @@ export default function Page() {
<p>
Before that I helped take SaaS and AI products from 0 to 1, shipped scraping- and
automation-heavy SaaS, and built open-source tools now used by projects including{" "}
<span className={cn(newsreader.className, "font-medium tracking-wide italic")}>
<span className={cn(lora.className, "font-medium tracking-wide italic")}>
TanStack, SST, Electric SQL, and Storybook
</span>
. I care about clean systems, fast builds, strong types, useful docs, and software that
Expand Down Expand Up @@ -307,7 +307,7 @@ export default function Page() {
</p>
<p className="text-muted-foreground">{roles.join(" · ")}</p>
<p>
<span className={cn(newsreader.className, "font-medium tracking-wide italic")}>
<span className={cn(lora.className, "font-medium tracking-wide italic")}>
The speed of a builder, the taste of someone who maintains tools for other developers,
and the judgment that comes from shipping enough software to know where the sharp
edges are.
Expand All @@ -322,7 +322,7 @@ export default function Page() {
<div className="space-y-4">
<p>
When I'm not coding, you'll find me consuming content and playing games.{" "}
<span className={cn(newsreader.className, "font-medium tracking-wide italic")}>
<span className={cn(lora.className, "font-medium tracking-wide italic")}>
This year, I want to travel more and explore new places
</span>
.
Expand Down
4 changes: 2 additions & 2 deletions web/next/src/app/(marketing)/resume/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { Metadata } from "next"
import Link from "next/link"

import { config } from "@/lib/config"
import { caveat, newsreader } from "@/lib/marketing/fonts"
import { caveat, lora } from "@/lib/marketing/fonts"

const ogImageUrl = `${config.app.url}/og?${new URLSearchParams({
section: "Résumé",
Expand Down Expand Up @@ -178,7 +178,7 @@ export default function Page() {
product surfaces and agent tooling at LightWork AI. Author of 250+ public repositories and
open-source tools with 1,045+ GitHub stars, used by projects including TanStack, SST,
Electric SQL, and Storybook.{" "}
<span className={cn(newsreader.className, "font-medium tracking-wide italic")}>
<span className={cn(lora.className, "font-medium tracking-wide italic")}>
I learn by shipping, and I sweat build performance, type safety, and release automation.
</span>
</p>
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
15 changes: 7 additions & 8 deletions web/next/src/lib/marketing/fonts.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import localFont from "next/font/local"

// Author-only fonts for /hire and /resume, kept out of lib/fonts.ts on purpose: next/font scopes a font's preload to the routes whose module graph instantiates it, and the root layout imports lib/fonts.ts, so any font declared there preloads on every page (the landing) and wastes ~193KB. Only these two pages import this module, so their preload stays scoped to /hire and /resume. Wholesale fork-excluded via .gitpickignore.
// Author-only fonts for /hire and /resume, kept out of lib/fonts.ts on purpose: next/font scopes a font's preload to the routes whose module graph instantiates it, and the root layout imports lib/fonts.ts, so any font declared there preloads on every page (the landing) and wastes ~116KB. Only these two pages import this module, so their preload stays scoped to /hire and /resume. Wholesale fork-excluded via .gitpickignore.
export const caveat = localFont({
src: "../../fonts/marketing/caveat-latin-wght-normal.woff2",
variable: "--font-caveat",
weight: "400 700",
})

export const newsreader = localFont({
src: [
{ path: "../../fonts/marketing/newsreader-latin-wght-normal.woff2", style: "normal" },
{ path: "../../fonts/marketing/newsreader-latin-wght-italic.woff2", style: "italic" },
],
variable: "--font-newsreader",
weight: "200 800",
export const lora = localFont({
src: "../../fonts/marketing/lora-latin-wght-italic.woff2",
adjustFontFallback: "Times New Roman",
style: "italic",
variable: "--font-lora",
weight: "400 700",
})
Loading