Falytom logoFALYTOM
Games
ToolsUI ComponentsServicesProductsAbout
menu
  1. Home
  2. /Web Development
  3. /Nextjs
  4. /Static Metadata
Your Progress0%
0 of 70 completed

NextJS Topics

Getting Started

  • What is Next.js?
  • Next.js vs React - Key Differences
  • Creating Your First Next.js 15 Project
  • Next.js Project Structure Explained
  • App Router vs Pages Router

Routing Fundamentals

  • File-Based Routing Basics
  • Creating Pages with page.tsx
  • Dynamic Routes and Route Parameters
  • Catch-All and Optional Catch-All Routes
  • Route Groups for Organization
  • Parallel Routes
  • Intercepting Routes

Layouts and Pages

  • Understanding Layouts
  • Root Layout and Global Configuration
  • Nested Layouts
  • Templates vs Layouts
  • Loading States with loading.tsx
  • Error Handling with error.tsx

Server and Client Components

  • Understanding Server Components
  • Client Components with 'use client'
  • When to Use Server vs Client Components
  • Component Composition Patterns
  • Passing Props Between Server and Client
  • Server Component Patterns and Best Practices

Data Fetching

  • Fetching Data in Server Components
  • Parallel and Sequential Data Fetching
  • Data Fetching Patterns and Strategies
  • Caching and Revalidation
  • Revalidate and Cache Tags
  • Handling Loading and Error States in Data Fetching

Navigation and Links

  • Link Component Basics
  • useRouter Hook for Programmatic Navigation
  • usePathname and useSearchParams Hooks
  • Active Links and Navigation States
  • Redirects and Navigation Guards

Styling in Next.js

  • CSS Modules in Next.js
  • Tailwind CSS Setup and Configuration
  • Global Styles and CSS Variables
  • Next.js Font Optimization

Images and Media

  • Next.js Image Component Basics
  • Image Optimization and Best Practices
  • Working with Static Assets

Forms and Data Mutations

  • Understanding Server Actions
  • Form Handling with Server Actions
  • Form Validation and Error Handling
  • useFormStatus and useFormState Hooks
  • Revalidating Data After Mutations
  • Optimistic Updates

Metadata and SEO

  • Static Metadata Configuration
  • Dynamic Metadata Generation
  • Open Graph and Social Media Cards
  • Sitemap and Robots.txt

API Routes and Route Handlers

  • Route Handlers Introduction
  • GET and POST Request Handlers
  • Dynamic API Routes
  • Request and Response Objects
  • API Error Handling and Status Codes

Middleware and Advanced Features

  • Introduction to Middleware
  • Authentication with Middleware
  • Environment Variables and Configuration
  • Streaming and Suspense
  • Not Found and Global Error Pages

Deployment and Optimization

  • Understanding Static and Dynamic Rendering
  • generateStaticParams for Static Generation
  • Build and Production Optimization
  • Deploying to Vercel
  • Alternative Deployment Options
  • Performance Monitoring and Analytics

Real-World Projects

  • Project 1: E-commerce Product Catalog
  • Project 2: Dashboard with Authentication

Static Metadata Configuration

SEO optimization with the Metadata API

Good SEO starts with proper metadata. Next.js provides the Metadata API for type-safe, automatic meta tag generation. Export a metadata object from your pages and layouts, and Next.js generates the HTML <head> tags automatically. With metadata inheritance, you set defaults once and customize per page. Let's master SEO optimization in Next.js!

Why Metadata Matters for SEO

What Search Engines Use

  • Title: Appears in search results and browser tabs
  • Description: Shown in search result snippets
  • Keywords: Help categorize content (less important now)
  • Open Graph: Controls social media previews
  • Canonical URL: Prevents duplicate content penalties
  • Robots: Controls crawling and indexing

SEO Impact

Good metadata improves click-through rates from search results, prevents duplicate content issues, controls how pages appear on social media, and helps search engines understand your content. Proper metadata is essential for visibility.

Basic Metadata Configuration

Simple Page Metadata

