import type { Metadata } from "next"; import { notFound } from "next/navigation"; import { MDXRemote } from "next-mdx-remote/rsc"; import { getArticleBySlug, getAllArticles, getAlternatesArticle } from "@/lib/blog/get-articles"; import { ArticleHero } from "@/components/sections/ArticleHero"; import { ArticleSummary } from "@/components/sections/ArticleSummary"; import { locales } from "@/middleware"; import Link from "next/link"; type props = { params: Promise<{ locale: string; slug: string; }>; }; const siteUrl = (process.env.NEXT_PUBLIC_SITE_URL ?? "https://matheoguilbert.fr").replace(/\/$/, ""); export async function generateMetadata({ params }: props): Promise { const { locale, slug } = await params; const article = getArticleBySlug(slug, locale); if (!article || !article.ready) { return {}; } const languageAlternates = getAlternatesArticle(article); const absoluteLanguageAlternates = Object.fromEntries( Object.entries(languageAlternates).map(([language, path]) => [ language, `${siteUrl}${path}`, ]) ); const url = `${siteUrl}/${locale}/blog/${slug}`; const title = article.title; const description = article.description; const imageUrl = article.cover ? article.cover.startsWith("http") ? article.cover : `${siteUrl}${article.cover}` : `${siteUrl}/og-image.jpg`; return { title, description, alternates: { canonical: url, languages: { ...absoluteLanguageAlternates, "x-default": url, }, }, openGraph: { title, description, url, siteName: "Mathéo Guilbert", type: "article", locale, publishedTime: article.date, images: [ { url: imageUrl, width: 1200, height: 630, alt: title, }, ], }, twitter: { card: "summary_large_image", title, description, images: [imageUrl], }, robots: { index: true, follow: true, }, }; } export function generateStaticParams() { const paths: { locale: string; slug: string }[] = []; locales.forEach((locale) => { getAllArticles(locale).forEach((article) => { paths.push({ locale, slug: article.slug, }); }); }); return paths; } const mdxComponents = { a: (props: any) => { const href = props.href; const isInternalLink = href && (href.startsWith('/') || href.startsWith('#')); if (isInternalLink) { return ( {props.children} ); } return ( {props.children} ); }, }; export default async function ArticlePage({ params }: props) { const { locale, slug } = await params; const article = getArticleBySlug(slug, locale); if (!article || !article.ready) { notFound(); } const articleUrl = `${siteUrl}/${locale}/blog/${slug}`; const imageUrl = article.cover ? article.cover.startsWith("http") ? article.cover : `${siteUrl}${article.cover}` : `${siteUrl}/og-image.jpg`; const jsonLd = { "@context": "https://schema.org", "@type": "BlogPosting", headline: article.title, description: article.description, image: imageUrl, datePublished: article.date, dateModified: article.date, author: { "@type": "Person", name: "Mathéo Guilbert", url: siteUrl, }, publisher: { "@type": "Person", name: "Mathéo Guilbert", url: siteUrl, }, mainEntityOfPage: { "@type": "WebPage", "@id": articleUrl, }, }; return (