Moves ClerkThemeProvider from the root layout into (app)/layout.tsx and (auth)/layout.tsx — it was previously mounted globally, shipping the ~240 KiB Clerk client SDK to every route including the public marketing page. Only Sidebar's UserButton and the (auth) sign-in/sign-up forms actually need client-side Clerk context; server-side auth() calls are unaffected since they read from proxy.ts's clerkMiddleware, not React context. Also fixes two WCAG AA contrast failures on the hero/header CTAs (orange-500/600 -> orange-700, ~2.8:1/3.6:1 -> ~5.5:1) and adds a missing <main> landmark around the landing page content. Source: PageSpeed Insights audit, mobile Performance 70 -> targets >90.
69 lines
2.0 KiB
TypeScript
69 lines
2.0 KiB
TypeScript
import type { Metadata, Viewport } from "next";
|
|
import { Inter } from "next/font/google";
|
|
import { ThemeProvider } from "next-themes";
|
|
import { NextIntlClientProvider } from "next-intl";
|
|
import { getLocale, getMessages } from "next-intl/server";
|
|
import { TRPCReactProvider } from "@/trpc/client";
|
|
import { ActivePetProvider } from "@/context/ActivePetContext";
|
|
import { Toaster } from "@/components/ui/sonner";
|
|
import "./globals.css";
|
|
|
|
const inter = Inter({
|
|
variable: "--font-sans",
|
|
subsets: ["latin"],
|
|
});
|
|
|
|
export const metadata: Metadata = {
|
|
metadataBase: new URL(process.env.NEXT_PUBLIC_APP_URL ?? "https://pawfeed.org"),
|
|
title: { default: "PawFeed", template: "%s · PawFeed" },
|
|
description: "The social platform where pets are the stars.",
|
|
openGraph: {
|
|
title: "PawFeed",
|
|
description: "The social platform where pets are the stars.",
|
|
url: "/",
|
|
siteName: "PawFeed",
|
|
type: "website",
|
|
},
|
|
twitter: {
|
|
card: "summary_large_image",
|
|
title: "PawFeed",
|
|
description: "The social platform where pets are the stars.",
|
|
},
|
|
};
|
|
|
|
export const viewport: Viewport = {
|
|
width: "device-width",
|
|
initialScale: 1,
|
|
viewportFit: "cover",
|
|
};
|
|
|
|
export default async function RootLayout({
|
|
children,
|
|
}: Readonly<{
|
|
children: React.ReactNode;
|
|
}>) {
|
|
const locale = await getLocale();
|
|
const messages = await getMessages();
|
|
|
|
return (
|
|
<html
|
|
lang={locale}
|
|
suppressHydrationWarning
|
|
className={`${inter.variable} h-full antialiased font-sans`}
|
|
>
|
|
<body className="min-h-full flex flex-col">
|
|
<ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange>
|
|
<NextIntlClientProvider locale={locale} messages={messages}>
|
|
<TRPCReactProvider>
|
|
<ActivePetProvider>
|
|
{children}
|
|
<Toaster />
|
|
</ActivePetProvider>
|
|
</TRPCReactProvider>
|
|
</NextIntlClientProvider>
|
|
</ThemeProvider>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|