Good Code
The good version lets Next.js generate route metadata from server-side article data.
Lesson 09
Use the Metadata API in Server Components instead of mutating the document head manually.
import type { Metadata } from "next";
import { getArticleBySlug } from "@/lib/articles";
export async function generateMetadata({
params,
}: PageProps<"/articles/[slug]">): Promise<Metadata> {
const { slug } = await params;
const article = await getArticleBySlug(slug);
// generateMetadata makes head data part of the server route contract.
return {
title: article?.title ?? "Article not found",
description: article?.excerpt ?? "This article is not available.",
};
}
export default async function ArticlePage({
params,
}: PageProps<"/articles/[slug]">) {
const { slug } = await params;
const article = await getArticleBySlug(slug);
return <h1>{article?.title}</h1>;
}"use client";
import { useEffect } from "react";
export function ArticleTitle({ title }: { title: string }) {
// Updating document.title after hydration is too late for reliable previews.
useEffect(() => {
document.title = title;
}, [title]);
return <h1>{title}</h1>;
}The good version lets Next.js generate route metadata from server-side article data.
The bad version updates document.title after hydration, so crawlers and social previews can miss the route-specific metadata.