diff --git a/frontend/app/[locale]/blog/[slug]/PostDetails.tsx b/frontend/app/[locale]/blog/[slug]/PostDetails.tsx index 611cc811..d3be7b4d 100644 --- a/frontend/app/[locale]/blog/[slug]/PostDetails.tsx +++ b/frontend/app/[locale]/blog/[slug]/PostDetails.tsx @@ -187,15 +187,15 @@ export default async function PostDetails({ const post: Post | null = await client .withConfig({ useCdn: false }) .fetch(query, { - slug: slugParam, - locale, - }); + slug: slugParam, + locale, + }); const recommendedAll: Post[] = await client .withConfig({ useCdn: false }) .fetch(recommendedQuery, { - slug: slugParam, - locale, - }); + slug: slugParam, + locale, + }); const recommendedPosts = seededShuffle( recommendedAll, hashString(slugParam) @@ -212,9 +212,71 @@ export default async function PostDetails({ ].filter(Boolean) as string[]; const authorMeta = authorMetaParts.join(' · '); const categoryLabel = post.categories?.[0]; + const baseUrl = process.env.NEXT_PUBLIC_SITE_URL; + const postUrl = baseUrl + ? `${baseUrl}/${locale}/blog/${slugParam}` + : null; + const blogUrl = baseUrl ? `${baseUrl}/${locale}/blog` : null; + const description = plainTextFromPortableText(post.body).slice(0, 160); + const breadcrumbsJsonLd = + blogUrl && postUrl + ? { + '@context': 'https://schema.org', + '@type': 'BreadcrumbList', + itemListElement: [ + { + '@type': 'ListItem', + position: 1, + name: tNav('blog'), + item: blogUrl, + }, + { + '@type': 'ListItem', + position: 2, + name: post.title, + item: postUrl, + }, + ], + } + : null; + const articleJsonLd = + postUrl + ? { + '@context': 'https://schema.org', + '@type': 'BlogPosting', + headline: post.title, + description: description || undefined, + mainEntityOfPage: postUrl, + url: postUrl, + datePublished: post.publishedAt || undefined, + author: post.author?.name + ? { + '@type': 'Person', + name: post.author.name, + } + : undefined, + image: post.mainImage ? [post.mainImage] : undefined, + } + : null; return (
+ {breadcrumbsJsonLd && ( +