import type { Metadata, Viewport } from "next"; import { Geist, Sora, JetBrains_Mono } from "next/font/google"; import "../globals.css"; import { locales, getDictionary, isValidLocale, defaultLocale, type Locale, } from "@/lib/dictionaries"; import { SITE_URL, localeAlternates } from "@/lib/seo"; import Navbar from "@/components/layout/Navbar"; import Footer from "@/components/layout/Footer"; import ScanlineOverlay from "@/components/ui/ScanlineOverlay"; import LangBanner from "@/components/ui/LangBanner"; const geistSans = Geist({ subsets: ["latin"], variable: "--font-geist-sans", display: "swap", }); const sora = Sora({ subsets: ["latin"], variable: "--font-sora", display: "swap", weight: ["300", "400", "500", "600", "700"], }); const jetbrains = JetBrains_Mono({ subsets: ["latin"], variable: "--font-jetbrains", display: "swap", weight: ["400", "500"], }); // Pre-render both locale shells at build time export function generateStaticParams() { return locales.map((locale) => ({ locale })); } // Tell the browser the document is dark before any CSS/JS runs. This sets the // / theme-color in the SSR so the initial // canvas (and mobile browser chrome) paints dark, never white. export const viewport: Viewport = { colorScheme: "dark", themeColor: "#0F1117", }; export async function generateMetadata({ params, }: { params: Promise<{ locale: string }>; }): Promise { const { locale } = await params; const isSR = locale === "sr"; return { title: { default: isSR ? "Name — Full-stack inženjering, od početka do kraja" : "Name — Full-stack engineering, end to end", template: "%s · Name", }, description: isSR ? "Premium full-stack razvoj, deployment i self-hosted infrastruktura." : "Premium full-stack development, deployment, and self-hosted infrastructure.", metadataBase: new URL(SITE_URL), // Canonical — self-referencing within each locale. // Subpages override this with their own path via localeAlternates(). alternates: localeAlternates(locale), openGraph: { title: isSR ? "Name — Full-stack inženjering" : "Name — Full-stack engineering, end to end", description: isSR ? "Premium full-stack razvoj i self-hosted infrastruktura." : "Premium full-stack development and self-hosted infrastructure.", type: "website", locale: isSR ? "sr_RS" : "en_US", alternateLocale: isSR ? ["en_US"] : ["sr_RS"], siteName: "ksan.dev", url: `${SITE_URL}/${locale}`, }, twitter: { card: "summary_large_image", title: isSR ? "Name — Full-stack inženjering" : "Name — Full-stack engineering", }, robots: { index: true, follow: true, "max-image-preview": "large", "max-snippet": -1, }, }; } export default async function LocaleLayout({ children, params, }: { children: React.ReactNode; params: Promise<{ locale: string }>; }) { const { locale: rawLocale } = await params; const locale: Locale = isValidLocale(rawLocale) ? rawLocale : defaultLocale; const dict = getDictionary(locale); return (
{children}