devnotes.

SEO, Metadata & Image/Font Optimization

Static metadata

Export a metadata object from any layout.tsx or page.tsx to control <title>, <meta> description, Open Graph tags, and more — Next.js injects them into <head> automatically:

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

export const metadata: Metadata = {
  title: 'About Us',
  description: 'Learn more about our company and mission.',
  openGraph: {
    title: 'About Us',
    images: ['/og-about.png'],
  },
};

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

Dynamic metadata with generateMetadata

For pages whose title/description depend on fetched data (a blog post, a product):

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

export async function generateMetadata({
  params,
}: {
  params: Promise<{ slug: string }>;
}): Promise<Metadata> {
  const { slug } = await params;
  const post = await getPost(slug);
  return {
    title: post.title,
    description: post.excerpt,
    openGraph: { images: [post.coverImage] },
  };
}

export default async function BlogPost({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  const post = await getPost(slug);
  return <article>{post.content}</article>;
}

Streaming Metadata (GA as of Next.js 16.2)

Historically, Next.js had to wait for generateMetadata to fully resolve before starting to stream any HTML. With Streaming Metadata, the page's visible content can start streaming to the browser immediately while metadata resolves in parallel, improving perceived load time on pages with slow metadata-fetching logic.

Automatic sitemaps and robots.txt

// app/sitemap.ts
import type { MetadataRoute } from 'next';

export default function sitemap(): MetadataRoute.Sitemap {
  return [
    { url: 'https://example.com', lastModified: new Date() },
    { url: 'https://example.com/about', lastModified: new Date() },
  ];
}
// app/robots.ts
import type { MetadataRoute } from 'next';

export default function robots(): MetadataRoute.Robots {
  return {
    rules: { userAgent: '*', allow: '/' },
    sitemap: 'https://example.com/sitemap.xml',
  };
}

Image optimization with next/image

import Image from 'next/image';

export default function Hero() {
  return (
    <Image
      src="/hero.jpg"
      alt="Students collaborating on a project"
      width={1200}
      height={600}
      priority // load eagerly for above-the-fold images
    />
  );
}

next/image automatically serves modern formats (WebP/AVIF) when supported, resizes images per device, lazy-loads off-screen images by default, and prevents layout shift by reserving the correct space using width/height.

Next.js SEO: Metadata API, next/image and next/font | DevNotes