Menu
Coddy logo textTech

Dynamic Metadata

Part of the Next.js Essentials section of Coddy's React journey — lesson 15 of 47.

A metadata object is a constant, so it can't help a dynamic route: app/dishes/[slug]/page.jsx serves a different dish at every URL, and each one needs its own title.

For that, export a function instead:

export async function generateMetadata({ params }) {
    const { slug } = await params;
    return { title: DISHES[slug].name };
}

It gets the same params the page gets (a promise, so you await it) and returns the same shape the metadata object had. Use one or the other, never both in the same file.

Title templates

Repeating the site name in every page's title gets old. A layout can hand down a pattern instead of a plain string:

// app/layout.jsx
export const metadata = {
    title: {
        default: 'Coddy Eats',
        template: '%s | Coddy Eats',
    },
};
  • default: the title for pages that set none
  • template: the pattern for pages that do; their title is dropped in where %s is

So a page returning title: 'Margherita' ends up as Margherita | Coddy Eats in the tab, and the home page, which sets nothing, stays Coddy Eats. Write the branding once, in the layout.

challenge icon

Challenge

Medium

Every dish page currently shows Coddy Eats in the tab. Give each one its own title.

In app/dishes/[slug]/page.jsx, add an exported async function called generateMetadata that:

  1. Takes { params } and awaits it to get slug
  2. Returns { title: DISHES[slug].name }

app/layout.jsx already carries the template '%s | Coddy Eats', so /dishes/margherita should end up titled Margherita | Coddy Eats. Have a look at the layout: you don't need to change it.

Try it yourself

import './globals.css';

export const metadata = {
    title: {
        default: 'Coddy Eats',
        template: '%s | Coddy Eats',
    },
};

export default function RootLayout({ children }) {
    return (
        <html lang="en">
            <body>
                {children}
            </body>
        </html>
    );
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Next.js Essentials