Commit cc45d518 by PLN (Algolia)

feat: /blog pages point canonical at the root form

The root form is canonical (DESIGN.md): the alias keeps serving the same
page but declares alternates.canonical at me.nech.pl/<slug>, once per
post across the language variant too.
parent caa6587a
import { notFound } from "next/navigation"; import { notFound } from "next/navigation";
import PostArticle from "../../PostArticle"; import PostArticle from "../../PostArticle";
import { buildLanguageNav } from "../../language-nav"; import { buildLanguageNav } from "../../language-nav";
import { BLOG_LANGS, DEFAULT_LANG, getAllBlogSlugs, getBlogLanguages, getBlogPost } from "@/lib/blog"; import { BLOG_LANGS, DEFAULT_LANG, blogCanonicalPath, getAllBlogSlugs, getBlogLanguages, getBlogPost } from "@/lib/blog";
/** /**
* Non-default language route: `/blog/<slug>/<lang>`. The default language is * Non-default language route: `/blog/<slug>/<lang>`. The default language is
...@@ -25,14 +25,19 @@ export async function generateMetadata({ params }) { ...@@ -25,14 +25,19 @@ export async function generateMetadata({ params }) {
const post = await getBlogPost(slug, lang).catch(() => null); const post = await getBlogPost(slug, lang).catch(() => null);
if (!post) return {}; if (!post) return {};
// Alias with canonical: the canonical is declared once per post — the root
// form of the canonical folder slug (DESIGN.md, "the root form is
// canonical"). Language variants and root keys all point there.
const canonical = blogCanonicalPath(post.slug);
return { return {
title: post.title, title: post.title,
description: post.description, description: post.description,
alternates: { canonical },
openGraph: { openGraph: {
title: post.title, title: post.title,
description: post.description, description: post.description,
type: 'article', type: 'article',
url: `/blog/${post.slug}`, url: canonical,
publishedTime: post.date, publishedTime: post.date,
images: ['/images/profile.png'], images: ['/images/profile.png'],
}, },
......
import { notFound } from "next/navigation"; import { notFound } from "next/navigation";
import PostArticle from "../PostArticle"; import PostArticle from "../PostArticle";
import { buildLanguageNav } from "../language-nav"; import { buildLanguageNav } from "../language-nav";
import { getAllBlogSlugs, getBlogPost } from "@/lib/blog"; import { blogCanonicalPath, getAllBlogSlugs, getBlogPost } from "@/lib/blog";
export function generateStaticParams() { export function generateStaticParams() {
const slugs = getAllBlogSlugs(); const slugs = getAllBlogSlugs();
...@@ -14,14 +14,18 @@ export function generateStaticParams() { ...@@ -14,14 +14,18 @@ export function generateStaticParams() {
export async function generateMetadata({ params }) { export async function generateMetadata({ params }) {
const { slug } = await params; const { slug } = await params;
const post = await getBlogPost(slug); const post = await getBlogPost(slug);
// Alias with canonical: the root form is the real address (DESIGN.md) —
// this page serves the same content and points at it.
const canonical = blogCanonicalPath(post.slug);
return { return {
title: post.title, title: post.title,
description: post.description, description: post.description,
alternates: { canonical },
openGraph: { openGraph: {
title: post.title, title: post.title,
description: post.description, description: post.description,
type: 'article', type: 'article',
url: `/blog/${post.slug}`, url: canonical,
publishedTime: post.date, publishedTime: post.date,
images: ['/images/profile.png'], images: ['/images/profile.png'],
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment