import { IconCalendarEvent, IconEdit, IconEye, IconMessages, IconTag } from "@tabler/icons-react"; import type { Metadata } from "next"; import Link from "next/link"; import { notFound } from "next/navigation"; import { Suspense, ViewTransition } from "react"; import { JsonLd } from "react-schemaorg"; import type { BlogPosting } from "schema-dts"; import { CommentCount } from "@/components/comment-count"; import { Comments } from "@/components/comments/comments"; import { CommentsSkeleton } from "@/components/comments/comments-skeleton"; import { DirectionalTransition } from "@/components/page-transition"; import { ViewCounter } from "@/components/view-counter"; import authorConfig from "@/lib/config/author"; import siteConfig from "@/lib/config/site"; import { createMetadata } from "@/lib/metadata"; import { getFrontMatter, getSlugs, POSTS_DIR } from "@/lib/posts"; import { size as ogImageSize } from "./opengraph-image"; export const generateStaticParams = async () => { const slugs = await getSlugs(); // map slugs into a static paths object required by next.js return slugs.map((slug) => ({ slug, })); }; export const generateMetadata = async ({ params, }: { params: Promise<{ slug: string }>; }): Promise => { const { slug } = await params; const frontmatter = await getFrontMatter(slug); return createMetadata({ title: frontmatter?.title, description: frontmatter?.description, canonical: `/${POSTS_DIR}/${slug}`, openGraph: { type: "article", authors: [authorConfig.name], tags: frontmatter?.tags, publishedTime: frontmatter?.date, modifiedTime: frontmatter?.date, }, twitter: { card: "summary_large_image", }, }); }; const Page = async ({ params }: { params: Promise<{ slug: string }> }) => { const { slug } = await params; const frontmatter = await getFrontMatter(slug); if (!frontmatter) notFound(); const d = new Date(frontmatter.date); const formattedDates = { dateISO: d.toISOString(), dateTitle: d.toLocaleString("en-US", { month: "short", day: "numeric", year: "numeric", hour: "numeric", minute: "2-digit", timeZoneName: "short", }), dateDisplay: d.toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric", }), }; const { default: MDXContent } = await import(`../../../${POSTS_DIR}/${slug}/index.mdx`); return ( item={{ "@context": "https://schema.org", "@type": "BlogPosting", headline: frontmatter?.title, description: frontmatter?.description, url: frontmatter?.permalink, image: { "@type": "ImageObject", contentUrl: `${process.env.NEXT_PUBLIC_BASE_URL}/${POSTS_DIR}/${frontmatter?.slug}/opengraph-image`, width: `${ogImageSize.width}`, height: `${ogImageSize.height}`, }, keywords: frontmatter?.tags?.join(", "), datePublished: frontmatter?.date, dateModified: frontmatter?.date, inLanguage: process.env.NEXT_PUBLIC_SITE_LOCALE, license: `https://spdx.org/licenses/${siteConfig.license}.html`, author: { // defined in app/layout.tsx "@id": `${process.env.NEXT_PUBLIC_BASE_URL}/#person`, }, }} />

{frontmatter?.noComments ? (

Comments are closed.

) : ( } > )}
); }; export default Page;