/** * /u/[handle] — public profile, Posts tab (default). * * Server shell that exists for three reasons: * * 1. Export `generateMetadata` so direct shares of this URL * (https://prabhupadasays.org/u/) get a rich OG card * pointing at /api/og/profile/. The layout and the body * below are client components; only this file is server. * 2. Emit server-rendered ProfilePage/Person JSON-LD so crawlers + LLMs * can resolve the profile (the layout is a client component and * fetches the profile after hydration, too late for crawlers). * 3. Mount the client tree (), which reads the * ProfileContext provided by the parent layout. */ import type { Metadata } from "next"; import { bff } from "@/lib/bff"; import { JsonLd } from "@/components/seo/json-ld"; import { profileJsonLd } from "@/lib/jsonld"; import { PostsGrid } from "./posts-grid"; import { metadataForHandle } from "./profile-og"; type Props = { params: Promise<{ handle: string }> }; export async function generateMetadata({ params }: Props): Promise { const { handle } = await params; return metadataForHandle(handle); } export default async function PublicProfilePage({ params }: Props) { const { handle } = await params; let person: object | null = null; try { const profile = await bff<{ handle: string; name: string; avatar_url?: string | null; }>(`/u/${encodeURIComponent(handle)}`, { revalidate: 60 }); if (profile) { person = profileJsonLd({ path: `/u/${profile.handle}`, name: profile.name, handle: profile.handle, image: profile.avatar_url ?? null, }); } } catch { // Profile unavailable — skip JSON-LD rather than fail the page. } return ( <> {person ? : null} ); }