import type { Metadata } from "next"; import { notFound } from "next/navigation"; import { getPostBySlug, getPublishedPosts } from "@/lib/store"; import PostContent from "@/components/PostContent"; const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || "https://asui.xyz"; export async function generateStaticParams() { const posts = await getPublishedPosts(); return posts.map((post) => ({ slug: post.slug })); } export async function generateMetadata({ params, }: { params: Promise<{ slug: string }>; }): Promise { const { slug } = await params; const post = await getPostBySlug(slug); if (!post) return {}; const url = `${SITE_URL}/posts/${post.slug}`; return { title: post.title, description: post.excerpt, alternates: { canonical: url }, openGraph: { title: post.title, description: post.excerpt, url, type: "article", publishedTime: post.date, authors: ["胡旭"], tags: post.tags, siteName: "随 · asui.xyz", locale: "zh_CN", }, twitter: { card: "summary_large_image", title: post.title, description: post.excerpt, }, }; } export default async function PostPage({ params }: { params: Promise<{ slug: string }> }) { const { slug } = await params; const post = await getPostBySlug(slug); if (!post) notFound(); const all = await getPublishedPosts(); const currentIndex = all.findIndex((p) => p.slug === slug); const prevPost = currentIndex > 0 ? all[currentIndex - 1] : null; const nextPost = currentIndex < all.length - 1 ? all[currentIndex + 1] : null; // BlogPosting 结构化数据,利于搜索引擎富摘要 const jsonLd = { "@context": "https://schema.org", "@type": "BlogPosting", headline: post.title, description: post.excerpt, datePublished: post.date, dateModified: post.updatedAt, author: { "@type": "Person", name: "胡旭", url: SITE_URL }, publisher: { "@type": "Person", name: "胡旭" }, mainEntityOfPage: `${SITE_URL}/posts/${post.slug}`, keywords: post.tags.join(", "), }; return ( <>