feat: share post to other apps

This commit is contained in:
gosangam
2026-05-31 08:04:46 +05:30
parent 03b8f85e06
commit 336f478f8b
13 changed files with 1290 additions and 82 deletions
+85
View File
@@ -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],
},
};
}