Metadata (for tsx and mdx pages)
In this chapter, we will add metadata to our pages (and layout) by using the Next.js Metadata API, this will add meta tags inside of the <head>
element of our HTML documents, which is essential to help the crawlers from search engines and social networks better understand the content of our pages. These efforts will result in improved SEO scores, which means we will be getting more traffic from organic sources
As we saw early in this tutorial, Next.js has created a layout.tsx
file in the /app
folder and already added a basic metadata object
Metadata in layouts
We start by editing the layout.tsx
file to add some entries to the metadata object:
Lines 7 to 10: we edit the title meta tag, the default title value was previously a string, but we turned it into an object with two properties
Line 8: by using the title.template we ensure that all will titles have a similar structure on every page and it helps reduce repetition (DRY)
Line 9: the second property is the default title for the homepage (which is required, when using template)
The template will work for any pages that are in the same route segment as the layout, as this is the root layout of our project, it means the template will work on all our pages
When we visit one of pages, Next.js metadata will replace title.template %s
placeholder with the title of the current page we are visiting
Line 11: we only changed the description default value to something else
Launch the dev server, then open the "home" page at http://localhost:3000/
, and then right-click and select inspect
Look at what is inside your page's <head>
element. There are, for example, some Next.js <script>
tags, but also the following 4 tags are now present:
The viewport
tag gets always added to every page by default, but you can customize the content value of the viewport using the generateViewport function:
The second charset
tag gets also added by Next.js to every page
And then there are also the two metadata tags we added in the layout.tsx
file, both title and description display the default values we have set in our layout
Now, let's have a look at the source code of our home page:
As we saw when inspecting the <head>
element of our page had meta tags, but our page.tsx
file does not have any code related to the metadata object, this is because every page will inherit the metadata we have set in the layout, you only add a metadata object in the pages for which you want to override the default values from the layout or if you want to add a new metadata property that you didn't set in the layout
Metadata in typescript pages
Let's keep the home page as is and instead edit the second page we created earlier, which is the /app/blog/page.tsx
file, and add some metadata to it:
Line 1: we import the Metadata
type to strictly type the metadata object
Lines 3 to 5: we create a metadata
object and add a custom title for the blog page
Now launch the dev server, then open the blog page http://localhost:3000/blog
in your browser, then right click and select Inspect
If you look at the meta tags you will notice that the title tag has used the template from our layout file and combined it with the custom title from the blog page. The description is unchanged, as we did NOT overwrite the default value from our layout
Metadata in MDX pages
When I first experimented with the new metadata object, I was wondering if it would also work in MDX pages, and YES, it does 🎉
Let's edit the last gfm playground page we created earlier and add some metadata on top:
Lines 1 to 3: we create a new metadata object and add a custom title for the GFM playground page (we do NOT import the Metadata
type as MDX files are not typescript)
If you inspect the source of the playground page http://localhost:3000/gfm_playground
, you will see the MDX page has the correct title (and also makes use of the template from the layout)
Congratulations 🎉 you just learned how to add metadata using layouts and pages
favicon (mobile icons)
Adding a favicon is important if you want to customize how the bookmarks of your project will look like or what the icon will be if a user adds a link to your website to their desktop
It is also very simple to add a favicon when using Next.js, all you need to do is create a favicon.ico file and then put it into your /app
folder
Besides adding a favicon.ico file, you can also add apple icons. You can add more than one by adding a number at the end of their name. For example, you can put an apple-icon1.png, apple-icon2.png and apple-icon3.png files into your /app
folder
Next.js will detect your app and fav icon files in the /app
folder and automatically generate the meta tags (and set attributes like the content-type and dimensions) for your:
If you have an image and want to quickly create a favicon online then I recommend checking out realfavicongenerator.net
Open Graph metadata
The Open Graph protocol is essential if you want to control what gets displayed when your content gets shared, but it is also helpful if you want to improve your SEO score. In the past, it was mostly regarded as a Facebook thing, but today a lot of social networks, messengers, search engines and a bunch of services will use the open graph data that your website provides
First, let's add a default Open Graph object to our root layout file:
Lines 12 to 17: we add an Open Graph object and set a few properties, like the permalink url of the page, the projects (blog, wesite, ...) site name, the locale of the content and the type of content that it is
As we already have a title and description in the regular metadata, we do NOT need to repeat those in the open graph data, Next.js will handle this automatically for us
Next, let's also add a metadata example to our GFM playground:
Lines 2 to 5: we overwrite the URL property of the Open Graph layout metadata with the permalink of the current page
Now inspect the source of the playground page http://localhost:3000/gfm_playground
, you will see that in the <head>
element of our page there are the following tags:
I expected to see 6 meta tags, but there are only 3, which means the openGraph object from the page did not get merged with the openGraph object of the layout. At first, I thought this was a bug, so I did a search in the Next.js issues in the Next.js GitHub repository and found an Issue Next.js issue "openGraph metadata not merging across layouts" #47540 and then 2 more Next.js issue "All properties of nested metadata objects like openGraph get overwritten even if only one was a duplicate" #46899, Next.js issue "Nested Open Graph metadata overwrites root metadata" #46434 about problems when merging openGraph of a page with the one of the layout. The issues all have comments which seem to indicate that this by design and it is not something they plan to change, as explained in this comment by a member of the Nextj.js team.
3 ways to merge Open Graph metadata
There are 3 different workarounds to merge Open Graph meta data, I will start with the most obvious one and end with one that is a bit more complex:
Solution 1: we can repeat the open graph values in every page, in which we use the static metadata export, this means manually copying the open graph we already set in the layout and adding it again to the page itself:
Lines 5 to 7: we manually re-add the Open Graph properties we already added in the layout
Solution 2: is to use the generateMetadata function to get the parent open graph metadata object and extend it manually:
When I saw the await
in the above code, I was afraid that using this might opt the page out of static rendering, so I used the npm run build
command to make a local test build and saw that it is NOT the case:
The same code we added to the MDX page can be strictly typed if we add it to a typescript page, like so:
Solution 3: as suggested in the metadata merging documentation, create a file with default open graph values and then always import that file:
First, we create a new shared
folder in the root of the project and then inside of it a metadata.ts
file, into which we add the metadata including our open graph we want to use in every page:
Then we import the shared open graph file inside of our page(s):
Make sure the sharedMetadata
variable is first in the openGraph
so that what comes after overwrites the default values
Congratulations 🎉 you now also have support for open graph metadata in your project
If you liked this post, please consider making a donation ❤️ as it will help me create more content and keep it free for everyone