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 "prismjs/components/prism-bash"; import "prismjs/components/prism-sql"; import "prismjs/components/prism-yaml"; import "prismjs/components/prism-markdown"; import "prismjs/components/prism-json"; import "prismjs/components/prism-perl"; 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, smallDescription, titleImage, _createdAt }[0]`; const data = await client.fetch(query, {}, { cache: "no-store" }); return data; } interface BlogSlugArticle { currentSlug: string; title: string; content: any; titleImage: string; _createdAt: string; } export const dynamic = "force-static"; export async function generateMetadata(props: { params: Promise<{ slug: string }>; }): Promise { const params = await props.params; const data = await getData(params.slug); if (!data) { return { title: "404 Not Found - SVR.JS", openGraph: { title: "404 Not Found - SVR.JS" }, twitter: { title: "404 Not Found - SVR.JS" } }; } return { title: `${data.title} - SVR.JS`, description: data.smallDescription, openGraph: { title: `${data.title} - SVR.JS`, description: data.smallDescription, url: `${process.env.NEXT_PUBLIC_WEBSITE_URL}/blog/${data.currentSlug}`, type: "website", images: [ { url: data.titleImage ? urlFor(data.titleImage).url() : `${process.env.NEXT_PUBLIC_WEBSITE_URL}/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() : `${process.env.NEXT_PUBLIC_WEBSITE_URL}/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 || "none"; const grammar = Prism.languages[language]; if (language != "none" && !grammar) { console.error(`No grammar found for language: "${language}"`); } return (
            {value.code}
          
{language == "none" ? "" : }
); } } }; export default async function BlogSlugArticle(props: { params: Promise<{ slug: string }>; }) { const params = await props.params; 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}

Published on: {formattedDate}

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