/** * Shared `generateMetadata` helper for /u/[handle] routes. * * Both `/u/[handle]/page.tsx` (Posts tab) and `/u/[handle]/posts/page.tsx` * (scroll feed) want the same profile-flavoured OG card on direct URL * shares — the difference between the two is purely the rendered body, * not the social preview. This helper fetches the profile via the * server-side BFF client and hands it to the canonical `ogForProfile` * builder. * * Failures (404 handle, BFF unreachable, malformed payload) fall back * to the site-level `ogDefault` so unfurlers still get a valid card * rather than nothing. * * Note: the page's underlying `app/u/[handle]/layout.tsx` is a client * component and can't export `generateMetadata`. The metadata has to * live on the (server) page that mounts the client tree, which is why * we slim each page.tsx down to a server shell + a separate client * content file. */ import type { Metadata } from "next"; import { bff } from "@/lib/bff"; import { ogDefault, ogForProfile } from "@/lib/og"; type PublicProfileForOg = { handle: string; name: string; post_count?: number; }; export async function metadataForHandle(handle: string): Promise { try { const profile = await bff( `/u/${encodeURIComponent(handle)}`, { revalidate: 60 }, ); if (!profile) return ogDefault(); return ogForProfile({ handle: profile.handle, name: profile.name, postCount: profile.post_count, }); } catch { return ogDefault(); } }