app/about/page.tsx
import { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'About Us',
  description: 'Learn about our company, mission, and team.',
};

export default function AboutPage() {
  return (
    <div>
      <h1>About Us</h1>
      <p>Welcome to our about page!</p>
    </div>
  );
}

// Generates:
// <title>About Us</title>
// <meta name="description" content="Learn about our company..." />

// ✅ Type-safe with TypeScript
// ✅ Automatic meta tag generation
// ✅ No manual <head> manipulation needed

Comprehensive Metadata Example

app/page.tsx
import { Metadata } from 'next';

export const metadata: Metadata = {
  // Basic metadata
  title: 'Home - My Awesome Site',
  description: 'Welcome to My Awesome Site. We build amazing things.',
  
  // Keywords (less important for modern SEO)
  keywords: ['next.js', 'react', 'web development', 'tutorial'],
  
  // Authors
  authors: [
    { name: 'John Doe', url: 'https://johndoe.com' },
    { name: 'Jane Smith' },
  ],
  
  // Creator
  creator: 'My Awesome Company',
  publisher: 'My Awesome Company',
  
  // Application name
  applicationName: 'My Awesome Site',
  
  // Generator
  generator: 'Next.js',
  
  // Referrer policy
  referrer: 'origin-when-cross-origin',
  
  // Color scheme
  colorScheme: 'light',
  themeColor: '#ffffff',
  
  // Viewport (default is already optimal)
  // viewport: 'width=device-width, initial-scale=1',
};

export default function HomePage() {
  return <div>Home Page</div>;
}

// ✅ Comprehensive SEO metadata
// ✅ All fields type-safe
// ✅ Automatic HTML generation

Metadata Inheritance

Root Layout - Default Metadata

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

export const metadata: Metadata = {
  // Default title for all pages
  title: {
    template: '%s | My Awesome Site',
    default: 'My Awesome Site',
  },
  
  // Default description
  description: 'The best site on the internet',
  
  // Application metadata
  applicationName: 'My Awesome Site',
  authors: [{ name: 'My Company' }],
  
  // Default Open Graph
  openGraph: {
    siteName: 'My Awesome Site',
    locale: 'en_US',
    type: 'website',
  },
  
  // Robots
  robots: {
    index: true,
    follow: true,
    googleBot: {
      index: true,
      follow: true,
      'max-video-preview': -1,
      'max-image-preview': 'large',
      'max-snippet': -1,
    },
  },
};

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

// ✅ Default metadata for entire site
// ✅ title.template applies to all children
// ✅ title.default used when no child title set

Child Page - Inherits and Overrides

app/about/page.tsx
import { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'About Us',
  description: 'Learn about our company and team.',
};

export default function AboutPage() {
  return <div>About Us</div>;
}

// Final title: "About Us | My Awesome Site"
// ✅ Inherits template from root layout
// ✅ title becomes "About Us | My Awesome Site"
// ✅ Overrides description
// ✅ Keeps other metadata from root

How Inheritance Works

Metadata Cascade

TYPESCRIPT
// Root layout:
{
  title: { template: '%s | Site', default: 'Site' },
  description: 'Default description',
  keywords: ['default'],
}

// Child page:
{
  title: 'About',
  description: 'About page',
}

// Final result:
{
  title: 'About | Site',  // Template applied
  description: 'About page',  // Overridden
  keywords: ['default'],  // Inherited
}

// ✅ Child overrides parent
// ✅ Unspecified fields inherited
// ✅ Template applies to child titles

Advanced Title Configuration

Title Templates

TYPESCRIPT
// Template with %s placeholder
export const metadata = {
  title: {
    template: '%s | My Site',
    default: 'My Site',
  },
};

// Child pages:
// title: 'About' → "About | My Site"
// title: 'Blog' → "Blog | My Site"
// title: 'Contact' → "Contact | My Site"

// If child doesn't set title → "My Site" (default)

// ✅ Consistent branding
// ✅ DRY - set suffix once
// ✅ Automatic for all children

Absolute Title (Skip Template)

