I'm currently working on a Next.js 15 project using the App Router and Tailwind CSS v4.0. Initially, I had Turbopack enabled, and my globals.css looked like this:
@import url(":ital,wght@0,100..900;1,100..900&display=swap");
@import url(":ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap");
@import "tailwindcss";
:root {
--background: #fff;
--foreground: #171717;
}
@theme {
--color-primary-black: #111;
--color-primary-white: #f5f5f4;
--font-poppins: "Poppins", sans-serif;
--font-montserrat: "Montserrat", sans-serif;
}
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
}
body {
background: var(--background);
color: var(--foreground);
}
And my page.tsx looked like this:
export default function Home() {
return (
<div className="flex flex-col items-center justify-center h-screen bg-primary-black">
<div className="text-primary-white font-poppins">Thanks for using my package!</div>
</div>
);
}
With Turbopack enabled, the fonts and colors only updated if I rebuilt and restarted the application (npm run build && npm run dev
).
After disabling Turbopack, the CSS changes started being reflected instantly, but the fonts stopped working entirely. The text now defaults to Helvetica because neither Poppins nor Montserrat are even being fetched in the network requests.
Temporary Fix
I found that adding the fonts inside layout.tsx using next/font/google
makes them work again:
import type { Metadata } from "next";
import { Geist, Geist_Mono, Poppins, Montserrat } from "next/font/google";
import "./globals.css";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
const poppins = Poppins({
variable: "--font-poppins",
subsets: ["latin"],
weight: ["100", "200", "300", "400", "500", "600", "700", "800", "900"],
display: "swap",
});
const montserrat = Montserrat({
variable: "--font-montserrat",
subsets: ["latin"],
weight: ["100", "200", "300", "400", "500", "600", "700", "800", "900"],
display: "swap",
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} ${poppins.variable} ${montserrat.variable} antialiased`}
>
{children}
</body>
</html>
);
}
While this fixes the issue, it doesn't seem like the correct way to do it.
I have 3 questions.
- Why does disabling Turbopack break font imports via
@import url()
in globals.css? - Is there a way to properly load external Google Fonts via globals.css rather than having to use
next/font/google
in layout.tsx? - Is this behavior expected in Next.js 15 + Tailwind v4, or is there a better approach to ensure fonts load correctly?
Appreciate any and all help.