Social-sharing previews had no image — layout.tsx's OG/Twitter tags existed but pointed at nothing. Adds src/app/opengraph-image.tsx using next/og's ImageResponse to render a branded card (paw mark, wordmark, tagline) at request time instead of shipping a static asset, and switches twitter.card to summary_large_image now that there's an image for it to show.
72 lines
2.0 KiB
TypeScript
72 lines
2.0 KiB
TypeScript
import type { Metadata, Viewport } from "next";
|
|
import { Inter } from "next/font/google";
|
|
import { ClerkProvider } from "@clerk/nextjs";
|
|
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 (
|
|
<ClerkProvider
|
|
appearance={{
|
|
variables: {
|
|
colorPrimary: "#F97316",
|
|
colorBackground: "#FAFAFA",
|
|
},
|
|
}}
|
|
>
|
|
<html lang={locale} className={`${inter.variable} h-full antialiased font-sans`}>
|
|
<body className="min-h-full flex flex-col">
|
|
<NextIntlClientProvider locale={locale} messages={messages}>
|
|
<TRPCReactProvider>
|
|
<ActivePetProvider>
|
|
{children}
|
|
<Toaster />
|
|
</ActivePetProvider>
|
|
</TRPCReactProvider>
|
|
</NextIntlClientProvider>
|
|
</body>
|
|
</html>
|
|
</ClerkProvider>
|
|
);
|
|
}
|