TYPESCRIPT
// Use absolute title to skip template
export const metadata = {
  title: {
    absolute: 'Special Page - No Template Applied',
  },
};

// Result: "Special Page - No Template Applied"
// ✅ Template NOT applied
// ✅ Use for pages that need exact title
// ✅ Good for landing pages, campaigns

Section-Specific Templates

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

export const metadata: Metadata = {
  title: {
    template: '%s - Blog | My Site',
    default: 'Blog | My Site',
  },
};

export default function BlogLayout({ children }) {
  return <div>{children}</div>;
}

// Blog post titles:
// title: 'My First Post' → "My First Post - Blog | My Site"
// title: 'React Tips' → "React Tips - Blog | My Site"

// ✅ Blog-specific template
// ✅ Overrides root template
// ✅ Consistent blog branding

Common Meta Tags

Open Graph Basics

TYPESCRIPT
export const metadata: Metadata = {
  title: 'My Page',
  description: 'Page description',
  
  openGraph: {
    title: 'My Page',  // Can differ from page title
    description: 'Page description for social media',
    url: 'https://example.com/page',
    siteName: 'My Site',
    locale: 'en_US',
    type: 'website',
    
    images: [
      {
        url: 'https://example.com/og-image.jpg',
        width: 1200,
        height: 630,
        alt: 'My Page Image',
      },
    ],
  },
};

// Generates:
// <meta property="og:title" content="My Page" />
// <meta property="og:description" content="..." />
// <meta property="og:image" content="..." />
// <meta property="og:url" content="..." />

// ✅ Controls social media previews
// ✅ Facebook, LinkedIn, etc.
// ✅ Type-safe configuration

Twitter Cards

TYPESCRIPT
export const metadata: Metadata = {
  twitter: {
    card: 'summary_large_image',
    title: 'My Page',
    description: 'Page description for Twitter',
    creator: '@myhandle',
    site: '@mysite',
    
    images: ['https://example.com/twitter-image.jpg'],
  },
};

// Card types:
// - 'summary': Small image
// - 'summary_large_image': Large image (recommended)
// - 'app': App card
// - 'player': Video/audio player

// ✅ Twitter-specific previews
// ✅ Different from Open Graph if needed
// ✅ Large image for better engagement

Canonical URLs and Alternates

TYPESCRIPT
export const metadata: Metadata = {
  // Canonical URL (prevents duplicate content)
  alternates: {
    canonical: 'https://example.com/preferred-url',
    
    // Alternate languages
    languages: {
      'en-US': 'https://example.com/en-us',
      'de-DE': 'https://example.com/de-de',
      'fr-FR': 'https://example.com/fr-fr',
    },
  },
};

// Generates:
// <link rel="canonical" href="https://example.com/preferred-url" />
// <link rel="alternate" hreflang="en-US" href="..." />
// <link rel="alternate" hreflang="de-DE" href="..." />

// ✅ Prevents duplicate content penalties
// ✅ Indicates preferred URL
// ✅ Multi-language support

Robots and Indexing

TYPESCRIPT
export const metadata: Metadata = {
  robots: {
    index: true,      // Allow indexing
    follow: true,     // Follow links
    nocache: false,   // Allow caching
    
    // Google-specific
    googleBot: {
      index: true,
      follow: true,
      'max-video-preview': -1,
      'max-image-preview': 'large',
      'max-snippet': -1,
    },
  },
};

// Generates:
// <meta name="robots" content="index, follow" />
// <meta name="googlebot" content="index, follow, max-video-preview:-1..." />

// ✅ Control search engine behavior
// ✅ Prevent indexing of sensitive pages
// ✅ Google-specific optimizations

// Example: Don't index admin pages
export const metadata: Metadata = {
  robots: {
    index: false,
    follow: false,
  },
};

Verification Tags

TYPESCRIPT
export const metadata: Metadata = {
  verification: {
    google: 'google-verification-code',
    yandex: 'yandex-verification-code',
    yahoo: 'yahoo-verification-code',
    other: {
      'fb:app_id': 'facebook-app-id',
    },
  },
};

