47 lines
1.5 KiB
TypeScript
47 lines
1.5 KiB
TypeScript
import { notFound } from 'next/navigation';
|
|
import { loadContent } from '@/lib/content/load';
|
|
import { loadPost } from '@/lib/content/posts-store';
|
|
import { BlogArticle } from '@/components/blog/BlogArticle';
|
|
|
|
// Live content: bodies and card meta both come from the CMS-merged tree, so
|
|
// admin edits show immediately. (No generateStaticParams — render on demand.)
|
|
export const dynamic = 'force-dynamic';
|
|
|
|
type Params = { slug: string };
|
|
|
|
export function generateMetadata({ params }: { params: Params }) {
|
|
const { en } = loadContent();
|
|
const post = en.blog.items.find((p) => p.slug === params.slug);
|
|
if (!post) return {};
|
|
return {
|
|
title: post.title,
|
|
description: post.excerpt,
|
|
openGraph: { title: post.title, description: post.excerpt, type: 'article' },
|
|
alternates: {
|
|
canonical: `/blog/${post.slug}`,
|
|
languages: {
|
|
'fa-IR': `/blog/${post.slug}`,
|
|
'en-US': `/blog/${post.slug}`,
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
export default function BlogPostPage({ params }: { params: Params }) {
|
|
const content = loadPost(params.slug);
|
|
const { en: enContent, fa: faContent } = loadContent();
|
|
const en = enContent.blog.items.find((p) => p.slug === params.slug);
|
|
const fa = faContent.blog.items.find((p) => p.slug === params.slug);
|
|
if (!content || !en || !fa) notFound();
|
|
|
|
return (
|
|
<BlogArticle
|
|
content={content}
|
|
meta={{
|
|
en: { title: en.title, category: en.category, readTime: en.readTime },
|
|
fa: { title: fa.title, category: fa.category, readTime: fa.readTime },
|
|
}}
|
|
/>
|
|
);
|
|
}
|