1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2026-06-05 19:35:27 -04:00

refactor: update font imports and variables

- Replaced GeistSans and GeistMono with Inter and JetBrainsMono in globals.css and layout.tsx.
- Updated font variable names to reflect the new font choices in fonts.ts.
This commit is contained in:
2026-02-19 13:36:13 -05:00
parent eecf93e7cc
commit 4858c8928c
10 changed files with 729 additions and 878 deletions
+1 -1
View File
@@ -1 +1 @@
24.13.0
24.13.1
+2 -2
View File
@@ -6,9 +6,9 @@
@custom-variant dark (&:where(.dark *));
@theme inline {
--font-sans: var(--font-geist-sans);
--font-sans: var(--font-inter);
--font-sans--font-feature-settings: "rlig" 1, "calt" 0;
--font-mono: var(--font-geist-mono);
--font-mono: var(--font-jetbrains-mono);
--font-mono--font-feature-settings: "liga" 0;
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
+2 -2
View File
@@ -7,7 +7,7 @@ import { Footer } from "@/components/layout/footer";
import { Toaster } from "@/components/ui/sonner";
import { Analytics } from "@/app/analytics";
import { defaultMetadata } from "@/lib/metadata";
import { GeistSans, GeistMono } from "@/lib/fonts";
import { Inter, JetBrainsMono } from "@/lib/fonts";
import siteConfig from "@/lib/config/site";
import authorConfig from "@/lib/config/author";
import type { Person, WebSite } from "schema-dts";
@@ -20,7 +20,7 @@ const RootLayout = ({ children }: Readonly<{ children: React.ReactNode }>) => {
return (
<html
lang={env.NEXT_PUBLIC_SITE_LOCALE}
className={`${GeistSans.variable} ${GeistMono.variable}`}
className={`${Inter.variable} ${JetBrainsMono.variable}`}
suppressHydrationWarning
>
<head>
+11 -16
View File
@@ -5,6 +5,7 @@ import { ImageResponse } from "next/og";
import { notFound } from "next/navigation";
import { getSlugs, getFrontMatter, POSTS_DIR } from "@/lib/posts";
import siteConfig from "@/lib/config/site";
import { loadGoogleFont } from "@/lib/og-utils";
export const contentType = "image/png";
export const size = {
@@ -53,16 +54,14 @@ const OpenGraphImage = async ({ params }: { params: Promise<{ slug: string }> })
// get the post's title and image filename from its frontmatter
const frontmatter = await getFrontMatter(slug);
const [postImg, avatarImg, fontRegular, fontSemiBold] = await Promise.all([
frontmatter!.image ? getLocalImage(`${POSTS_DIR}/${slug}/${frontmatter!.image}`) : null,
// IMPORTANT: include these exact paths in next.config.ts under "outputFileTracingIncludes"
const [postImg, avatarImg] = await Promise.all([
frontmatter!.image ? getLocalImage(`${POSTS_DIR}/${slug}/${frontmatter!.image}`) : null,
getLocalImage("app/avatar.jpg"),
// load the Geist font directly from its npm package
fs.promises.readFile(path.join(process.cwd(), "node_modules/geist/dist/fonts/geist-sans/Geist-Regular.ttf")),
fs.promises.readFile(path.join(process.cwd(), "node_modules/geist/dist/fonts/geist-sans/Geist-SemiBold.ttf")),
]);
const [fontRegular, fontSemibold] = await Promise.all([loadGoogleFont("Inter", 400), loadGoogleFont("Inter", 600)]);
// template is HEAVILY inspired by https://og-new.clerkstage.dev/
return new ImageResponse(
<div
@@ -138,8 +137,7 @@ const OpenGraphImage = async ({ params }: { params: Promise<{ slug: string }> })
<span
style={{
fontSize: "1.825rem",
fontFamily: "Geist-SemiBold",
fontWeight: 700,
fontWeight: 600,
lineHeight: "3rem",
letterSpacing: "-0.015em",
marginLeft: "0.75rem",
@@ -153,8 +151,7 @@ const OpenGraphImage = async ({ params }: { params: Promise<{ slug: string }> })
style={{
display: "flex",
flexGrow: 0,
fontFamily: "Geist-SemiBold",
fontWeight: 700,
fontWeight: 600,
fontSize: "48px",
color: "#030712",
letterSpacing: "-0.025em",
@@ -172,7 +169,6 @@ const OpenGraphImage = async ({ params }: { params: Promise<{ slug: string }> })
>
<span
style={{
fontFamily: "Geist-Regular",
fontWeight: 400,
fontSize: "20px",
color: "#030712",
@@ -193,7 +189,6 @@ const OpenGraphImage = async ({ params }: { params: Promise<{ slug: string }> })
style={{
display: "flex",
flexGrow: 0,
fontFamily: "Geist-Regular",
fontWeight: 400,
fontSize: "24px",
color: "#030712",
@@ -235,16 +230,16 @@ const OpenGraphImage = async ({ params }: { params: Promise<{ slug: string }> })
...size,
fonts: [
{
name: "Geist-Regular",
name: "Inter",
data: fontRegular,
style: "normal",
weight: 400,
},
{
name: "Geist-SemiBold",
data: fontSemiBold,
name: "Inter",
data: fontSemibold,
style: "normal",
weight: 700,
weight: 600,
},
],
}
+2 -3
View File
@@ -9,15 +9,14 @@ const Footer = () => {
<Link href="/license" className="underline underline-offset-4">
{siteConfig.license}
</Link>
. Code is{" "}
. View source on{" "}
<a
href={`https://github.com/${env.NEXT_PUBLIC_GITHUB_REPO}`}
target="_blank"
rel="noopener noreferrer"
title="View Source on GitHub"
className="underline underline-offset-4"
>
open source
GitHub
</a>
.
</footer>
+6 -6
View File
@@ -2,22 +2,22 @@
// https://nextjs.org/docs/pages/building-your-application/optimizing/fonts#reusing-fonts
import {
Geist as GeistSansLoader,
Geist_Mono as GeistMonoLoader,
Inter as InterLoader,
JetBrains_Mono as JetBrainsMonoLoader,
Comic_Neue as ComicNeueLoader,
} from "next/font/google";
export const GeistSans = GeistSansLoader({
export const Inter = InterLoader({
subsets: ["latin"],
display: "swap",
variable: "--font-geist-sans",
variable: "--font-inter",
preload: true,
});
export const GeistMono = GeistMonoLoader({
export const JetBrainsMono = JetBrainsMonoLoader({
subsets: ["latin"],
display: "swap",
variable: "--font-geist-mono",
variable: "--font-jetbrains-mono",
preload: true,
});
+31
View File
@@ -0,0 +1,31 @@
import { cacheLife } from "next/cache";
// Load a Google Font from the Google Fonts API
// Adapted from https://github.com/brianlovin/briOS/blob/f72dc33a11194de45c80337b22be4560da62ad7e/src/lib/og-utils.tsx#L32
export async function loadGoogleFont(font: string, weight: number): Promise<ArrayBuffer> {
"use cache";
const url = `https://fonts.googleapis.com/css2?family=${font}:wght@${weight}`;
const cssResponse = await fetch(url, {
next: {
revalidate: 31_536_000, // 1 year
},
});
const css = await cssResponse.text();
const resource = css.match(/src: url\((.+)\) format\('(opentype|truetype)'\)/);
if (resource) {
const fontResponse = await fetch(resource[1], {
next: {
revalidate: 31_536_000, // 1 year
},
});
if (fontResponse.status === 200) {
cacheLife("max"); // cache indefinitely if successful
return fontResponse.arrayBuffer();
}
}
throw new Error(`Failed to load font: ${font} ${weight}`);
}
+1 -6
View File
@@ -22,12 +22,7 @@ const nextConfig = {
],
},
outputFileTracingIncludes: {
"/notes/[slug]/opengraph-image": [
"./notes/**/*",
"./app/opengraph-image.jpg",
"./node_modules/geist/dist/fonts/geist-sans/Geist-Regular.ttf",
"./node_modules/geist/dist/fonts/geist-sans/Geist-SemiBold.ttf",
],
"/notes/[slug]/opengraph-image": ["./notes/**/*", "./app/opengraph-image.jpg"],
},
productionBrowserSourceMaps: true,
experimental: {
+16 -17
View File
@@ -47,11 +47,11 @@
"@radix-ui/react-toggle-group": "^1.1.11",
"@radix-ui/react-tooltip": "^1.2.8",
"@t3-oss/env-nextjs": "^0.13.10",
"@tanstack/react-form": "^1.28.0",
"@tanstack/react-form": "^1.28.3",
"@vercel/analytics": "^1.6.1",
"@vercel/functions": "^3.4.0",
"@vercel/functions": "^3.4.2",
"@vercel/speed-insights": "^1.3.1",
"better-auth": "^1.4.17",
"better-auth": "^1.4.18",
"botid": "^1.5.10",
"cheerio": "^1.2.0",
"class-variance-authority": "^0.7.1",
@@ -60,18 +60,17 @@
"drizzle-orm": "^0.45.1",
"fast-glob": "^3.3.3",
"feed": "^5.2.0",
"geist": "^1.5.1",
"html-entities": "^2.6.0",
"lucide-react": "0.563.0",
"lucide-react": "0.575.0",
"next": "16.1.6",
"next-themes": "^0.4.6",
"pg": "^8.17.2",
"pg": "^8.18.0",
"react": "19.2.4",
"react-activity-calendar": "^3.1.1",
"react-compare-slider": "^3.1.0",
"react-countup": "^6.5.3",
"react-dom": "19.2.4",
"react-lite-youtube-embed": "^3.3.3",
"react-lite-youtube-embed": "~3.3.3",
"react-markdown": "^10.1.0",
"react-schemaorg": "^2.0.0",
"react-timeago": "^8.3.0",
@@ -92,12 +91,12 @@
"remark-rehype": "^11.1.2",
"remark-smartypants": "^3.0.2",
"remark-strip-mdx-imports-exports": "^1.0.1",
"resend": "^6.9.1",
"resend": "^6.9.2",
"server-only": "0.0.1",
"shiki": "^3.21.0",
"shiki": "^3.22.0",
"sonner": "^2.0.7",
"tailwind-merge": "^3.4.0",
"tailwindcss": "^4.1.18",
"tailwind-merge": "^3.5.0",
"tailwindcss": "^4.2.0",
"unified": "^11.0.5",
"zod": "^4.3.6"
},
@@ -105,18 +104,18 @@
"@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^9.39.2",
"@jakejarvis/eslint-config": "^4.0.7",
"@tailwindcss/postcss": "^4.1.18",
"@tailwindcss/postcss": "^4.2.0",
"@tailwindcss/typography": "^0.5.19",
"@types/hast": "^3.0.4",
"@types/mdx": "^2.0.13",
"@types/node": "^25.1.0",
"@types/node": "^25.3.0",
"@types/pg": "^8.16.0",
"@types/react": "19.2.10",
"@types/react": "19.2.14",
"@types/react-dom": "19.2.3",
"babel-plugin-react-compiler": "19.1.0-rc.3",
"cross-env": "^10.1.0",
"dotenv": "^17.2.3",
"drizzle-kit": "^0.31.8",
"dotenv": "^17.3.1",
"drizzle-kit": "^0.31.9",
"eslint": "^9.39.2",
"eslint-config-next": "16.1.6",
"eslint-config-prettier": "^10.1.8",
@@ -141,7 +140,7 @@
"engines": {
"node": ">=24.x"
},
"packageManager": "pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264",
"packageManager": "pnpm@10.30.0+sha512.2b5753de015d480eeb88f5b5b61e0051f05b4301808a82ec8b840c9d2adf7748eb352c83f5c1593ca703ff1017295bc3fdd3119abb9686efc96b9fcb18200937",
"cacheDirectories": [
"node_modules",
".next/cache"
+657 -825
View File
File diff suppressed because it is too large Load Diff