Next.js - Meta Data
Next.js - Managing Page Metadata
Section titled “Next.js - Managing Page Metadata”Modifying the <head> section of your HTML pages is essential for SEO (Search Engine Optimization), social media sharing (Open Graph tags), and providing context to the browser (like setting the page title).
Next.js provides different ways to manage metadata depending on whether you are using the App Router or the Pages Router.
1. App Router: Metadata API (Recommended)
Section titled “1. App Router: Metadata API (Recommended)”The App Router introduces a powerful Metadata API. You can define metadata by exporting a static metadata object or a dynamic generateMetadata function from a layout.js or page.js file.
Static Example (app/about/page.js):
import { Metadata } from 'next';
export const metadata: Metadata = { title: 'About Us | My Awesome Site', description: 'Learn more about our company and team.', openGraph: { title: 'About Us | My Awesome Site', description: 'Learn more about our company and team.', // images: ['/path/to/image.jpg'], },};
export default function AboutPage() { return ( <div> <h1>About Us</h1> <p>This page uses the static Metadata API.</p> </div> );}Dynamic Example (app/posts/[slug]/page.js): Fetches data to generate metadata.
import { Metadata, ResolvingMetadata } from 'next';
// Function to fetch post data (replace with your actual data fetching logic)async function getPostData(slug) { // const res = await fetch(`.../api/posts/${slug}`) // const post = await res.json() // return post return { title: `Post: ${slug}`, excerpt: `Details about post ${slug}` };}
type Props = { params: { slug: string }; searchParams: { [key: string]: string | string[] | undefined };};
export async function generateMetadata( { params, searchParams }: Props, parent: ResolvingMetadata): Promise<Metadata> { // read route params const slug = params.slug;
// fetch data const post = await getPostData(slug);
// optionally access and extend (rather than replace) parent metadata // const previousImages = (await parent).openGraph?.images || [];
return { title: post.title, description: post.excerpt, openGraph: { title: post.title, description: post.excerpt, // images: ['/some-specific-post-image.jpg', ...previousImages], }, };}
export default async function PostPage({ params }: Props) { const post = await getPostData(params.slug); return ( <div> <h1>{post.title}</h1> <p>This page uses the dynamic generateMetadata function.</p> </div> );}The Metadata API automatically handles merging metadata from parent layouts and deduplicating tags, making it robust and easier to manage.
2. Pages Router: next/head Component
Section titled “2. Pages Router: next/head Component”In the Pages Router, you use the built-in Head component imported from next/head. Any tags you place inside <Head> will be appended to the <head> section of the final HTML.
Let’s update sample pages (pages/index.js and pages/posts/first-post.js) to include titles and meta descriptions using <Head>.
Update pages/index.js:
import Link from 'next/link';import Head from 'next/head'; // Import Head
function HomePage() { return ( <> {/* Add Head component */} <Head> <title>Welcome to My Next.js Site!</title> <meta name="description" content="The homepage of my awesome Next.js application" /> {/* You can add other tags like Open Graph meta tags here */} <meta property="og:title" content="Welcome to My Next.js Site!" /> </Head>
<div> <h1>Welcome to Next.js!</h1> <Link href="/posts/first-post"> <a>Go to First Post</a> </Link> </div> </> );}
export default HomePage;Update pages/posts/first-post.js:
import Link from 'next/link';import Head from 'next/head'; // Import Headimport Layout from '../../components/layout'; // Assuming Layout component exists
export default function FirstPost() { return ( <Layout> {/* Add Head component */} <Head> <title>My First Post | Next.js Blog</title> <meta name="description" content="Reading the very first post on this blog." /> </Head>
<h1>My First Post</h1> <p>This is the content of the first post.</p> <h2> <Link href="/"> <a>Back to home</a> </Link> </h2> </Layout> );}If multiple components in the render tree use <Head> with the same tag (e.g., multiple <title> tags), Next.js will automatically deduplicate them, typically keeping the last one defined. To ensure uniqueness for tags like <meta name="description">, add a unique key prop: <meta name="description" key="desc" content="..." />.
Running the Development Server
Section titled “Running the Development Server”Start the server if it’s not running:
npm run dev
# Example Output:# ready - started server on 0.0.0.0:3000, url: http://localhost:3000Verify Output
Section titled “Verify Output”-
Open
http://localhost:3000in your browser. Check the browser tab title - it should display ‘Welcome to My Next.js Site!’. View the page source (Right-click -> View Page Source or use browser developer tools) and inspect the<head>section. You should find the<title>and<meta name="description">tags as defined inpages/index.js. -
Click the link to navigate to the ‘First Post’ (
/posts/first-post). Observe that the browser tab title changes to ‘My First Post | Next.js Blog’. Inspect the page source again; the<head>section should now contain the metadata defined inpages/posts/first-post.js.
Properly managing metadata is crucial for how search engines index your site and how links appear when shared on social media platforms.