fix: og image generation

This commit is contained in:
gosangam
2026-05-06 01:35:06 +05:30
parent b81b18632d
commit de374eab8b
27 changed files with 703 additions and 4 deletions
+24
View File
@@ -1,3 +1,6 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -6,6 +9,8 @@ import {
type BbdChapter,
type BbdSidebarItem,
} from "@/lib/bbd";
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { BOOK_NAMES } from "@/lib/constants";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -13,6 +18,25 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";
import { MobileNav, type MobileNavGroup } from "@/components/mobile-nav";
// ---------------------------------------------------------------------------
// Metadata
// ---------------------------------------------------------------------------
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const sp = await searchParams;
const hlQuote = extractQuoteFromHl(sp);
if (hlQuote) {
return buildOgMeta({ title: BOOK_NAMES["bbd"], quote: hlQuote });
}
return ogForChapter("bbd", "");
}
// ---------------------------------------------------------------------------
// Page
// ---------------------------------------------------------------------------
+27
View File
@@ -1,9 +1,36 @@
import type { Metadata } from "next";
import Link from "next/link";
import { PageHeader } from "@/components/page-header";
import { notFound } from "next/navigation";
import { getBookMeta, getSingleVerse, getChapterVerseIndex } from "@/lib/api";
import { ChapterViewer } from "@/app/books/chapter-viewer";
import type { MobileNavGroup } from "@/components/mobile-nav";
import { ogForVerse, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
export const dynamic = "force-dynamic";
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string; verse: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const { chapter, verse } = await params;
const sp = await searchParams;
const quote = extractQuoteFromHl(sp);
if (quote) {
return buildOgMeta({
title: "Bhagavad-gītā As It Is",
detail: `Chapter ${chapter}, Verse ${verse}`,
quote,
});
}
return ogForVerse("bg", {
chapter: parseInt(chapter),
verse: parseInt(verse),
});
}
type BgMeta = {
book: string;
+18
View File
@@ -1,3 +1,4 @@
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -6,6 +7,8 @@ import {
type BkChapter,
type BkSidebarItem,
} from "@/lib/bk";
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { BOOK_NAMES } from "@/lib/constants";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -15,6 +18,21 @@ import { MobileNav, type MobileNavGroup } from "@/components/mobile-nav";
export const dynamic = "force-dynamic";
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const sp = await searchParams;
const hlQuote = extractQuoteFromHl(sp);
if (hlQuote) {
return buildOgMeta({ title: BOOK_NAMES["bk"], quote: hlQuote });
}
return ogForChapter("bk", "");
}
// ---------------------------------------------------------------------------
// Page
// ---------------------------------------------------------------------------
+27
View File
@@ -1,3 +1,4 @@
import type { Metadata } from "next";
import fs from "fs";
import path from "path";
import Link from "next/link";
@@ -12,6 +13,9 @@ import {
} from "@/lib/api";
import { ChapterViewer } from "@/app/books/chapter-viewer";
import type { MobileNavGroup } from "@/components/mobile-nav";
import { ogForVerse, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
export const dynamic = "force-dynamic";
type BsMeta = {
book: string;
@@ -110,6 +114,29 @@ async function getVerseWithFallback(
return null;
}
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string; verse: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const { chapter, verse } = await params;
const sp = await searchParams;
const quote = extractQuoteFromHl(sp);
if (quote) {
return buildOgMeta({
title: "Śrī Brahma-saṁhitā",
detail: `Chapter ${chapter}, Verse ${parseInt(verse)}`,
quote,
});
}
return ogForVerse("bs", {
chapter: parseInt(chapter),
verse: parseInt(verse),
});
}
export default async function VersePage({
params,
}: {
+18
View File
@@ -1,3 +1,4 @@
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -6,6 +7,8 @@ import {
type CbhcChapter,
type CbhcSidebarItem,
} from "@/lib/cbhc";
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { BOOK_NAMES } from "@/lib/constants";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -15,6 +18,21 @@ import { MobileNav, type MobileNavGroup } from "@/components/mobile-nav";
export const dynamic = "force-dynamic";
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const sp = await searchParams;
const hlQuote = extractQuoteFromHl(sp);
if (hlQuote) {
return buildOgMeta({ title: BOOK_NAMES["cbhc"], quote: hlQuote });
}
return ogForChapter("cbhc", "");
}
// ---------------------------------------------------------------------------
// Page
// ---------------------------------------------------------------------------
@@ -1,9 +1,13 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { PageHeader } from "@/components/page-header";
import { notFound } from "next/navigation";
import { getBookMeta, getSingleVerse, getChapterVerseIndex } from "@/lib/api";
import { ChapterViewer } from "@/app/books/chapter-viewer";
import type { MobileNavGroup } from "@/components/mobile-nav";
import { ogForVerse, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
type ChapterInfo = {
number: number;
@@ -19,6 +23,31 @@ type LilaInfo = {
chapters: ChapterInfo[];
};
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ lila: string; chapter: string; verse: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const { lila, chapter, verse } = await params;
const sp = await searchParams;
const quote = extractQuoteFromHl(sp);
if (quote) {
const bookTitle = "Śrī Caitanya-caritāmṛta";
return buildOgMeta({
title: bookTitle,
detail: `${lila.charAt(0).toUpperCase() + lila.slice(1)}, Chapter ${chapter}, Verse ${verse}`,
quote,
});
}
return ogForVerse("cc", {
division: lila,
chapter: parseInt(chapter),
verse: parseInt(verse),
});
}
export default async function CcVersePage({
params,
}: {
+24
View File
@@ -1,3 +1,6 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -6,6 +9,8 @@ import {
type DsChapter,
type DsSidebarItem,
} from "@/lib/ds";
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { BOOK_NAMES } from "@/lib/constants";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -13,6 +18,25 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";
import { MobileNav, type MobileNavGroup } from "@/components/mobile-nav";
// ---------------------------------------------------------------------------
// Metadata
// ---------------------------------------------------------------------------
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const sp = await searchParams;
const hlQuote = extractQuoteFromHl(sp);
if (hlQuote) {
return buildOgMeta({ title: BOOK_NAMES["ds"], quote: hlQuote });
}
return ogForChapter("ds", "");
}
// ---------------------------------------------------------------------------
// Page
// ---------------------------------------------------------------------------
+24
View File
@@ -1,3 +1,6 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -6,6 +9,8 @@ import {
type EjChapter,
type EjSidebarItem,
} from "@/lib/ej";
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { BOOK_NAMES } from "@/lib/constants";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -13,6 +18,25 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";
import { MobileNav, type MobileNavGroup } from "@/components/mobile-nav";
// ---------------------------------------------------------------------------
// Metadata
// ---------------------------------------------------------------------------
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const sp = await searchParams;
const hlQuote = extractQuoteFromHl(sp);
if (hlQuote) {
return buildOgMeta({ title: BOOK_NAMES["ej"], quote: hlQuote });
}
return ogForChapter("ej", "");
}
// ---------------------------------------------------------------------------
// Page
// ---------------------------------------------------------------------------
+24
View File
@@ -1,3 +1,6 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -6,6 +9,8 @@ import {
type EkChapter,
type EkSidebarItem,
} from "@/lib/ek";
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { BOOK_NAMES } from "@/lib/constants";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -13,6 +18,25 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";
import { MobileNav, type MobileNavGroup } from "@/components/mobile-nav";
// ---------------------------------------------------------------------------
// Metadata
// ---------------------------------------------------------------------------
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const sp = await searchParams;
const hlQuote = extractQuoteFromHl(sp);
if (hlQuote) {
return buildOgMeta({ title: BOOK_NAMES["ek"], quote: hlQuote });
}
return ogForChapter("ek", "");
}
// ---------------------------------------------------------------------------
// Page
// ---------------------------------------------------------------------------
+18
View File
@@ -1,3 +1,4 @@
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -6,6 +7,8 @@ import {
type GgChapter,
type GgSidebarItem,
} from "@/lib/gg";
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { BOOK_NAMES } from "@/lib/constants";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -15,6 +18,21 @@ import { MobileNav, type MobileNavGroup } from "@/components/mobile-nav";
export const dynamic = "force-dynamic";
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const sp = await searchParams;
const hlQuote = extractQuoteFromHl(sp);
if (hlQuote) {
return buildOgMeta({ title: BOOK_NAMES["gg"], quote: hlQuote });
}
return ogForChapter("gg", "");
}
// ---------------------------------------------------------------------------
// Page
// ---------------------------------------------------------------------------
+24
View File
@@ -1,3 +1,6 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -6,6 +9,8 @@ import {
type HkhChapter,
type HkhSidebarItem,
} from "@/lib/hkh";
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { BOOK_NAMES } from "@/lib/constants";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -13,6 +18,25 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";
import { MobileNav, type MobileNavGroup } from "@/components/mobile-nav";
// ---------------------------------------------------------------------------
// Metadata
// ---------------------------------------------------------------------------
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const sp = await searchParams;
const hlQuote = extractQuoteFromHl(sp);
if (hlQuote) {
return buildOgMeta({ title: BOOK_NAMES["hkh"], quote: hlQuote });
}
return ogForChapter("hkh", "");
}
// ---------------------------------------------------------------------------
// Page
// ---------------------------------------------------------------------------
+38
View File
@@ -1,3 +1,6 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -7,6 +10,7 @@ import {
type IsoIntroSegment,
type IsoSidebarItem,
} from "@/lib/iso";
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -28,6 +32,40 @@ function isIntroSegment(
return "paragraphs" in content && "order" in content;
}
// ---------------------------------------------------------------------------
// Metadata
// ---------------------------------------------------------------------------
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ mantra: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const { mantra: slug } = await params;
const sp = await searchParams;
const quote = extractQuoteFromHl(sp);
if (quote) {
return buildOgMeta({
title: "Śrī Īśopaniṣad",
detail: `Mantra ${slug}`,
quote,
});
}
const content = await getIsoContent(slug);
const isVerse_ = content && "mantra" in content && "devanagari" in content;
const title = isVerse_
? `${(content as IsoVerse).reference}: ${(content as IsoVerse).title}`
: content && "title" in content
? (content as IsoIntroSegment).title
: `Mantra ${slug}`;
return ogForChapter("iso", title);
}
// ---------------------------------------------------------------------------
// Page
// ---------------------------------------------------------------------------
+30
View File
@@ -1,6 +1,11 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import { getProseChapter, getProseChapters } from "@/lib/api";
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { BOOK_NAMES } from "@/lib/constants";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -8,6 +13,31 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";
import { MobileNav, type MobileNavGroup } from "@/components/mobile-nav";
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ volume: string; slug: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const { volume, slug } = await params;
const sp = await searchParams;
const vol = parseInt(volume);
const chapter = !isNaN(vol) ? await getProseChapter("kb", vol, slug) : null;
const hlQuote = extractQuoteFromHl(sp);
if (hlQuote) {
return buildOgMeta({
title: BOOK_NAMES["kb"],
detail: chapter ? `Volume ${vol} — ${chapter.title}` : `Volume ${vol}`,
quote: hlQuote,
});
}
return ogForChapter(
"kb",
chapter ? `Volume ${vol} — ${chapter.title}` : `Volume ${vol}`,
);
}
export default async function KbChapterPage({
params,
}: {
+24
View File
@@ -1,3 +1,6 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -6,6 +9,8 @@ import {
type LclChapter,
type LclSidebarItem,
} from "@/lib/lcl";
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { BOOK_NAMES } from "@/lib/constants";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -13,6 +18,25 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";
import { MobileNav, type MobileNavGroup } from "@/components/mobile-nav";
// ---------------------------------------------------------------------------
// Metadata
// ---------------------------------------------------------------------------
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const sp = await searchParams;
const hlQuote = extractQuoteFromHl(sp);
if (hlQuote) {
return buildOgMeta({ title: BOOK_NAMES["lcl"], quote: hlQuote });
}
return ogForChapter("lcl", "");
}
// ---------------------------------------------------------------------------
// Page
// ---------------------------------------------------------------------------
+23 -3
View File
@@ -1,3 +1,6 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -6,6 +9,8 @@ import {
type LobChapter,
type LobSidebarItem,
} from "@/lib/lob";
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { BOOK_NAMES } from "@/lib/constants";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -13,6 +18,21 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";
import { MobileNav, type MobileNavGroup } from "@/components/mobile-nav";
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const sp = await searchParams;
const hlQuote = extractQuoteFromHl(sp);
if (hlQuote) {
return buildOgMeta({ title: BOOK_NAMES["lob"], quote: hlQuote });
}
return ogForChapter("lob", "");
}
// ---------------------------------------------------------------------------
// Page
// ---------------------------------------------------------------------------
@@ -76,7 +96,7 @@ export default async function LobChapterPage({
<Card>
<CardContent className="py-8 px-6 sm:px-8">
<div className="space-y-4">
{content.paragraphs.map((paragraph, i) => (
{content.paragraphs.map((paragraph, i) =>
paragraph.startsWith("<b>") ? (
<div
key={i}
@@ -89,8 +109,8 @@ export default async function LobChapterPage({
className="text-base text-foreground leading-relaxed"
dangerouslySetInnerHTML={{ __html: paragraph }}
/>
)
))}
),
)}
</div>
</CardContent>
</Card>
+20
View File
@@ -1,3 +1,6 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -6,6 +9,8 @@ import {
type MgChapter,
type MgSidebarItem,
} from "@/lib/mg";
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { BOOK_NAMES } from "@/lib/constants";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -13,6 +18,21 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";
import { MobileNav, type MobileNavGroup } from "@/components/mobile-nav";
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const sp = await searchParams;
const hlQuote = extractQuoteFromHl(sp);
if (hlQuote) {
return buildOgMeta({ title: BOOK_NAMES["mg"], quote: hlQuote });
}
return ogForChapter("mg", "");
}
// ---------------------------------------------------------------------------
// Page
// ---------------------------------------------------------------------------
+27
View File
@@ -12,6 +12,33 @@ import {
} from "@/lib/api";
import { ChapterViewer } from "@/app/books/chapter-viewer";
import type { MobileNavGroup } from "@/components/mobile-nav";
import type { Metadata } from "next";
import { ogForVerse, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
export const dynamic = "force-dynamic";
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string; verse: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const { chapter, verse } = await params;
const sp = await searchParams;
const quote = extractQuoteFromHl(sp);
if (quote) {
return buildOgMeta({
title: "Mukunda-mālā-stotra",
detail: `Chapter ${chapter}, Verse ${verse}`,
quote,
});
}
return ogForVerse("mm", {
chapter: parseInt(chapter),
verse: parseInt(verse),
});
}
type MmMeta = {
book: string;
+27
View File
@@ -1,3 +1,6 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import fs from "fs";
import path from "path";
import Link from "next/link";
@@ -10,6 +13,7 @@ import {
type VerseIndexEntry,
type VerseRecord,
} from "@/lib/api";
import { ogForVerse, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { ChapterViewer } from "@/app/books/chapter-viewer";
import type { MobileNavGroup } from "@/components/mobile-nav";
@@ -110,6 +114,29 @@ async function getVerseWithFallback(
return null;
}
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string; verse: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const { chapter, verse } = await params;
const sp = await searchParams;
const quote = extractQuoteFromHl(sp);
if (quote) {
return buildOgMeta({
title: "Nārada-bhakti-sūtra",
detail: `Chapter ${chapter}, Verse ${verse}`,
quote,
});
}
return ogForVerse("nbs", {
chapter: parseInt(chapter),
verse: parseInt(verse),
});
}
export default async function VersePage({
params,
}: {
+26
View File
@@ -1,3 +1,6 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -7,6 +10,7 @@ import {
type NoiIntroSegment,
type NoiSidebarItem,
} from "@/lib/noi";
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -32,6 +36,28 @@ function isIntroSegment(
// Page
// ---------------------------------------------------------------------------
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ text: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const { text: slug } = await params;
const sp = await searchParams;
const quote = extractQuoteFromHl(sp);
if (quote) {
return buildOgMeta({
title: "The Nectar of Instruction",
detail: `Text ${slug}`,
quote,
});
}
return ogForChapter("noi", `Text ${slug}`);
}
export default async function NoiTextPage({
params,
}: {
@@ -1,9 +1,13 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { PageHeader } from "@/components/page-header";
import { notFound } from "next/navigation";
import { getBookMeta, getSingleVerse, getChapterVerseIndex } from "@/lib/api";
import { ChapterViewer } from "@/app/books/chapter-viewer";
import type { MobileNavGroup } from "@/components/mobile-nav";
import { ogForVerse, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
type ChapterInfo = {
number: number;
@@ -18,6 +22,30 @@ type CantoInfo = {
chapters: ChapterInfo[];
};
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ canto: string; chapter: string; verse: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const { canto, chapter, verse } = await params;
const sp = await searchParams;
const quote = extractQuoteFromHl(sp);
if (quote) {
return buildOgMeta({
title: "Śrīmad-Bhāgavatam",
detail: `Canto ${canto}, Chapter ${chapter}, Verse ${verse}`,
quote,
});
}
return ogForVerse("sb", {
division: canto,
chapter: parseInt(chapter),
verse: parseInt(verse),
});
}
export default async function SbVersePage({
params,
}: {
@@ -1,9 +1,13 @@
import type { Metadata } from "next";
import Link from "next/link";
import { PageHeader } from "@/components/page-header";
import { notFound } from "next/navigation";
import { getBookMeta, getSingleVerse, getChapterVerseIndex } from "@/lib/api";
import { ChapterViewer } from "@/app/books/chapter-viewer";
import type { MobileNavGroup } from "@/components/mobile-nav";
import { ogForVerse, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
export const dynamic = "force-dynamic";
type Sb1962Meta = {
book: string;
@@ -13,6 +17,29 @@ type Sb1962Meta = {
chapters: { number: number; title: string; totalVerses: number }[];
};
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ chapter: string; verse: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const { chapter, verse } = await params;
const sp = await searchParams;
const quote = extractQuoteFromHl(sp);
if (quote) {
return buildOgMeta({
title: "Śrīmad-Bhāgavatam (1962)",
detail: `Chapter ${chapter}, Verse ${verse}`,
quote,
});
}
return ogForVerse("sb1962", {
chapter: parseInt(chapter),
verse: parseInt(verse),
});
}
export default async function VersePage({
params,
}: {
+26
View File
@@ -1,7 +1,9 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import { ogForEssay, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -90,6 +92,30 @@ async function getEssaySidebar(): Promise<SidebarItem[]> {
// Page
// ---------------------------------------------------------------------------
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ slug: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const { slug } = await params;
const sp = await searchParams;
const essay = await getEssay(slug);
if (!essay) return {};
const hlQuote = extractQuoteFromHl(sp);
if (hlQuote) {
return buildOgMeta({
title: essay.title,
detail: "Essay by Śrīla Prabhupāda",
quote: hlQuote,
});
}
return ogForEssay(essay.title);
}
export default async function EssayPage({
params,
}: {
+33
View File
@@ -1,5 +1,6 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -9,6 +10,7 @@ import {
slugToBookCode,
type JournalSidebarItem,
} from "@/lib/journals";
import { ogForJournal, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -16,6 +18,37 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";
import { MobileNav, type MobileNavGroup } from "@/components/mobile-nav";
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ slug: string; chapter: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const { slug, chapter: chapterSlug } = await params;
const sp = await searchParams;
const bookCode = slugToBookCode(slug);
const [meta, content] = await Promise.all([
getJournalMeta(bookCode),
getJournalContent(bookCode, chapterSlug),
]);
const journalTitle = meta?.title || slug;
const entryTitle = content?.title || chapterSlug;
const quote = extractQuoteFromHl(sp);
if (quote) {
return buildOgMeta({
title: journalTitle,
detail: entryTitle,
quote,
});
}
return ogForJournal(journalTitle, entryTitle);
}
export default async function JournalChapterPage({
params,
}: {
+14 -1
View File
@@ -4,7 +4,7 @@ import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import { getLetter, getAdjacentLetters } from "@/lib/letters";
import { ogForLetter } from "@/lib/og";
import { ogForLetter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -13,14 +13,27 @@ import { cn } from "@/lib/utils";
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ slug: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const { slug } = await params;
const sp = await searchParams;
const letter = await getLetter(slug);
if (!letter) return {};
const meta = [letter.date, letter.location].filter(Boolean).join(" · ");
const hlQuote = extractQuoteFromHl(sp);
if (hlQuote) {
return buildOgMeta({
title: `Letter to ${letter.recipientDisplay}`,
detail: meta || undefined,
quote: hlQuote,
});
}
return ogForLetter(letter.recipientDisplay, meta || undefined);
}
+31
View File
@@ -1,5 +1,6 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -9,6 +10,7 @@ import {
slugToBookCode,
type MagazineSidebarItem,
} from "@/lib/magazines";
import { ogForMagazine, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -16,6 +18,35 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";
import { MobileNav, type MobileNavGroup } from "@/components/mobile-nav";
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ slug: string; issue: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const { slug, issue: issueSlug } = await params;
const sp = await searchParams;
const bookCode = slugToBookCode(slug);
const quote = extractQuoteFromHl(sp);
if (quote) {
const meta = await getMagazineMeta(bookCode);
const title = meta?.title ?? slug;
return buildOgMeta({ title, quote });
}
const [meta, content] = await Promise.all([
getMagazineMeta(bookCode),
getMagazineContent(bookCode, issueSlug),
]);
const magTitle = meta?.title ?? slug;
const issueTitle = content?.title ?? undefined;
return ogForMagazine(magTitle, issueTitle);
}
export default async function MagazineIssuePage({
params,
}: {
@@ -1,5 +1,6 @@
export const dynamic = "force-dynamic";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import {
@@ -9,6 +10,7 @@ import {
slugToBookCode,
type OtherDocumentSidebarItem,
} from "@/lib/other-documents";
import { ogForOtherDocument, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
import { PageHeader } from "@/components/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { buttonVariants } from "@/components/ui/button";
@@ -16,6 +18,38 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";
import { MobileNav, type MobileNavGroup } from "@/components/mobile-nav";
// ---------------------------------------------------------------------------
// Metadata
// ---------------------------------------------------------------------------
export async function generateMetadata({
params,
searchParams,
}: {
params: Promise<{ slug: string; chapter: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}): Promise<Metadata> {
const { slug, chapter: chapterSlug } = await params;
const sp = await searchParams;
const bookCode = slugToBookCode(slug);
const quote = extractQuoteFromHl(sp);
if (quote) {
const meta = await getOtherDocumentMeta(bookCode);
const content = await getOtherDocumentContent(bookCode, chapterSlug);
const title = meta?.title ?? slug;
const detail = content?.title ?? `Chapter ${chapterSlug}`;
return buildOgMeta({ title, detail, quote });
}
const [meta, content] = await Promise.all([
getOtherDocumentMeta(bookCode),
getOtherDocumentContent(bookCode, chapterSlug),
]);
return ogForOtherDocument(meta?.title ?? slug, content?.title ?? undefined);
}
// ---------------------------------------------------------------------------
// Page
// ---------------------------------------------------------------------------
+38
View File
@@ -6,6 +6,7 @@
*/
import { BOOK_NAMES, CC_LILAS } from "@/lib/constants";
import { decodeTextFragment } from "@/lib/text-highlight";
const SITE_URL =
process.env.NEXT_PUBLIC_SITE_URL || "https://prabhupadasays.org";
@@ -297,6 +298,43 @@ export function ogForLettersByLocation(location: string, count: number) {
});
}
// ---------------------------------------------------------------------------
// hl= query param → OG quote extraction
// ---------------------------------------------------------------------------
/**
* Extract a display quote from the `?hl=` search param.
*
* The `hl` param encodes `prefix,suffix,length`. We reconstruct a readable
* snippet from the prefix + suffix: "first few words ... last few words"
*
* Returns null if hl is missing or invalid.
*/
export function extractQuoteFromHl(
searchParams: Record<string, string | string[] | undefined> | URLSearchParams,
): string | null {
const raw =
searchParams instanceof URLSearchParams
? searchParams.get("hl")
: typeof searchParams.hl === "string"
? searchParams.hl
: null;
if (!raw) return null;
const fragment = decodeTextFragment(raw);
if (!fragment) return null;
const { prefix, suffix } = fragment;
if (!prefix) return null;
if (suffix && suffix !== prefix) {
return `${prefix} ... ${suffix}`;
}
return prefix;
}
/** Default OG metadata for the site. */
export function ogDefault() {
return buildOgMeta({