// Generates:
// <meta name="google-site-verification" content="..." />
// <meta name="yandex-verification" content="..." />

// ✅ Verify site ownership
// ✅ Enable search console access
// ✅ Social media verification

Icons and Manifests

Favicon and Icons

TYPESCRIPT
export const metadata: Metadata = {
  icons: {
    icon: '/favicon.ico',
    shortcut: '/shortcut-icon.png',
    apple: '/apple-icon.png',
    other: [
      {
        rel: 'icon',
        type: 'image/png',
        sizes: '32x32',
        url: '/icon-32x32.png',
      },
      {
        rel: 'icon',
        type: 'image/png',
        sizes: '16x16',
        url: '/icon-16x16.png',
      },
    ],
  },
};

// Generates:
// <link rel="icon" href="/favicon.ico" />
// <link rel="shortcut icon" href="/shortcut-icon.png" />
// <link rel="apple-touch-icon" href="/apple-icon.png" />
// <link rel="icon" type="image/png" sizes="32x32" href="..." />

// ✅ Multiple icon sizes
// ✅ Apple touch icons
// ✅ Favicon configuration

Web App Manifest

TYPESCRIPT
export const metadata: Metadata = {
  manifest: '/manifest.json',
  
  // App-specific metadata
  applicationName: 'My Awesome App',
  appleWebApp: {
    capable: true,
    statusBarStyle: 'black-translucent',
    title: 'My Awesome App',
  },
};

