Meta tags

Okay, we've covered rendering strategies. Now we're ready to discuss the next, possibly even more important thing - meta tags. There's actually a lot of new things here!

Pages router

In old versions of Next.js, to set meta tags, you needed to use the Head component from the next/head package.

import Head from "next/head";

function IndexPage() {
return (
<div>
<Head>
<title>My page title</title>
<meta name="description">My page description</meta>
</Head>
<p>Hello world!</p>
</div>
);
}

export default IndexPage;

Based on this approach, all SEO was done, requiring knowledge of exactly what you needed and how it worked. Nowadays, things are simpler, with ready-made tools available that cover most of your needs.

App router

Next.js version that based on app router has a Metadata API. there are several ways you can add metadata to your application:

  • Config-based Metadata: Export a static metadata object or a dynamic generateMetadata function in a layout.js or page.js file.
  • File-based Metadata: Add static or dynamically generated special files to route segments.

Static Metadata

To define static metadata, export a Metadata object from a layout.js or static page.js file.

import type { Metadata } from "next";

export const metadata: Metadata = {
title: "My page title",
description: "My page description",
};

export default function Page() {}

Static metadata covers most use cases. The following metadata properties are supported:

  • title: The title of the page.
  • description: The description of the page.
  • Basic Fields: generator, applicationName, referrer, keywords, authors, etc.
  • metadatabase: a convenience option to set a base URL prefix for metadata fields that require a fully qualified URL.
  • openGraph: Open Graph metadata.
  • robots: Robots metadata.

This is not a complete list of supported metadata properties. For a full list, see the Metadata object type definition.

Dynamic Metadata

Sure in most cases we need to set metadata dynamically. For this purpose, we can use the generateMetadata function.

import type { Metadata, ResolvingMetadata } from 'next'

type Props = {
params: { id: string }
searchParams: { [key: string]: string | string[] | undefined }
}

export async function generateMetadata(
{ params, searchParams }: Props,
parent: ResolvingMetadata
): Promise<Metadata> {
// read route params
const id = params.id

// fetch data
const product = await fetch(`https://.../${id}`).then((res) => res.json())

// optionally access and extend (rather than replace) parent metadata
const previousImages = (await parent).openGraph?.images || []

return {
title: product.title,
openGraph: {
images: ['/some-specific-page-image.jpg', ...previousImages],
},
}
}

export default function Page({ params, searchParams }: Props) {}

For all the available params, see the API Reference. This function give as a possibility to fetch data from API and set metadata based on this data. The rerutn object follow the format of the Metadata object.

File-based metadata

Last but not least, we can add metadata to our pages based on files. This is a powerful feature that designed to work with favicons, robots.txt, sitemap.xml, robots.txt etc.

We are not going to cover all the possibilities of this feature, Please read the full documentation here.

But we would like to hightkight one of them. It is a Dynamic Image Gerenation package.

Dynamic Image Generation

By using this feature we can greate og:image on a fly or on a build lvl. Simply create file named opengraph-image.tsx and write the following code:

import { ImageResponse } from "next/og";

// Route segment config
export const runtime = "edge";

// Image metadata
export const alt = "About Acme";
export const size = {
width: 1200,
height: 630,
};

export const contentType = "image/png";

// Image generation
export default async function Image() {
return new ImageResponse(
(
// ImageResponse JSX element
<div
style={{
fontSize: 128,
background: "white",
width: "100%",
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
About Acme
</div>
),
// ImageResponse options
{
// For convenience, we can re-use the exported opengraph-image
// size config to also set the ImageResponse's width and height.
...size,
}
);
}

Next.js will automatically generate an image and place all needed metadata in the head of the page. All work is done on the edge, so it is very fast and cacheable.

Conclusion

The latest versions of Next.js offer a range of built-in solutions for handling metadata, simplifying the process and reducing the need for additional libraries or extensive manual coding. These advancements provide us with efficient and flexible options for SEO optimization. So let's use them.