48 lines
1.5 KiB
TypeScript
48 lines
1.5 KiB
TypeScript
/**
|
|
* 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<Metadata> {
|
|
try {
|
|
const profile = await bff<PublicProfileForOg>(
|
|
`/u/${encodeURIComponent(handle)}`,
|
|
{ revalidate: 60 },
|
|
);
|
|
if (!profile) return ogDefault();
|
|
return ogForProfile({
|
|
handle: profile.handle,
|
|
name: profile.name,
|
|
postCount: profile.post_count,
|
|
});
|
|
} catch {
|
|
return ogDefault();
|
|
}
|
|
}
|