Next's Metadata API
Video Summary
All of the projects we've seen so far are missing one pretty important thing: a title!
This happens because we haven't included a <title>
in the <head>
of our document.
One way to fix this is to include it in our layout.js
. After all, React owns the entire DOM when we work with Next!
function FlashMsgLayout({ children }) { return ( <html lang="en"> <head> <title>Inline title</title> </head> <body> <ToastProvider> {children} <ToastShelf /> </ToastProvider> </body> </html> );}
This is a perfectly viable solution, but there's a more conventional way to do this in Next: the Metadata API.
Here's how it works: from any layout.js
or page.js
component, we can export a JS object that contains information about the page's metadata:
export const metadata = { title: 'Metadata Title',};
function FlashMsgLayout({ children }) { return ( <html lang="en"> <body> <ToastProvider> {children} <ToastShelf /> </ToastProvider> </body> </html> );}
The metadata
object can include lots of stuff: the page title, descriptions and other metadata for search engines, OpenGraph images, favicons… That said, I mostly use it for filling in text-based tags; as part of the Metadata API, things like favicons and OG images will automatically be included if we add those images to the /app
directory.
When Next renders this page, it'll notice that we've exported a metadata
object, and use it to automatically create and inject a <title>
into the <head>
of the document.
We can export metadata
objects from multiple files: metadata
in a page.js
will be merged with the metadata in layout.js
, allowing us to set a default value in the layout, and to overwrite it as-necessary in particular pages.
This will work in most cases, but every now and then, you'll hit a situation which requires a bit more control.
Earlier, we built the world's most boring social network. I think it'd be nice if the <title>
was specific to the current profile. That's the way it works on Twitter!
For example, when we're visiting María's profile, we should see her name in the title:
This is tricky, because the exact value will depend on the dynamic segment. We don't have access to that outside the Page component!
Fortunately, Next has an escape hatch for this exact situation. Instead of exporting a static metadata
object, we can export a dynamic generateMetadata
function.
Here's what it looks like:
export async function generateMetadata({ params }) { const profile = await getProfileInfo(params.profileId);
return { title: `${profile.name}’s profile`, };}
When Next renders this page, it notices we've exported this function. It then invokes this function with the same arguments it passed to our component!
We return a Metadata object, the same type of object we had been exporting before. Except now, it'll be dynamically recalculated based on the route params!
In cases like this, the generateMetadata
function is an absolute lifesaver. 💯
You can learn much more about the Metadata API in the Next docs (opens in new tab).