text highlight and og image
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
/**
|
||||
* OG Image metadata utilities.
|
||||
*
|
||||
* Builds the /api/og URL with appropriate query params for dynamic
|
||||
* Open Graph image generation. Used by page-level metadata exports.
|
||||
*/
|
||||
|
||||
import { BOOK_NAMES, CC_LILAS } from "@/lib/constants";
|
||||
|
||||
const SITE_URL =
|
||||
process.env.NEXT_PUBLIC_SITE_URL || "https://prabhupadasays.org";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Types
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export type OgParams = {
|
||||
title: string;
|
||||
detail?: string;
|
||||
quote?: string;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Build the /api/og image URL
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Build a fully-qualified URL to the /api/og image endpoint.
|
||||
*
|
||||
* The URL is kept as short as possible — only non-empty params are included.
|
||||
* The quote is truncated to 260 chars to keep URL length reasonable.
|
||||
*/
|
||||
export function buildOgImageUrl(params: OgParams): string {
|
||||
const url = new URL("/api/og", SITE_URL);
|
||||
|
||||
url.searchParams.set("title", params.title);
|
||||
|
||||
if (params.detail) {
|
||||
url.searchParams.set("detail", params.detail);
|
||||
}
|
||||
|
||||
if (params.quote) {
|
||||
const truncated =
|
||||
params.quote.length > 260
|
||||
? params.quote.slice(0, 257) + "..."
|
||||
: params.quote;
|
||||
url.searchParams.set("quote", truncated);
|
||||
}
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build OG metadata object for use in Next.js page `metadata` exports.
|
||||
*
|
||||
* Returns the `openGraph` and `twitter` fields to spread into `Metadata`.
|
||||
*/
|
||||
export function buildOgMeta(params: OgParams & { description?: string }) {
|
||||
const imageUrl = buildOgImageUrl(params);
|
||||
const description =
|
||||
params.description ||
|
||||
params.quote ||
|
||||
`${params.title}${params.detail ? ` — ${params.detail}` : ""}`;
|
||||
|
||||
return {
|
||||
openGraph: {
|
||||
title: params.title,
|
||||
description,
|
||||
images: [
|
||||
{
|
||||
url: imageUrl,
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: params.title,
|
||||
},
|
||||
],
|
||||
siteName: "Prabhupāda Says",
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image" as const,
|
||||
title: params.title,
|
||||
description,
|
||||
images: [imageUrl],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers for common page types
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** OG metadata for a book page. */
|
||||
export function ogForBook(code: string) {
|
||||
const title = BOOK_NAMES[code] || code.toUpperCase();
|
||||
return buildOgMeta({ title });
|
||||
}
|
||||
|
||||
/** OG metadata for a verse page. */
|
||||
export function ogForVerse(
|
||||
code: string,
|
||||
parts: { division?: string; chapter: number; verse: number },
|
||||
) {
|
||||
const title = BOOK_NAMES[code] || code.toUpperCase();
|
||||
let detail: string;
|
||||
|
||||
if (code === "sb" && parts.division) {
|
||||
detail = `Canto ${parts.division}, Chapter ${parts.chapter}, Verse ${parts.verse}`;
|
||||
} else if (code === "cc" && parts.division) {
|
||||
const lila = CC_LILAS[parts.division] || parts.division;
|
||||
detail = `${lila}, Chapter ${parts.chapter}, Verse ${parts.verse}`;
|
||||
} else {
|
||||
detail = `Chapter ${parts.chapter}, Verse ${parts.verse}`;
|
||||
}
|
||||
|
||||
return buildOgMeta({ title, detail });
|
||||
}
|
||||
|
||||
/** OG metadata for a prose chapter. */
|
||||
export function ogForChapter(code: string, chapterTitle: string) {
|
||||
const bookTitle = BOOK_NAMES[code] || code.toUpperCase();
|
||||
return buildOgMeta({ title: bookTitle, detail: chapterTitle });
|
||||
}
|
||||
|
||||
/** OG metadata for an essay. */
|
||||
export function ogForEssay(title: string) {
|
||||
return buildOgMeta({
|
||||
title,
|
||||
detail: "Essay by Śrīla Prabhupāda",
|
||||
});
|
||||
}
|
||||
|
||||
/** OG metadata for a letter. */
|
||||
export function ogForLetter(recipient: string, meta?: string) {
|
||||
return buildOgMeta({
|
||||
title: `Letter to ${recipient}`,
|
||||
detail: meta || undefined,
|
||||
});
|
||||
}
|
||||
|
||||
/** OG metadata for a journal entry. */
|
||||
export function ogForJournal(journalTitle: string, entryTitle?: string) {
|
||||
return buildOgMeta({
|
||||
title: journalTitle,
|
||||
detail: entryTitle || undefined,
|
||||
});
|
||||
}
|
||||
|
||||
/** OG metadata for a magazine issue. */
|
||||
export function ogForMagazine(magazineTitle: string, issueTitle?: string) {
|
||||
return buildOgMeta({
|
||||
title: magazineTitle,
|
||||
detail: issueTitle || undefined,
|
||||
});
|
||||
}
|
||||
|
||||
/** OG metadata for an other document chapter. */
|
||||
export function ogForOtherDocument(docTitle: string, chapterTitle?: string) {
|
||||
return buildOgMeta({
|
||||
title: docTitle,
|
||||
detail: chapterTitle || undefined,
|
||||
});
|
||||
}
|
||||
|
||||
/** Default OG metadata for the site. */
|
||||
export function ogDefault() {
|
||||
return buildOgMeta({
|
||||
title: "Prabhupāda Says",
|
||||
description:
|
||||
"Browse the books and teachings of His Divine Grace A.C. Bhaktivedanta Swami Prabhupāda",
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user