#nextjs #seo #metadata #open-graph

Day 7 — Metadata & SEO: The Static & The Dynamic

🧭 Day 7 — Metadata & SEO: The Static & The Dynamic

Zero to Hero — Hands-on Next.js Tutorial

Search Engine Optimization (SEO) is built into the core of Next.js. Gone are the days of installing react-helmet. We now export a metadata object.


🟦 1. Static Metadata (layout.tsx)

In your Root Layout (or any layout/page), export a metadata constant. This sets the default SEO tags for that subtree.

// src/app/layout.tsx
import type { Metadata } from 'next';

export const metadata: Metadata = {
  title: {
    template: '%s | CodeCompass',
    default: 'CodeCompass', // a default is required when creating a template
  },
  description: 'The ultimate developer blog for Angular and Next.js.',
  openGraph: {
    title: 'CodeCompass',
    description: 'Learn web dev the right way.',
  },
};

Template: The %s allows child pages to inject their title. e.g., If a child page has title “About”, the browser tab shows: “About | CodeCompass”.


🟩 2. Dynamic Metadata (generateMetadata)

For dynamic routes (like /blog/[slug]), you can’t assume the title. You need to fetch data first. Use the generateMetadata function.

// src/app/blog/[slug]/page.tsx
import { Metadata } from 'next';

type Props = {
  params: { slug: string }
};

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  // 1. Fetch data
  const post = await fetchPost(params.slug);
  
  // 2. Return metadata object
  return {
    title: post.title,
    description: post.summary,
    openGraph: {
      images: [post.coverImage], // Great for social sharing!
    },
  };
}

export default function Page({ params }: Props) { 
  /* ... render component ... */ 
}

Next.js automatically deduplicates requests. If you call fetchPost(id) in metadata AND in the component, Next.js only makes one actual API request.


🟧 3. Favicons & Social Images

Next.js has “File-based Metadata”. Just drop files into your app/ folder!

  • favicon.ico -> Browser icon.
  • opengraph-image.png -> Social card for Twitter/Facebook.
  • twitter-image.png -> Twitter specific card.
  • sitemap.ts -> Auto-generate your sitemap.
  • robots.ts -> Auto-generate robots.txt.

Dynamic OpenGraph Images: You can even generate images with code using ImageResponse! (We’ll cover this in the advanced week).


🧪 Challenge: Day 7

  1. Add a favicon.ico to your app folder (or public folder).
  2. Update your Root Layout metadata to have a cool title template (e.g., %s | Next Hero).
  3. Create a dynamic route /users/[id] and implement generateMetadata to change the page title to “User Profile: [ID]”.
  4. Inspect the <head> of your page in DevTools to verify the tags are there.

See you tomorrow for the big shift: Server vs. Client Components! ⚛️