Generating metadata in Next.js dynamic routing

힘센캥거루
2024년 12월 16일
27
nextjs

While searching how to add metadata for search engine optimization, I came across a post on velog by Doeunnkimm and had been injecting metadata statically.

Once I started posting, I wanted to add different metadata for each post in dynamic routing.

So I’m writing this as a review and reference.

1. Code

First, the code I got from the velog post above is as follows.

// First, set the basic metadata you need.
const META = {
  title: "Blog title",
  siteName: "Site name",
  description: "A brief description of the blog",
  keyword: ["array", "type", "keywords"],
  url: "https://sample.kr",
  googleVerification: "xxx", // Google Search Console
  naverVerification: "xxx", // Naver Search Advisor
  ogImage: "https://sample.kr/assets/thumbnail.png", // thumbnail,
} as const;

// Use the getMetadata function to set metadata.
// With this single function, you can cover most metadata needed for most sites.
export const getMetadata = (metadataProps?: generateMetadataProps) => {
  const { title, description, asPath, ogImage } = metadataProps || {};

  const TITLE = title ? `${title} | Blog title` : META.title;
  const DESCRIPTION = description || META.description;
  const PAGE_URL = asPath ? asPath : "";
  const OG_IMAGE = ogImage || META.ogImage;

  const metadata: Metadata = {
    metadataBase: new URL(META.url),
    alternates: {
      canonical: PAGE_URL,
    },
    title: TITLE,
    description: DESCRIPTION,
    keywords: [...META.keyword],
    openGraph: {
      title: TITLE,
      description: DESCRIPTION,
      siteName: TITLE,
      locale: "ko_KR",
      type: "website",
      url: PAGE_URL,
      images: {
        url: OG_IMAGE,
      },
    },
    verification: {
      google: META.googleVerification,
      other: {
        "naver-site-verification": META.naverVerification,
      },
    },
    twitter: {
      title: TITLE,
      description: DESCRIPTION,
      images: {
        url: OG_IMAGE,
      },
    },
    icons: {
      icon: "/favicon/favicon.ico",
    },
  };

  return metadata;
};

Then you call this code in layout.tsx to use it.

By creating the metadata and exporting it, you generate metadata for the homepage.

import "./globals.css";
import { Metadata } from "next";
import { getMetadata } from "@/utils/getMetadata";

// Export the metadata object
export const metadata: Metadata = {
  // Use the spread operator .., to bring in the object.
  ...getMetadata(),

  // If you want to use another title, you can do it like this.
  ...getMetadata({ title: "Another title" }),
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ko">
      <body className="h-svh">
        <div>
          <div className="mx-auto max-w-7xl p-6 lg:px-8">{children}</div>
        </div>
      </body>
    </html>
  );
}

Open your homepage, press the F12 key, and check the <head> tag to see the metadata.

Generating metadata in Next.js dynamic routing-1

2. Dynamic routing and metadata

For dynamic routing, I used the generateMetadata function.

Explanations for this can be found in the blog above or in the official Next.js docs.

Generating metadata in Next.js dynamic routing-2

The key point of this post is that you can use the object used for dynamic routing when creating metadata.

I used the slug and a JSON file that contains the list of posts to create the metadata.

export async function generateMetadata({
  params,
}: {
  params: { slug: string };
}) {
  const { slug } = await params;

  // Load the category list JSON
  const categoryData = fs.readFileSync(categoryJsonPath, "utf-8");
  const categorys: postCardFrontMatter[] = JSON.parse(categoryData);

  // Find and return the single entry whose url matches the current slug.
  const baseMetaData = categorys.find(
    (category) => category.postUrlPath === slug
  );

  // Use this to set the metadata
  const metadata: Metadata = {
    ...getMetadata({
      title: baseMetaData?.data.title,
      description: baseMetaData?.data.description,
      asPath: `https://earthscience.kr/posts/${slug}`,
      ogImage:
        baseMetaData?.data.thumbnail &&
        `https://earthscience.kr/posts/${slug}/${baseMetaData.data.thumbnail}`,
    }),
  };
  return metadata;
}

3. Thoughts

People usually make good use of Facebook’s Sharing Debugger.

But I don’t have a Facebook account, so I just tested it via KakaoTalk.

The downside is that it takes a bit of time for the image to show up.

Generating metadata in Next.js dynamic routing-3

At first the image didn’t appear, but when I checked again the next day, it displayed fine.

It feels fun to build things up one by one.

댓글을 불러오는 중...