import { client, urlFor } from "@/lib/sanity"; import { PortableText, PortableTextComponents } from "@portabletext/react"; import Image from "next/image"; import Link from "next/link"; import { ArrowLeft, Rss } from "lucide-react"; import { Separator } from "@/components/ui/separator"; import { notFound } from "next/navigation"; import { Metadata } from "next"; import { format } from "date-fns"; import Prism from "prismjs"; import "prismjs/components/prism-javascript"; import "prismjs/components/prism-python"; import "prismjs/components/prism-php"; import CopyButton from "@/components/shared/copyButton"; import "./_styles/prism-twilight.css"; import "./_styles/prism.twilight.min.css"; import PrismLoader from "@/components/loader/prismLoader"; import { Button } from "@/components/ui/button"; async function getData(slug: string) { const query = ` *[_type == "blog" && slug.current == '${slug}'] { "currentSlug": slug.current, title, content, titleImage, _createdAt }[0]`; const data = await client.fetch(query); return data; } interface BlogSlugArticle { currentSlug: string; title: string; content: any; titleImage: string; _createdAt: string; } export async function generateMetadata({ params }: { params: { slug: string }; }): Promise { const data = await getData(params.slug); if (!data) { return { title: "Not Found", description: "Blog post not found" }; } return { title: `${data.title} - SVR.JS`, description: data.smallDescription, openGraph: { title: `${data.title} - SVR.JS`, description: data.smallDescription, url: `https://svrjs.org/blog/${data.currentSlug}`, type: "website", images: [ { url: data.titleImage ? urlFor(data.titleImage).url() : "https://svrjs.vercel.app/blog-missing.png", width: 800, height: 600, alt: `${data.title} - SVR.JS` } ] }, twitter: { card: "summary_large_image", site: "@SVR_JS", title: `${data.title} - SVR.JS`, description: data.smallDescription, images: [ data.titleImage ? urlFor(data.titleImage).url() : "https://svrjs.vercel.app/blog-missing.png" ], creator: "@SVR_JS" } }; } const customPortableTextComponents: PortableTextComponents = { types: { image: ({ value }) => { return (
{value.alt {value.caption && (

{value.caption}

)}
); }, code: ({ value }) => { const language = value.language || "javascript"; const grammar = Prism.languages[language]; if (!grammar) { console.error(`No grammar found for language: "${language}"`); return (
            {value.code}
          
); } return (
            {value.code}
          
); } } }; export default async function BlogSlugArticle({ params }: { params: { slug: string }; }) { const data: BlogSlugArticle = await getData(params.slug); if (!data) { notFound(); } const formattedDate = format(new Date(data._createdAt), "MMMM d, yyyy"); return ( <>

{data.title}

{data.title}

Uploaded at {formattedDate}

); } export async function generateStaticParams() { const query = `*[_type == 'blog']{ "slug": slug.current, }`; const slugsRaw = await client.fetch(query); return slugsRaw; }