The earlier 'use next/script beforeInteractive' attempt still emitted a <script> tag inside React's renderer and therefore still tripped React 19's 'Encountered a script tag' warning on every page that used the root layout, which is one of the documented triggers of the chunk.reason.enqueueModel flight-client crash in vercel/next.js#92362. ThemeScript now returns null. The first paint picks the OS preference via a @media (prefers-color-scheme: dark) block in globals.css so no flash occurs for users on the default. An explicit stored choice is applied synchronously by ThemeSync (a small client component) on mount — a trade-off the shadcn dark-mode guide accepts too. Also fixes the .light class selector the new media-query rule introduces.
35 lines
No EOL
901 B
TypeScript
35 lines
No EOL
901 B
TypeScript
import type { Metadata } from "next";
|
|
import { Inter } from "next/font/google";
|
|
|
|
import { ThemeScript } from "@/components/theme/theme-script";
|
|
import { ThemeSync } from "@/components/theme/theme-sync";
|
|
import "./globals.css";
|
|
|
|
const inter = Inter({
|
|
subsets: ["latin"],
|
|
variable: "--font-inter",
|
|
display: "swap",
|
|
});
|
|
|
|
export const metadata: Metadata = {
|
|
title: "Client Board",
|
|
description: "Project tracking for client work",
|
|
};
|
|
|
|
export default function RootLayout({
|
|
children,
|
|
}: Readonly<{ children: React.ReactNode }>) {
|
|
return (
|
|
// suppressHydrationWarning: ThemeSync mutates the class on <html> when
|
|
// it mounts, so server and client markup differ here by design.
|
|
<html lang="en" className={inter.variable} suppressHydrationWarning>
|
|
<head>
|
|
<ThemeScript />
|
|
</head>
|
|
<body>
|
|
{children}
|
|
<ThemeSync />
|
|
</body>
|
|
</html>
|
|
);
|
|
} |