feat: share post to other apps
This commit is contained in:
@@ -385,3 +385,88 @@ export function ogDefault() {
|
||||
quote: SITE_DESCRIPTION,
|
||||
});
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Social: profile + post OG cards
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// Profiles and posts get their own image-rendering routes (see
|
||||
// app/api/og/profile/[handle] and app/api/og/post/[id]) so the card
|
||||
// can carry avatars, author bylines, and (for posts) the attached
|
||||
// image. The helpers below just produce the Metadata object pointing
|
||||
// at those routes. They live here rather than inline in share-og.ts
|
||||
// so non-share entrypoints (e.g. a profile/post page that adds its
|
||||
// own `generateMetadata`) can reuse the same builder.
|
||||
|
||||
/** OG metadata for a public user profile (`/u/<handle>`). */
|
||||
export function ogForProfile(p: {
|
||||
handle: string;
|
||||
name: string;
|
||||
postCount?: number;
|
||||
}) {
|
||||
const imageUrl = new URL(
|
||||
`/api/og/profile/${encodeURIComponent(p.handle)}`,
|
||||
SITE_URL,
|
||||
).toString();
|
||||
const title = `${p.name} (@${p.handle})`;
|
||||
const stats =
|
||||
typeof p.postCount === "number"
|
||||
? `${p.postCount} post${p.postCount === 1 ? "" : "s"} on Prabhupāda Says`
|
||||
: "Reading shared on Prabhupāda Says";
|
||||
return {
|
||||
title,
|
||||
description: stats,
|
||||
openGraph: {
|
||||
title,
|
||||
description: stats,
|
||||
images: [{ url: imageUrl, width: 1200, height: 630, alt: title }],
|
||||
siteName: "Prabhupāda Says",
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image" as const,
|
||||
title,
|
||||
description: stats,
|
||||
images: [imageUrl],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/** OG metadata for a single post (`/u/<handle>/posts#post-<id>` shares). */
|
||||
export function ogForPost(p: {
|
||||
id: string;
|
||||
caption: string;
|
||||
source_title?: string | null;
|
||||
author_name?: string | null;
|
||||
author_handle?: string | null;
|
||||
}) {
|
||||
const imageUrl = new URL(
|
||||
`/api/og/post/${encodeURIComponent(p.id)}`,
|
||||
SITE_URL,
|
||||
).toString();
|
||||
const byline = p.author_handle
|
||||
? `${p.author_name ?? p.author_handle} (@${p.author_handle})`
|
||||
: p.author_name ?? "Prabhupāda Says";
|
||||
const reference = p.source_title?.trim() || "Prabhupāda Says";
|
||||
// Description is shown in some unfurlers (Slack, Discord) when the
|
||||
// image fails to load — keep the caption visible there too.
|
||||
const truncatedCaption =
|
||||
p.caption.length > 200 ? p.caption.slice(0, 197) + "…" : p.caption;
|
||||
const description = `“${truncatedCaption}” — ${reference}`;
|
||||
const title = `${reference} · shared by ${byline}`;
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
openGraph: {
|
||||
title,
|
||||
description,
|
||||
images: [{ url: imageUrl, width: 1200, height: 630, alt: reference }],
|
||||
siteName: "Prabhupāda Says",
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image" as const,
|
||||
title,
|
||||
description,
|
||||
images: [imageUrl],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user