// manifest.json:
{
  "name": "My Awesome App",
  "short_name": "MyApp",
  "description": "An awesome progressive web app",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#000000",
  "icons": [
    {
      "src": "/icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

// ✅ PWA support
// ✅ App-like experience
// ✅ Install to home screen

Complete Metadata Examples

Example 1: E-commerce Product Metadata

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

export const metadata: Metadata = {
  title: {
    template: '%s - Products | My Store',
    default: 'Products | My Store',
  },
  description: 'Browse our amazing products',
  
  openGraph: {
    type: 'website',
    siteName: 'My Store',
  },
};

export default function ProductsLayout({ children }) {
  return <div>{children}</div>;
}
app/products/[id]/page.tsx (static metadata)
import { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'Amazing Product',
  description: 'The best product you will ever buy',
  
  keywords: [
    'product',
    'e-commerce',
    'buy online',
    'amazing',
  ],
  
  openGraph: {
    title: 'Amazing Product',
    description: 'The best product you will ever buy',
    type: 'product',
    images: [
      {
        url: 'https://mystore.com/products/amazing-product.jpg',
        width: 1200,
        height: 630,
        alt: 'Amazing Product',
      },
    ],
  },
  
  twitter: {
    card: 'summary_large_image',
    title: 'Amazing Product',
    description: 'The best product you will ever buy',
    images: ['https://mystore.com/products/amazing-product.jpg'],
  },
  
  alternates: {
    canonical: 'https://mystore.com/products/amazing-product',
  },
};

export default function ProductPage() {
  return <div>Product Details</div>;
}

// ✅ Product-specific metadata
// ✅ Open Graph type: 'product'
// ✅ Rich social previews
// ✅ Canonical URL

Example 2: Blog Article Metadata

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

export const metadata: Metadata = {
  title: 'Understanding React Server Components',
  description: 'A deep dive into React Server Components and how they work in Next.js',
  
  authors: [{ name: 'John Doe', url: 'https://johndoe.com' }],
  
  keywords: [
    'react',
    'server components',
    'next.js',
    'web development',
  ],
  
  openGraph: {
    title: 'Understanding React Server Components',
    description: 'A deep dive into React Server Components',
    type: 'article',
    publishedTime: '2024-01-15T00:00:00.000Z',
    authors: ['John Doe'],
    tags: ['React', 'Next.js', 'Server Components'],
    images: [
      {
        url: 'https://myblog.com/articles/rsc-cover.jpg',
        width: 1200,
        height: 630,
        alt: 'React Server Components',
      },
    ],
  },
  
  twitter: {
    card: 'summary_large_image',
    title: 'Understanding React Server Components',
    description: 'A deep dive into React Server Components',
    creator: '@johndoe',
    images: ['https://myblog.com/articles/rsc-cover.jpg'],
  },
  
  alternates: {
    canonical: 'https://myblog.com/blog/react-server-components',
  },
  
  robots: {
    index: true,
    follow: true,
  },
};

export default function BlogPostPage() {
  return <article>Blog content...</article>;
}

// ✅ Article-specific metadata
// ✅ Open Graph type: 'article'
// ✅ Published time and authors
// ✅ Rich Twitter cards

Metadata Configuration Structure

Organization of metadata across pages and layouts

appImportant

Select a file or folder to see details

Metadata Best Practices

1. Set Defaults in Root Layout

TYPESCRIPT
// ✅ GOOD: Defaults in root layout
// app/layout.tsx
export const metadata = {
  title: {
    template: '%s | My Site',
    default: 'My Site',
  },
  description: 'Default description',
  openGraph: {
    siteName: 'My Site',
  },
};

// Pages only override what's different
// ❌ BAD: Repeating everything on every page

2. Use Descriptive Titles and Descriptions

TYPESCRIPT
// ✅ GOOD: Descriptive and specific
export const metadata = {
  title: 'Next.js Server Actions Tutorial - Complete Guide',
  description: 'Learn how to use Server Actions in Next.js 15 for form handling, mutations, and data updates with step-by-step examples.',
};

// ❌ BAD: Generic and vague
export const metadata = {
  title: 'Tutorial',
  description: 'Learn stuff',
};

// Good titles: 50-60 characters
// Good descriptions: 150-160 characters

3. Include Keywords Naturally

TYPESCRIPT
// ✅ GOOD: Natural keyword inclusion
export const metadata = {
  title: 'React Server Components Tutorial',
  description: 'Learn React Server Components in Next.js 15 with practical examples and best practices for building fast web applications.',
  keywords: ['react', 'server components', 'next.js', 'tutorial'],
};

// ❌ BAD: Keyword stuffing
export const metadata = {
  description: 'react server components react tutorial react next.js react components...',
};

// Keywords matter less than content quality

4. Always Set Canonical URLs

TYPESCRIPT
// ✅ GOOD: Canonical prevents duplicate content
export const metadata = {
  alternates: {
    canonical: 'https://example.com/preferred-url',
  },
};

// Especially important for:
// - Pages with query parameters
// - Multiple URLs for same content
// - Syndicated content

5. Optimize for Social Sharing

TYPESCRIPT
// ✅ GOOD: Rich social previews
export const metadata = {
  title: 'My Awesome Article',
  description: 'Great description',
  
  openGraph: {
    title: 'My Awesome Article',
    description: 'Great description',
    images: [
      {
        url: 'https://example.com/og-image.jpg',
        width: 1200,
        height: 630,  // Recommended Open Graph size
        alt: 'Descriptive alt text',
      },
    ],
  },
  
  twitter: {
    card: 'summary_large_image',
    images: ['https://example.com/twitter-image.jpg'],
  },
};

// Large images get more engagement
// Alt text improves accessibility

Key Takeaways

  • Export metadata object - type-safe configuration
  • Metadata inheritance - children merge with parents
  • Title templates - consistent branding with %s
  • Open Graph - controls social media previews
  • Twitter cards - Twitter-specific metadata
  • Canonical URLs - prevents duplicate content
  • Robots meta - controls indexing
  • Server Components only - metadata export not in Client Components

What's Next?

You've mastered static metadata! Next, we'll explore Dynamic Metadata Generation—generating metadata based on page data, route parameters, and external sources. You'll learn generateMetadata function, async metadata, and creating dynamic titles and descriptions for database-driven content!

We'll cover generateMetadata, fetching data for metadata, type-safe dynamic metadata, and optimizing metadata generation for performance.

🔍 SEO is Ongoing

Good metadata is the foundation of SEO, but it's just the start. Focus on quality content, fast loading times, mobile responsiveness, and good user experience. Metadata helps search engines understand your content—great content keeps users engaged!

Test Your Understanding

Question 1 of 4

How do you add metadata to a Next.js page?

Master static metadata in Next.js! Learn the Metadata API for better SEO and social media previews.

Previous
Optimistic Updates
Next
Dynamic Metadata Generation

Master Next.js SEO

Join 2,000+ developers building SEO-optimized Next.js apps. Get the next lesson on dynamic metadata generation - 100% FREE.

You might also like

UI Components

Ready-made components for your projects

Developer Tools

Boost productivity with handy generators

HTML Game

Learn HTML concepts through interactive gameplay

Join Our Web Development Training Program

Master frontend & backend development with hands-on projects.

NextJS Tutorials

0 of 70 completed

Your Progress0%

Topics

Getting Started

  • What is Next.js?
  • Next.js vs React - Key Differences
  • Creating Your First Next.js 15 Project
  • Next.js Project Structure Explained
  • App Router vs Pages Router

Routing Fundamentals

  • File-Based Routing Basics
  • Creating Pages with page.tsx
  • Dynamic Routes and Route Parameters
  • Catch-All and Optional Catch-All Routes
  • Route Groups for Organization
  • Parallel Routes
  • Intercepting Routes

Layouts and Pages

  • Understanding Layouts
  • Root Layout and Global Configuration
  • Nested Layouts
  • Templates vs Layouts
  • Loading States with loading.tsx
  • Error Handling with error.tsx

Server and Client Components

  • Understanding Server Components
  • Client Components with 'use client'
  • When to Use Server vs Client Components
  • Component Composition Patterns
  • Passing Props Between Server and Client
  • Server Component Patterns and Best Practices

Data Fetching

  • Fetching Data in Server Components
  • Parallel and Sequential Data Fetching
  • Data Fetching Patterns and Strategies
  • Caching and Revalidation
  • Revalidate and Cache Tags
  • Handling Loading and Error States in Data Fetching

Navigation and Links

  • Link Component Basics
  • useRouter Hook for Programmatic Navigation
  • usePathname and useSearchParams Hooks
  • Active Links and Navigation States
  • Redirects and Navigation Guards

Styling in Next.js

  • CSS Modules in Next.js
  • Tailwind CSS Setup and Configuration
  • Global Styles and CSS Variables
  • Next.js Font Optimization

Images and Media

  • Next.js Image Component Basics
  • Image Optimization and Best Practices
  • Working with Static Assets

Forms and Data Mutations

  • Understanding Server Actions
  • Form Handling with Server Actions
  • Form Validation and Error Handling
  • useFormStatus and useFormState Hooks
  • Revalidating Data After Mutations
  • Optimistic Updates

Metadata and SEO

  • Static Metadata Configuration
  • Dynamic Metadata Generation
  • Open Graph and Social Media Cards
  • Sitemap and Robots.txt

API Routes and Route Handlers

  • Route Handlers Introduction
  • GET and POST Request Handlers
  • Dynamic API Routes
  • Request and Response Objects
  • API Error Handling and Status Codes

Middleware and Advanced Features

  • Introduction to Middleware
  • Authentication with Middleware
  • Environment Variables and Configuration
  • Streaming and Suspense
  • Not Found and Global Error Pages

Deployment and Optimization

  • Understanding Static and Dynamic Rendering
  • generateStaticParams for Static Generation
  • Build and Production Optimization
  • Deploying to Vercel
  • Alternative Deployment Options
  • Performance Monitoring and Analytics

Real-World Projects

  • Project 1: E-commerce Product Catalog
  • Project 2: Dashboard with Authentication
Falytom logoFALYTOM

Learn technologies like HTML, CSS, JavaScript, React, NodeJS and more through interactive games, tutorials, components and free tools. Transform your businesses with AI chatbots, SEO-optimized websites, and professional development services.

© 2025 Tomilola Group
  • Facebook logo
  • Twitter logo
  • Instagram logo
  • LinkedIn logo
  • GitHub logo
  • YouTube logo