New: We've launched a brand new Coding Challenges section! Check out these interactive, real-world exercises to level up your skills.Explore Challenges
FrontendPrep
nextjsEasy

Next.js: SEO, Metadata, and Social Graphs

Loading...

Master Next.js App Router SEO. Learn to easily manage static and dynamic metadata, canonical URLs, OpenGraph properties, and automated sitemaps using real-world examples.

Arvind M
Arvind MLinkedIn

Next.js: SEO, Metadata, and Social Graphs

If you’ve ever wondered why your website looks amazing when you share it on Twitter, but dull when shared on Slack, or why search engines love some sites more than others, it usually boils down to Metadata.

Search Engine Optimization (SEO) is one of the biggest reasons teams pick Next.js. The Next.js App Router comes with a fantastic, built-in Metadata API that makes managing titles, descriptions, and those cool social media cards extremely easy and type-safe.

Let's break down how this works in the real world.


1. Static vs. Dynamic Metadata

Next.js gives you two ways to define metadata: Static and Dynamic.

A. Static Metadata (The "Set It and Forget It" Approach)

Imagine you are building a landing page for an online sneaker store called "SoleStyle". The homepage metadata never changes, so you can simply export a static metadata object in your page.tsx.

// app/page.tsx
import type { Metadata } from 'next';
 
export const metadata: Metadata = {
  title: 'SoleStyle | Premium Sneakers & Streetwear',
  description: 'Shop the latest drops from Nike, Adidas, and New Balance.',
};
 
export default function HomePage() {
  return <h1>Welcome to SoleStyle!</h1>;
}

B. Dynamic Metadata (The "Data-Driven" Approach)

Now, what if a user visits a specific sneaker's page? You can't hardcode the title—it needs to dynamically match the shoe they're looking at.

This is where generateMetadata shines. Next.js will run this function to fetch the shoe's data and generate the SEO tags before the page renders.

// app/products/[id]/page.tsx
import type { Metadata } from 'next';
 
type Props = {
  params: Promise<{ id: string }>;
};
 
// 1. Generate SEO metadata dynamically based on the product ID
export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const { id } = await params;
 
  // Fetching from your database or API
  const sneaker = await fetchSneaker(id);
 
  return {
    title: `${sneaker.name} | SoleStyle`,
    description: sneaker.shortDescription,
    openGraph: {
      images: [{ url: sneaker.imageUrl }], // Makes the link preview look great!
    },
  };
}
 
// 2. Render the actual page
export default async function ProductPage({ params }: Props) {
  const { id } = await params;
 
  // Wait, aren't we fetching the same data twice?
  // Nope! Next.js automatically deduplicates this fetch call.
  const sneaker = await fetchSneaker(id);
 
  return <h1>Buy the {sneaker.name}</h1>;
}

Pro Tip: Next.js automatically deduplicates the fetchSneaker calls. It will only make one network request, so you don't have to worry about performance hits!


2. OpenGraph and Social Media Cards

When someone shares your link on social media or messaging apps, OpenGraph (OG) tags determine what the preview card looks like. A great OG image can drastically increase your click-through rates.

Social Media Link Preview

Here is how you can configure these rich social cards alongside canonical URLs (which tell Google "Hey, this is the original source of this content"):

// app/blog/nextjs-seo/page.tsx
import type { Metadata } from "next";
 
export const metadata: Metadata = {
  alternates: {
    // Prevents search engines from penalizing you for duplicate content
    canonical: "https://frontendprep.io/blog/nextjs-seo",
  },
  openGraph: {
    title: "How to Master Next.js SEO in 2024",
    description:
      "A comprehensive guide to metadata, sitemaps, and ranking #1 on Google.",
    url: "https://frontendprep.io/blog/nextjs-seo",
    siteName: "SoleStyle Tech Blog",
    type: "article",
    images: [
      {
        url: "https://frontendprep.io/images/og-seo-guide.png",
        width: 1200,
        height: 630,
        alt: "Next.js SEO Guide Cover Image",
      },
    ],
  },
};

3. Automated Sitemaps (sitemap.ts)

A sitemap is like a map of your website that you hand directly to Google to help it find all your pages. Instead of manually maintaining an XML file, Next.js lets you generate it programmatically.

Just drop a sitemap.ts file in your root app/ directory:

// app/sitemap.ts
import { MetadataRoute } from "next";
import { getAllProducts } from "@/lib/db";
 
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const baseUrl = "https://frontendprep.io";
 
  // Fetch all your dynamic products
  const products = await getAllProducts();
 
  // Map them into standard sitemap entries
  const productUrls = products.map((product) => ({
    url: `${baseUrl}/products/${product.id}`,
    lastModified: product.updatedAt,
    changeFrequency: "weekly" as const,
    priority: 0.8,
  }));
 
  return [
    {
      url: baseUrl, // The homepage
      lastModified: new Date(),
      changeFrequency: "daily",
      priority: 1.0, // Highest priority
    },
    ...productUrls, // Spread the dynamic product URLs
  ];
}

💡 How to Answer in an Interview

"Next.js manages SEO in the App Router using a built-in, type-safe Metadata API.

For simple, unchanging pages, we can just export a static metadata object. But for dynamic pages—like an e-commerce product page—we use the generateMetadata function. This allows us to fetch data (like the product name or image) and dynamically generate SEO tags like <title>, canonical links, and OpenGraph social cards. Next.js is smart enough to automatically deduplicate the fetch requests between generateMetadata and the actual page component, so there's no performance penalty.

Finally, instead of managing static XML files, we can dynamically build sitemaps by exporting a function from app/sitemap.ts that queries our database and outputs a standardized sitemap."


🛑 Common Interview Mistakes

❌ Putting Metadata in Client Components

You cannot export metadata or generateMetadata from components that have "use client" at the top. They must be in Server Components. Search engine crawlers need this data in the initial HTML from the server to parse it easily.

❌ Worrying about Double-Fetching

Many developers try to build complex state management just to pass data from generateMetadata down to the page component. You don't need to do this! Next.js extends the native fetch API to automatically cache and deduplicate identical requests. Just fetch exactly what you need, wherever you need it.

Finished practicing this challenge?

Mark it as completed to track your progress, or bookmark it to review later.

Loading...

Share this Resource

Help other developers level up by sharing this study guide.

⚡ Weekly newsletter

Crack Your Next Frontend Interview.

Join senior engineers who receive practical, deep-dive frontend challenges, detailed concepts, and blueprints directly in their inbox.

  • Senior level React, JS, and CSS interview blueprints
  • System Design & performance optimization deep-dives
  • 100% free, zero spam, unsubscribe with one click

Join the Study Track

We value your privacy. Unsubscribe at any time.

More Technical Questions

Expand your mastery. Deep dive into other frontend interview challenges in this category.