feat(seo): add sitemap generator
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
NEXT_PUBLIC_SITE_URL=https://prabhupadasays.org
|
||||||
|
|
||||||
# BFF API Server (server-side fetches)
|
# BFF API Server (server-side fetches)
|
||||||
BFF_URL=http://localhost:8080
|
BFF_URL=http://localhost:8080
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function BbdChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/bbd/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Beyond Birth and Death" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/bbd"
|
href="/books/bbd"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getBbdMeta, getBbdIntroSegments } from "@/lib/bbd";
|
import { getBbdMeta, getBbdIntroSegments } from "@/lib/bbd";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -20,6 +22,7 @@ export default async function BbdPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/bbd", name: "Beyond Birth and Death" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getBookMeta, getProseChapters } from "@/lib/api";
|
import { getBookMeta, getProseChapters } from "@/lib/api";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { ExtractedVerseCount } from "../extracted-verse-count";
|
import { ExtractedVerseCount } from "../extracted-verse-count";
|
||||||
|
|
||||||
@@ -34,6 +36,7 @@ export default async function BgPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/bg", name: "Bhagavad-gītā As It Is" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -63,6 +65,7 @@ export default async function BkChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/bk/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Bhagavāner Kathā" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/bk"
|
href="/books/bk"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getBkMeta } from "@/lib/bk";
|
import { getBkMeta } from "@/lib/bk";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -18,6 +20,7 @@ export default async function BkPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/bk", name: "Bhagavāner Kathā" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getBookMeta } from "@/lib/api";
|
import { getBookMeta } from "@/lib/api";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { ExtractedVerseCount } from "../extracted-verse-count";
|
import { ExtractedVerseCount } from "../extracted-verse-count";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
@@ -80,6 +82,7 @@ export default async function BsPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/bs", name: "Śrī Brahma-saṁhitā" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -63,6 +65,7 @@ export default async function CbhcChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/cbhc/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Śrī Caitanya-bhāgavata Commentary" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/cbhc"
|
href="/books/cbhc"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getCbhcMeta } from "@/lib/cbhc";
|
import { getCbhcMeta } from "@/lib/cbhc";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -18,6 +20,7 @@ export default async function CbhcPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/cbhc", name: "Śrī Caitanya-bhāgavata Commentary" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import Link from "next/link";
|
|||||||
import { getBookMeta, getProseChapters } from "@/lib/api";
|
import { getBookMeta, getProseChapters } from "@/lib/api";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { ExtractedVerseCount } from "../extracted-verse-count";
|
import { ExtractedVerseCount } from "../extracted-verse-count";
|
||||||
@@ -44,6 +46,7 @@ export default async function CcPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/cc", name: "Śrī Caitanya-caritāmṛta" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import { Badge } from "@/components/ui/badge";
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight, Loader2 } from "lucide-react";
|
import { ChevronLeft, ChevronRight, Loader2 } from "lucide-react";
|
||||||
import { MobileNav, type MobileNavGroup } from "@/components/layout/mobile-nav";
|
import { MobileNav, type MobileNavGroup } from "@/components/layout/mobile-nav";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Types
|
// Types
|
||||||
@@ -389,6 +392,19 @@ export function ChapterViewer({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{/* Structured data for the currently-shown verse (SSR'd for the initial
|
||||||
|
verse, updates on client navigation). */}
|
||||||
|
{currentVerse ? (
|
||||||
|
<JsonLd
|
||||||
|
data={articleJsonLd({
|
||||||
|
path: `${basePath}/${currentVerseNum}`,
|
||||||
|
headline: `${BOOK_NAMES[book] ?? book} ${currentVerse.reference}`,
|
||||||
|
description: currentVerse.translation,
|
||||||
|
isPartOf: BOOK_NAMES[book] ?? book,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
|
||||||
{/* ---- Sidebar: Verse Index ---- */}
|
{/* ---- Sidebar: Verse Index ---- */}
|
||||||
{/* Sticky sidebar. The max-h leaves 76px at the viewport bottom for
|
{/* Sticky sidebar. The max-h leaves 76px at the viewport bottom for
|
||||||
the site footer so the sidebar doesn't slide behind it when the
|
the site footer so the sidebar doesn't slide behind it when the
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -77,6 +79,7 @@ export default async function DsChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/ds/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Dialectic Spiritualism" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/ds"
|
href="/books/ds"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getDsMeta, getDsIntroSegments } from "@/lib/ds";
|
import { getDsMeta, getDsIntroSegments } from "@/lib/ds";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -20,6 +22,7 @@ export default async function DsPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/ds", name: "Dialectic Spiritualism" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function EjChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/ej/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Easy Journey to Other Planets" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/ej"
|
href="/books/ej"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getEjMeta, getEjIntroSegments } from "@/lib/ej";
|
import { getEjMeta, getEjIntroSegments } from "@/lib/ej";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -20,6 +22,7 @@ export default async function EjPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/ej", name: "Easy Journey to Other Planets" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function EkChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/ek/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Elevation to Kṛṣṇa Consciousness" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/ek"
|
href="/books/ek"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getEkMeta, getEkIntroSegments } from "@/lib/ek";
|
import { getEkMeta, getEkIntroSegments } from "@/lib/ek";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -20,6 +22,7 @@ export default async function EkPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/ek", name: "Elevation to Kṛṣṇa Consciousness" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -67,6 +69,7 @@ export default async function GgChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/gg/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Gītār Gān" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/gg"
|
href="/books/gg"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getGgMeta, getGgIntroSegments } from "@/lib/gg";
|
import { getGgMeta, getGgIntroSegments } from "@/lib/gg";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -24,6 +26,7 @@ export default async function GgPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/gg", name: "Gītār Gān" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function HkhChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/hkh/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "The Kṛṣṇa Consciousness Handbook" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/hkh"
|
href="/books/hkh"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getHkhMeta, getHkhIntroSegments } from "@/lib/hkh";
|
import { getHkhMeta, getHkhIntroSegments } from "@/lib/hkh";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -20,6 +22,7 @@ export default async function HkhPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/hkh", name: "The Kṛṣṇa Consciousness Handbook" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import {
|
|||||||
} from "@/lib/iso";
|
} from "@/lib/iso";
|
||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -103,6 +105,7 @@ export default async function IsoMantraPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/iso/${slug}`, headline: content.title ?? "Śrī Īśopaniṣad", isPartOf: "Śrī Īśopaniṣad" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/iso"
|
href="/books/iso"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getIsoMeta, getIsoIntroSegments } from "@/lib/iso";
|
import { getIsoMeta, getIsoIntroSegments } from "@/lib/iso";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -28,6 +30,7 @@ export default async function IsoPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/iso", name: "Śrī Īśopaniṣad" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import { getProseChapter, getProseChapters } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -66,6 +68,7 @@ export default async function KbChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/kb/${vol}/${slug}`, headline: chapter.title, description: chapter.paragraphs?.[0], isPartOf: "Kṛṣṇa, The Supreme Personality of Godhead" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href={`/books/kb/${vol}`}
|
href={`/books/kb/${vol}`}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getBookMeta } from "@/lib/api";
|
import { getBookMeta } from "@/lib/api";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
|
||||||
@@ -27,6 +29,7 @@ export default async function KbPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/kb", name: "Kṛṣṇa, The Supreme Personality of Godhead" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function LclChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/lcl/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Life Comes from Life" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/lcl"
|
href="/books/lcl"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getLclMeta, getLclIntroSegments } from "@/lib/lcl";
|
import { getLclMeta, getLclIntroSegments } from "@/lib/lcl";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -24,6 +26,7 @@ export default async function LclPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/lcl", name: "Life Comes from Life" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -67,6 +69,7 @@ export default async function LobChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/lob/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Light of the Bhāgavata" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/lob"
|
href="/books/lob"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getLobMeta, getLobIntroSegments } from "@/lib/lob";
|
import { getLobMeta, getLobIntroSegments } from "@/lib/lob";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -20,6 +22,7 @@ export default async function LobPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/lob", name: "Light of the Bhāgavata" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -67,6 +69,7 @@ export default async function MgChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/mg/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Kṛṣṇa Consciousness: The Matchless Gift" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/mg"
|
href="/books/mg"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getMgMeta, getMgIntroSegments } from "@/lib/mg";
|
import { getMgMeta, getMgIntroSegments } from "@/lib/mg";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -20,6 +22,7 @@ export default async function MgPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/mg", name: "Kṛṣṇa Consciousness: The Matchless Gift" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getBookMeta } from "@/lib/api";
|
import { getBookMeta } from "@/lib/api";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { ExtractedVerseCount } from "../extracted-verse-count";
|
import { ExtractedVerseCount } from "../extracted-verse-count";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
@@ -79,6 +81,7 @@ export default async function MmPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/mm", name: "Mukunda-mālā-stotra" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function MogChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/mog/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Message of Godhead" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/mog"
|
href="/books/mog"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getMogMeta, getMogIntroSegments } from "@/lib/mog";
|
import { getMogMeta, getMogIntroSegments } from "@/lib/mog";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -20,6 +22,7 @@ export default async function MogPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/mog", name: "Message of Godhead" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getBookMeta } from "@/lib/api";
|
import { getBookMeta } from "@/lib/api";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { ExtractedVerseCount } from "../extracted-verse-count";
|
import { ExtractedVerseCount } from "../extracted-verse-count";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
@@ -79,6 +81,7 @@ export default async function NbsPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/nbs", name: "Nārada-bhakti-sūtra" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function NodChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/nod/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "The Nectar of Devotion" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/nod"
|
href="/books/nod"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getNodMeta, getNodIntroSegments } from "@/lib/nod";
|
import { getNodMeta, getNodIntroSegments } from "@/lib/nod";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -27,6 +29,7 @@ export default async function NodPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/nod", name: "The Nectar of Devotion" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import {
|
|||||||
} from "@/lib/noi";
|
} from "@/lib/noi";
|
||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -94,6 +96,7 @@ export default async function NoiTextPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/noi/${slug}`, headline: content.title ?? "The Nectar of Instruction", isPartOf: "The Nectar of Instruction" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/noi"
|
href="/books/noi"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getNoiMeta, getNoiIntroSegments } from "@/lib/noi";
|
import { getNoiMeta, getNoiIntroSegments } from "@/lib/noi";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -24,6 +26,7 @@ export default async function NoiPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/noi", name: "The Nectar of Instruction" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function OchkmChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/ochkm/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "On Chanting Hare Kṛṣṇa" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/ochkm"
|
href="/books/ochkm"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getOchkmMeta, getOchkmIntroSegments } from "@/lib/ochkm";
|
import { getOchkmMeta, getOchkmIntroSegments } from "@/lib/ochkm";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -20,6 +22,7 @@ export default async function OchkmPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/ochkm", name: "On Chanting Hare Kṛṣṇa" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function OwkChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/owk/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "On the Way to Kṛṣṇa" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/owk"
|
href="/books/owk"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getOwkMeta, getOwkIntroSegments } from "@/lib/owk";
|
import { getOwkMeta, getOwkIntroSegments } from "@/lib/owk";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -20,6 +22,7 @@ export default async function OwkPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/owk", name: "On the Way to Kṛṣṇa" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -66,6 +68,7 @@ export default async function PkChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/pk/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Prabhupāda-Kṛpā" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/pk"
|
href="/books/pk"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getPkMeta } from "@/lib/pk";
|
import { getPkMeta } from "@/lib/pk";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -18,6 +20,7 @@ export default async function PkPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/pk", name: "Prabhupāda-Kṛpā" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function PoyChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/poy/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "The Perfection of Yoga" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/poy"
|
href="/books/poy"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getPoyMeta, getPoyIntroSegments } from "@/lib/poy";
|
import { getPoyMeta, getPoyIntroSegments } from "@/lib/poy";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -20,6 +22,7 @@ export default async function PoyPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/poy", name: "The Perfection of Yoga" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function PqpaChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/pqpa/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Perfect Questions, Perfect Answers" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/pqpa"
|
href="/books/pqpa"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getPqpaMeta, getPqpaIntroSegments } from "@/lib/pqpa";
|
import { getPqpaMeta, getPqpaIntroSegments } from "@/lib/pqpa";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -24,6 +26,7 @@ export default async function PqpaPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/pqpa", name: "Perfect Questions, Perfect Answers" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function RvChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/rv/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Rāja-vidyā: The King of Knowledge" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/rv"
|
href="/books/rv"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getRvMeta, getRvIntroSegments } from "@/lib/rv";
|
import { getRvMeta, getRvIntroSegments } from "@/lib/rv";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -20,6 +22,7 @@ export default async function RvPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/rv", name: "Rāja-vidyā: The King of Knowledge" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { ExtractedVerseCount } from "../extracted-verse-count";
|
import { ExtractedVerseCount } from "../extracted-verse-count";
|
||||||
@@ -42,6 +44,7 @@ export default async function SbPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/sb", name: "Śrīmad-Bhāgavatam" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getBookMeta } from "@/lib/api";
|
import { getBookMeta } from "@/lib/api";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { ExtractedVerseCount } from "../extracted-verse-count";
|
import { ExtractedVerseCount } from "../extracted-verse-count";
|
||||||
|
|
||||||
@@ -32,6 +34,7 @@ export default async function Sb1962Page() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/sb1962", name: "Śrīmad-Bhāgavatam (1962 Edition)" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -77,6 +79,7 @@ export default async function SsrChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/ssr/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "The Science of Self-Realization" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/ssr"
|
href="/books/ssr"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getSsrMeta, getSsrIntroSegments } from "@/lib/ssr";
|
import { getSsrMeta, getSsrIntroSegments } from "@/lib/ssr";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -24,6 +26,7 @@ export default async function SsrPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/ssr", name: "The Science of Self-Realization" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -78,6 +80,7 @@ export default async function SvaChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/sva/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Songs of the Vaiṣṇava Ācāryas" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/sva"
|
href="/books/sva"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getSvaMeta, getSvaIntroSegments } from "@/lib/sva";
|
import { getSvaMeta, getSvaIntroSegments } from "@/lib/sva";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -24,6 +26,7 @@ export default async function SvaPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/sva", name: "Songs of the Vaiṣṇava Ācāryas" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function TlcChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/tlc/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Teachings of Lord Caitanya" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/tlc"
|
href="/books/tlc"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getTlcMeta, getTlcIntroSegments } from "@/lib/tlc";
|
import { getTlcMeta, getTlcIntroSegments } from "@/lib/tlc";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -25,6 +27,7 @@ export default async function TlcPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/tlc", name: "Teachings of Lord Caitanya" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function TlkChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/tlk/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Teachings of Lord Kapila" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/tlk"
|
href="/books/tlk"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getTlkMeta, getTlkIntroSegments } from "@/lib/tlk";
|
import { getTlkMeta, getTlkIntroSegments } from "@/lib/tlk";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -24,6 +26,7 @@ export default async function TlkPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/tlk", name: "Teachings of Lord Kapila" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function TqkChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/tqk/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Teachings of Queen Kuntī" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/tqk"
|
href="/books/tqk"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getTqkMeta, getTqkIntroSegments } from "@/lib/tqk";
|
import { getTqkMeta, getTqkIntroSegments } from "@/lib/tqk";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -24,6 +26,7 @@ export default async function TqkPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/tqk", name: "Teachings of Queen Kuntī" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -71,6 +73,7 @@ export default async function TtpChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/ttp/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Teachings of Lord Kapila" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/ttp"
|
href="/books/ttp"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getTtpMeta } from "@/lib/ttp";
|
import { getTtpMeta } from "@/lib/ttp";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -18,6 +20,7 @@ export default async function TtpPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/ttp", name: "Teachings of Lord Kapila" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import { getProseChapter } from "@/lib/api";
|
|||||||
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForChapter, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { BOOK_NAMES } from "@/lib/constants";
|
import { BOOK_NAMES } from "@/lib/constants";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -63,6 +65,7 @@ export default async function VaChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/books/va/${slug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: "Vedānta-sūtra Transcript" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/books/va"
|
href="/books/va"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getVaMeta } from "@/lib/va";
|
import { getVaMeta } from "@/lib/va";
|
||||||
import { ogForBook } from "@/lib/og";
|
import { ogForBook } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { bookJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
export function generateMetadata(): Metadata {
|
export function generateMetadata(): Metadata {
|
||||||
@@ -18,6 +20,7 @@ export default async function VaPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={bookJsonLd({ path: "/books/va", name: "Vedānta-sūtra Transcript" })} />
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
<Link
|
<Link
|
||||||
href="/books"
|
href="/books"
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import Link from "next/link";
|
|||||||
import { notFound } from "next/navigation";
|
import { notFound } from "next/navigation";
|
||||||
import { ogForEssay, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForEssay, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -119,6 +121,7 @@ export default async function EssayPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/essays/${slug}`, headline: essay.title, description: essay.paragraphs?.[0], isPartOf: "Essays & Talks" })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href="/essays"
|
href="/essays"
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import { notFound } from "next/navigation";
|
|||||||
import { getAllGlossaryEntries } from "@/lib/api";
|
import { getAllGlossaryEntries } from "@/lib/api";
|
||||||
import { buildOgMeta, extractQuoteFromHl } from "@/lib/og";
|
import { buildOgMeta, extractQuoteFromHl } from "@/lib/og";
|
||||||
import { GlossaryClient } from "../glossary-client";
|
import { GlossaryClient } from "../glossary-client";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Diacritic → base letter mapping
|
// Diacritic → base letter mapping
|
||||||
@@ -145,6 +147,13 @@ export default async function GlossaryLetterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd
|
||||||
|
data={articleJsonLd({
|
||||||
|
path: `/glossary/${rawLetter}`,
|
||||||
|
headline: `Glossary — ${activeLetter}`,
|
||||||
|
isPartOf: "Glossary of Sanskrit & Vedic Terms",
|
||||||
|
})}
|
||||||
|
/>
|
||||||
<GlossaryClient
|
<GlossaryClient
|
||||||
entries={clientEntries}
|
entries={clientEntries}
|
||||||
activeLetter={activeLetter}
|
activeLetter={activeLetter}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import {
|
|||||||
} from "@/lib/journals";
|
} from "@/lib/journals";
|
||||||
import { ogForJournal, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForJournal, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -74,6 +76,7 @@ export default async function JournalChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/journals/${slug}/${chapterSlug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: meta.title })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href={`/journals/${slug}`}
|
href={`/journals/${slug}`}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import { Card, CardContent } from "@/components/ui/card";
|
|||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
|
|
||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
params,
|
params,
|
||||||
@@ -54,6 +56,15 @@ export default async function LetterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd
|
||||||
|
data={articleJsonLd({
|
||||||
|
path: `/letters/${slug}`,
|
||||||
|
headline: `Letter to ${letter.recipientDisplay}`,
|
||||||
|
description: letter.paragraphs[0],
|
||||||
|
datePublished: letter.year ? String(letter.year) : undefined,
|
||||||
|
isPartOf: "Letters of Śrīla Prabhupāda",
|
||||||
|
})}
|
||||||
|
/>
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href={backHref}
|
href={backHref}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import {
|
|||||||
} from "@/lib/magazines";
|
} from "@/lib/magazines";
|
||||||
import { ogForMagazine, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForMagazine, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -72,6 +74,7 @@ export default async function MagazineIssuePage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/magazines/${slug}/${issueSlug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: meta.title })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href={`/magazines/${slug}`}
|
href={`/magazines/${slug}`}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import {
|
|||||||
} from "@/lib/other-documents";
|
} from "@/lib/other-documents";
|
||||||
import { ogForOtherDocument, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
import { ogForOtherDocument, extractQuoteFromHl, buildOgMeta } from "@/lib/og";
|
||||||
import { PageHeader } from "@/components/layout/page-header";
|
import { PageHeader } from "@/components/layout/page-header";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
@@ -79,6 +81,7 @@ export default async function OtherDocumentChapterPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd data={articleJsonLd({ path: `/other-documents/${slug}/${chapterSlug}`, headline: content.title, description: content.paragraphs?.[0], isPartOf: meta.title })} />
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href={`/other-documents/${slug}`}
|
href={`/other-documents/${slug}`}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import { cn } from "@/lib/utils";
|
|||||||
import { ChevronLeft, ChevronRight, Clock, MapPin, Users } from "lucide-react";
|
import { ChevronLeft, ChevronRight, Clock, MapPin, Users } from "lucide-react";
|
||||||
import { PlayAudioButton } from "./play-audio-button";
|
import { PlayAudioButton } from "./play-audio-button";
|
||||||
import { FindInPage } from "@/components/layout/find-in-page";
|
import { FindInPage } from "@/components/layout/find-in-page";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { articleJsonLd } from "@/lib/jsonld";
|
||||||
|
|
||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
params,
|
params,
|
||||||
@@ -82,6 +84,15 @@ export default async function TranscriptionPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
|
<JsonLd
|
||||||
|
data={articleJsonLd({
|
||||||
|
path: `/transcriptions/${slug}`,
|
||||||
|
headline: t.name,
|
||||||
|
description: t.content[0]?.text,
|
||||||
|
datePublished: t.year ? String(t.year) : undefined,
|
||||||
|
isPartOf: "Lectures & Conversations of Śrīla Prabhupāda",
|
||||||
|
})}
|
||||||
|
/>
|
||||||
<PageHeader sticky>
|
<PageHeader sticky>
|
||||||
<Link
|
<Link
|
||||||
href={backHref}
|
href={backHref}
|
||||||
|
|||||||
@@ -1,18 +1,23 @@
|
|||||||
/**
|
/**
|
||||||
* /u/[handle] — public profile, Posts tab (default).
|
* /u/[handle] — public profile, Posts tab (default).
|
||||||
*
|
*
|
||||||
* Server shell that exists for two reasons:
|
* Server shell that exists for three reasons:
|
||||||
*
|
*
|
||||||
* 1. Export `generateMetadata` so direct shares of this URL
|
* 1. Export `generateMetadata` so direct shares of this URL
|
||||||
* (https://prabhupadasays.org/u/<handle>) get a rich OG card
|
* (https://prabhupadasays.org/u/<handle>) get a rich OG card
|
||||||
* pointing at /api/og/profile/<handle>. The layout and the body
|
* pointing at /api/og/profile/<handle>. The layout and the body
|
||||||
* below are client components; only this file is server.
|
* below are client components; only this file is server.
|
||||||
* 2. Mount the client tree (<PostsGrid />), which reads the
|
* 2. Emit server-rendered ProfilePage/Person JSON-LD so crawlers + LLMs
|
||||||
* ProfileContext provided by the parent layout for the post-grid
|
* can resolve the profile (the layout is a client component and
|
||||||
* hrefs and renders the feed.
|
* fetches the profile after hydration, too late for crawlers).
|
||||||
|
* 3. Mount the client tree (<PostsGrid />), which reads the
|
||||||
|
* ProfileContext provided by the parent layout.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
|
import { bff } from "@/lib/bff";
|
||||||
|
import { JsonLd } from "@/components/seo/json-ld";
|
||||||
|
import { profileJsonLd } from "@/lib/jsonld";
|
||||||
import { PostsGrid } from "./posts-grid";
|
import { PostsGrid } from "./posts-grid";
|
||||||
import { metadataForHandle } from "./profile-og";
|
import { metadataForHandle } from "./profile-og";
|
||||||
|
|
||||||
@@ -23,6 +28,32 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
|||||||
return metadataForHandle(handle);
|
return metadataForHandle(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function PublicProfilePage({ params }: Props) {
|
export default async function PublicProfilePage({ params }: Props) {
|
||||||
return <PostsGrid params={params} />;
|
const { handle } = await params;
|
||||||
|
|
||||||
|
let person: object | null = null;
|
||||||
|
try {
|
||||||
|
const profile = await bff<{
|
||||||
|
handle: string;
|
||||||
|
name: string;
|
||||||
|
avatar_url?: string | null;
|
||||||
|
}>(`/u/${encodeURIComponent(handle)}`, { revalidate: 60 });
|
||||||
|
if (profile) {
|
||||||
|
person = profileJsonLd({
|
||||||
|
path: `/u/${profile.handle}`,
|
||||||
|
name: profile.name,
|
||||||
|
handle: profile.handle,
|
||||||
|
image: profile.avatar_url ?? null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Profile unavailable — skip JSON-LD rather than fail the page.
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{person ? <JsonLd data={person} /> : null}
|
||||||
|
<PostsGrid params={params} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { revalidateTag } from "next/cache";
|
||||||
|
import type { NextRequest } from "next/server";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On-demand cache revalidation. The BFF pings this (fire-and-forget) when
|
||||||
|
* sitemap-relevant data changes — a new signup, or a content re-seed/reindex —
|
||||||
|
* so /sitemap.xml refreshes within seconds instead of waiting out the 24h ISR
|
||||||
|
* window. Secret-gated; lives under /api/ which robots.txt disallows.
|
||||||
|
*
|
||||||
|
* POST /api/revalidate?tag=sitemap&secret=…
|
||||||
|
*/
|
||||||
|
export const runtime = "nodejs";
|
||||||
|
|
||||||
|
export async function POST(req: NextRequest) {
|
||||||
|
const expected = process.env.REVALIDATE_SECRET;
|
||||||
|
const secret = req.nextUrl.searchParams.get("secret");
|
||||||
|
if (!expected || secret !== expected) {
|
||||||
|
return Response.json(
|
||||||
|
{ revalidated: false, error: "unauthorized" },
|
||||||
|
{ status: 401 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const tag = req.nextUrl.searchParams.get("tag") || "sitemap";
|
||||||
|
// Next 16 requires a cache-life profile as the 2nd arg; "max" fully purges
|
||||||
|
// the tagged entries so the next request re-fetches from the BFF.
|
||||||
|
revalidateTag(tag, "max");
|
||||||
|
return Response.json({ revalidated: true, tag });
|
||||||
|
}
|
||||||
@@ -43,6 +43,12 @@ const bricolage = Bricolage_Grotesque({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
|
// Resolves all relative OG/Twitter image URLs and canonical links to
|
||||||
|
// absolute URLs (required for correct social previews + SEO; Next warns
|
||||||
|
// without it).
|
||||||
|
metadataBase: new URL(
|
||||||
|
process.env.NEXT_PUBLIC_SITE_URL || "https://prabhupadasays.org",
|
||||||
|
),
|
||||||
title: "Prabhupāda Says",
|
title: "Prabhupāda Says",
|
||||||
description:
|
description:
|
||||||
"Browse the books and teachings of His Divine Grace A.C. Bhaktivedanta Swami Prabhupāda",
|
"Browse the books and teachings of His Divine Grace A.C. Bhaktivedanta Swami Prabhupāda",
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import type { MetadataRoute } from "next";
|
||||||
|
|
||||||
|
const SITE_URL =
|
||||||
|
process.env.NEXT_PUBLIC_SITE_URL || "https://prabhupadasays.org";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* robots.txt (generated).
|
||||||
|
*
|
||||||
|
* Open the whole site to crawlers — search engines AND AI/LLM crawlers
|
||||||
|
* (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, etc. all honour the
|
||||||
|
* `*` rule, and we deliberately don't block them so the corpus is
|
||||||
|
* discoverable). Only private / non-content surfaces are disallowed:
|
||||||
|
*
|
||||||
|
* • /api/ — JSON endpoints, never a destination page
|
||||||
|
* • /settings — auth-only account settings
|
||||||
|
* • /notifications — auth-only
|
||||||
|
* • /verify-email — transactional
|
||||||
|
* • /chat — interactive tool, not indexable content
|
||||||
|
* • /u/me, /u/me/* — the signed-in user's own private library
|
||||||
|
* ($ anchors the bare path so public handles like
|
||||||
|
* /u/meera aren't caught by the prefix)
|
||||||
|
*
|
||||||
|
* Public content (books, verses, prose, letters, transcriptions, essays,
|
||||||
|
* disciples, magazines, journals, glossary, public profiles, collections)
|
||||||
|
* stays crawlable and is enumerated in the sitemap index.
|
||||||
|
*/
|
||||||
|
export default function robots(): MetadataRoute.Robots {
|
||||||
|
return {
|
||||||
|
rules: {
|
||||||
|
userAgent: "*",
|
||||||
|
allow: "/",
|
||||||
|
disallow: [
|
||||||
|
"/api/",
|
||||||
|
"/settings",
|
||||||
|
"/notifications",
|
||||||
|
"/verify-email",
|
||||||
|
"/chat",
|
||||||
|
"/u/me$",
|
||||||
|
"/u/me/",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
sitemap: `${SITE_URL}/sitemap.xml`,
|
||||||
|
host: SITE_URL,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
import type { MetadataRoute } from "next";
|
||||||
|
import { bff } from "@/lib/bff";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sitemap (index + sharded children) for the whole public corpus.
|
||||||
|
*
|
||||||
|
* How this stays cheap on the BFF:
|
||||||
|
* • One projection-only BFF call (`/sitemap/content`) returns every content
|
||||||
|
* leaf path in a single sweep — no per-document fan-out.
|
||||||
|
* • That fetch is cached for 24h (revalidate below) AND the rendered XML is
|
||||||
|
* ISR-cached, so crawlers hit Next's cache, not the BFF. The BFF sees
|
||||||
|
* ~one query/day regardless of crawl volume (tag "sitemap" allows
|
||||||
|
* on-demand revalidation after a re-seed).
|
||||||
|
* • generateSitemaps() shards into ≤40k-URL files (under the 50k/50MB
|
||||||
|
* limits) and Next serves a sitemap index at /sitemap.xml automatically.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const revalidate = 86400; // 24h
|
||||||
|
|
||||||
|
const SITE_URL =
|
||||||
|
process.env.NEXT_PUBLIC_SITE_URL || "https://prabhupadasays.org";
|
||||||
|
const PER_SITEMAP = 40000;
|
||||||
|
|
||||||
|
// Top-level hubs that aren't content leaves but should be indexed.
|
||||||
|
const STATIC_PATHS = [
|
||||||
|
"/",
|
||||||
|
"/about",
|
||||||
|
"/books",
|
||||||
|
"/letters",
|
||||||
|
"/transcriptions",
|
||||||
|
"/disciples",
|
||||||
|
"/glossary",
|
||||||
|
"/essays",
|
||||||
|
"/magazines",
|
||||||
|
"/journals",
|
||||||
|
"/other-documents",
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All indexable paths: static hubs + book/division landing pages (derived
|
||||||
|
* from the content leaves) + every content leaf from the BFF. Resilient — if
|
||||||
|
* the BFF call fails we still emit the static hubs so /sitemap.xml never 500s.
|
||||||
|
*/
|
||||||
|
async function fetchUrls(path: string): Promise<string[]> {
|
||||||
|
try {
|
||||||
|
const res = await bff<{ urls: string[] }>(path, {
|
||||||
|
revalidate,
|
||||||
|
tags: ["sitemap"],
|
||||||
|
});
|
||||||
|
return res?.urls ?? [];
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function allPaths(): Promise<string[]> {
|
||||||
|
// Content (Mongo) and public profiles (Postgres) come from separate
|
||||||
|
// projection-only endpoints. New signups appear automatically on the next
|
||||||
|
// daily revalidation.
|
||||||
|
const [content, users] = await Promise.all([
|
||||||
|
fetchUrls("/sitemap/content"),
|
||||||
|
fetchUrls("/sitemap/users"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Derive non-redirecting hub pages from the content leaves: every book's
|
||||||
|
// landing page, and the SB canto / CC līlā division pages.
|
||||||
|
const hubs = new Set<string>();
|
||||||
|
for (const p of content) {
|
||||||
|
const book = p.match(/^\/books\/([^/]+)/);
|
||||||
|
if (book) hubs.add(`/books/${book[1]}`);
|
||||||
|
const division = p.match(/^\/books\/(sb|cc)\/([^/]+)\/\d+\/\d+$/);
|
||||||
|
if (division) hubs.add(`/books/${division[1]}/${division[2]}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dedupe across static + hubs + content + profiles.
|
||||||
|
return [...new Set([...STATIC_PATHS, ...hubs, ...content, ...users])];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function generateSitemaps(): Promise<{ id: number }[]> {
|
||||||
|
const paths = await allPaths();
|
||||||
|
const count = Math.max(1, Math.ceil(paths.length / PER_SITEMAP));
|
||||||
|
return Array.from({ length: count }, (_, id) => ({ id }));
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function sitemap({
|
||||||
|
id,
|
||||||
|
}: {
|
||||||
|
id: number;
|
||||||
|
}): Promise<MetadataRoute.Sitemap> {
|
||||||
|
const paths = await allPaths();
|
||||||
|
const slice = paths.slice(id * PER_SITEMAP, (id + 1) * PER_SITEMAP);
|
||||||
|
return slice.map((path) => ({
|
||||||
|
url: `${SITE_URL}${path}`,
|
||||||
|
changeFrequency: "weekly",
|
||||||
|
priority: path === "/" ? 1 : STATIC_PATHS.includes(path) ? 0.8 : 0.7,
|
||||||
|
}));
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Renders a schema.org JSON-LD <script>. Safe in server or client components.
|
||||||
|
* The `<` escape prevents the JSON from breaking out of the <script> element.
|
||||||
|
*/
|
||||||
|
export function JsonLd({ data }: { data: object | object[] }) {
|
||||||
|
return (
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: JSON.stringify(data).replace(/</g, "\\u003c"),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
+121
@@ -0,0 +1,121 @@
|
|||||||
|
/**
|
||||||
|
* schema.org JSON-LD builders for content pages.
|
||||||
|
*
|
||||||
|
* Emitting structured data gives Google rich-result eligibility and gives
|
||||||
|
* LLMs clean, linked facts (who authored it, which work it belongs to, when).
|
||||||
|
* Every page renders one of these via the <JsonLd> component
|
||||||
|
* (components/seo/json-ld.tsx).
|
||||||
|
*
|
||||||
|
* The author entity carries `sameAs` links to Wikipedia/Wikidata so search
|
||||||
|
* engines and LLMs can resolve it to the canonical Śrīla Prabhupāda entity.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const SITE_URL =
|
||||||
|
process.env.NEXT_PUBLIC_SITE_URL || "https://prabhupadasays.org";
|
||||||
|
|
||||||
|
const AUTHOR = {
|
||||||
|
"@type": "Person",
|
||||||
|
name: "His Divine Grace A.C. Bhaktivedanta Swami Prabhupāda",
|
||||||
|
alternateName: "A.C. Bhaktivedanta Swami Prabhupāda",
|
||||||
|
sameAs: [
|
||||||
|
"https://en.wikipedia.org/wiki/A._C._Bhaktivedanta_Swami_Prabhupada",
|
||||||
|
"https://www.wikidata.org/wiki/Q318439",
|
||||||
|
],
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
const PUBLISHER = {
|
||||||
|
"@type": "Organization",
|
||||||
|
name: "Prabhupāda Says",
|
||||||
|
url: SITE_URL,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
function abs(path: string): string {
|
||||||
|
return path.startsWith("http") ? path : `${SITE_URL}${path}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Trim a (possibly HTML) string to a clean plain-text description. */
|
||||||
|
function clean(text: string | undefined, max = 300): string | undefined {
|
||||||
|
if (!text) return undefined;
|
||||||
|
const plain = text
|
||||||
|
.replace(/<[^>]+>/g, "")
|
||||||
|
.replace(/\s+/g, " ")
|
||||||
|
.trim();
|
||||||
|
if (!plain) return undefined;
|
||||||
|
return plain.length > max ? plain.slice(0, max - 1).trimEnd() + "…" : plain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Article — used for every leaf content page (verses, letters, transcripts,
|
||||||
|
* prose chapters, essays, magazine/journal pages). `isPartOf` names the parent
|
||||||
|
* work (book/magazine); `datePublished` must be ISO 8601 (omit otherwise).
|
||||||
|
*/
|
||||||
|
export function articleJsonLd(params: {
|
||||||
|
path: string;
|
||||||
|
headline: string;
|
||||||
|
description?: string;
|
||||||
|
datePublished?: string;
|
||||||
|
isPartOf?: string;
|
||||||
|
}) {
|
||||||
|
const url = abs(params.path);
|
||||||
|
const obj: Record<string, unknown> = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Article",
|
||||||
|
headline: params.headline,
|
||||||
|
author: AUTHOR,
|
||||||
|
publisher: PUBLISHER,
|
||||||
|
inLanguage: "en",
|
||||||
|
isAccessibleForFree: true,
|
||||||
|
url,
|
||||||
|
mainEntityOfPage: url,
|
||||||
|
};
|
||||||
|
const desc = clean(params.description);
|
||||||
|
if (desc) obj.description = desc;
|
||||||
|
if (params.datePublished) obj.datePublished = params.datePublished;
|
||||||
|
if (params.isPartOf) {
|
||||||
|
obj.isPartOf = { "@type": "Book", name: params.isPartOf, author: AUTHOR };
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A public profile page → ProfilePage wrapping the Person. */
|
||||||
|
export function profileJsonLd(params: {
|
||||||
|
path: string;
|
||||||
|
name: string;
|
||||||
|
handle: string;
|
||||||
|
image?: string | null;
|
||||||
|
}) {
|
||||||
|
const url = abs(params.path);
|
||||||
|
const person: Record<string, unknown> = {
|
||||||
|
"@type": "Person",
|
||||||
|
name: params.name,
|
||||||
|
alternateName: `@${params.handle}`,
|
||||||
|
url,
|
||||||
|
};
|
||||||
|
if (params.image) person.image = params.image;
|
||||||
|
return {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "ProfilePage",
|
||||||
|
url,
|
||||||
|
mainEntity: person,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A Book — used for book landing pages. */
|
||||||
|
export function bookJsonLd(params: {
|
||||||
|
path: string;
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
}) {
|
||||||
|
const obj: Record<string, unknown> = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Book",
|
||||||
|
name: params.name,
|
||||||
|
author: AUTHOR,
|
||||||
|
publisher: PUBLISHER,
|
||||||
|
inLanguage: "en",
|
||||||
|
url: abs(params.path),
|
||||||
|
};
|
||||||
|
const desc = clean(params.description);
|
||||||
|
if (desc) obj.description = desc;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Prabhupāda Says
|
||||||
|
|
||||||
|
> The complete teachings of His Divine Grace A.C. Bhaktivedanta Swami Prabhupāda — the books, lectures, conversations, and letters of the Founder-Ācārya of the International Society for Krishna Consciousness (ISKCON) — as structured, searchable, Unicode text (Devanāgarī + IAST transliteration).
|
||||||
|
|
||||||
|
All content is server-rendered and crawlable. The full URL list (tens of thousands of pages) is in the sitemap index.
|
||||||
|
|
||||||
|
## Sitemap
|
||||||
|
|
||||||
|
- [Sitemap index](https://prabhupadasays.org/sitemap.xml): every book, chapter, verse, prose chapter, letter, transcript, essay, magazine, and journal page
|
||||||
|
|
||||||
|
## Scriptures (books)
|
||||||
|
|
||||||
|
- [All books](https://prabhupadasays.org/books): Bhagavad-gītā As It Is, Śrīmad-Bhāgavatam, Śrī Caitanya-caritāmṛta, Nectar of Devotion, Kṛṣṇa Book, and 30+ more — browsable by chapter and verse (Devanāgarī, transliteration, synonyms, translation, and purport)
|
||||||
|
|
||||||
|
## Lectures & conversations
|
||||||
|
|
||||||
|
- [Transcriptions](https://prabhupadasays.org/transcriptions): ~3,800 lectures, morning walks, room conversations, and interviews (1966–1977), browsable by year, place, and type
|
||||||
|
|
||||||
|
## Letters
|
||||||
|
|
||||||
|
- [Letters](https://prabhupadasays.org/letters): ~6,900 letters (1947–1977), browsable by year, recipient, and location
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
- [Glossary](https://prabhupadasays.org/glossary): ~2,750 Sanskrit/Vedic terms
|
||||||
|
- [Essays & other documents](https://prabhupadasays.org/essays)
|
||||||
|
- [Magazines (Back to Godhead)](https://prabhupadasays.org/magazines)
|
||||||
|
- [Journals](https://prabhupadasays.org/journals)
|
||||||
|
- [Disciples](https://prabhupadasays.org/disciples)
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
User-agent: *
|
|
||||||
Disallow: /
|
|
||||||
Reference in New Issue
Block a user