The scout hit a snag
+{errTitle}
- Something broke mid-scout. Try again — if it keeps happening, the pitch may be down for a moment. + {errBody}
ref: {error.digest}
} diff --git a/app/global-error.tsx b/app/global-error.tsx index 7f2c01d..7a456f4 100644 --- a/app/global-error.tsx +++ b/app/global-error.tsx @@ -1,6 +1,8 @@ "use client"; import { useEffect } from "react"; +import { useLocale } from "@/lib/i18n/useLocale"; +import { useUIDict } from "@/lib/i18n/hooks"; // Last-resort boundary: a throw in the root layout itself escapes app/error.tsx, // so this replaces the entire document (it must render its own /). @@ -18,8 +20,15 @@ export default function GlobalError({ console.error("[gitfut] global error:", error); }, [error]); + // GlobalError renders before the LocaleProvider mounts, so useLocale() may + // not have a value. Fall back to ENGLISH silently — global errors are rare + // and the user can still resolve the message. + const locale = useLocale(); + const ui = useUIDict().errors; + void locale; + return ( - +Match abandoned
+{ui.globalTitle}
- Something went badly wrong. Reload to get back to the pitch. + {ui.globalBody}
{error.digest && ({ + // Title/description are pinned to EN for SEO crawlers — search engines + // index the EN copy and ignore the user's locale. Switching to per-locale + // metadata would require for the homepage which is + // not part of this change. + const en = getDict(DEFAULT_LOCALE); + const TITLE = `${en.meta.brand} — ${en.meta.tagline}`; + const DESCRIPTION = + "Rate any GitHub profile out of 99 as a FIFA-Ultimate-Team-style player card, scored from real commits, stars and contributions. Get scouted and share your card."; + return { + metadataBase: new URL("https://gitfut.com"), title: TITLE, description: DESCRIPTION, - }, -}; + keywords: [ + "GitHub profile card", + "rate my GitHub", + "GitHub stats", + "developer trading card", + "FUT card", + "GitHub rating", + "World Cup", + "GitFut", + ], + alternates: { canonical: "/" }, + openGraph: { + title: TITLE, + description: DESCRIPTION, + url: "https://gitfut.com", + siteName: "GitFut", + type: "website", + }, + twitter: { + card: "summary_large_image", + title: TITLE, + description: DESCRIPTION, + }, + }; +} export const viewport: Viewport = { themeColor: "#02001e", }; -export default function RootLayout({ children }: { children: React.ReactNode }) { +export default async function RootLayout({ children }: { children: React.ReactNode }) { + // Resolve locale on the server (cookie > Accept-Language > default) so the + // initial markup matches the user's locale — prevents the visible "EN briefly + // then KO" flash on first paint. + const cookieStore = await cookies(); + const locale = localeFromCookie(cookieStore.get(LOCALE_COOKIE_NAME)?.value); + return (
- {children} +