Metadata API в Next.js 13+ — SEO-метаданные в App Router

27 июля 2026
Автор

Антон Ларичев

Введение

SEO-метаданные — title, description, Open Graph, canonical URL — критически важны для продвижения сайта в поисковых системах и красивого отображения ссылок в социальных сетях.

В Pages Router метаданные задавались через компонент <Head> из next/head. В App Router (Next.js 13+) появился новый Metadata API — декларативный способ управления метаданными через экспорт объекта или функции из файлов layout.tsx и page.tsx.

Курсы PurpleSchool

Учитесь у практикующих разработчиков — без воды

40 000+ студентов · рейтинг 4.8 · гарантия возврата 30 дней

Статические метаданные

Для страниц с фиксированными метаданными экспортируйте объект metadata:

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

export const metadata: Metadata = {
  title: 'О компании — PurpleSchool',
  description: 'Онлайн-школа программирования PurpleSchool — курсы по React, Next.js, TypeScript и Node.js.',
};

export default function AboutPage() {
  return <main>...</main>;
}

Шаблон заголовка — title.template

Чтобы не повторять название сайта в каждом заголовке, используйте title.template в корневом layout:

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

export const metadata: Metadata = {
  title: {
    template: '%s | PurpleSchool',
    default: 'PurpleSchool — онлайн-школа программирования',
  },
  description: 'Курсы по React, Next.js, TypeScript и Node.js.',
};
// app/courses/page.tsx
export const metadata: Metadata = {
  title: 'Каталог курсов', // → "Каталог курсов | PurpleSchool"
};

%s заменяется на title дочерней страницы. default используется если страница не задала собственный title.

Динамические метаданные — generateMetadata

Для страниц с динамическими данными (например, статья блога или страница курса) используйте функцию generateMetadata:

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

interface Props {
  params: { slug: string };
}

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const post = await fetchPost(params.slug);

  if (!post) {
    return {
      title: 'Статья не найдена',
    };
  }

  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      images: [
        {
          url: post.coverImage,
          width: 1200,
          height: 630,
          alt: post.title,
        },
      ],
    },
  };
}

generateMetadata выполняется на сервере, может делать async-запросы, и её результат кешируется вместе со страницей.

Open Graph и социальные сети

export const metadata: Metadata = {
  title: 'Курс по Next.js',
  description: 'Полное руководство по Next.js с нуля до продакшена.',
  openGraph: {
    title: 'Курс по Next.js — PurpleSchool',
    description: 'Полное руководство по Next.js с нуля до продакшена.',
    url: 'https://purpleschool.ru/course/nextjs',
    siteName: 'PurpleSchool',
    images: [
      {
        url: 'https://purpleschool.ru/og/nextjs-course.jpg',
        width: 1200,
        height: 630,
        alt: 'Курс по Next.js',
      },
    ],
    locale: 'ru_RU',
    type: 'website',
  },
};

Open Graph используется Facebook, VK, Telegram и другими платформами для формирования превью ссылки.

Twitter Card

export const metadata: Metadata = {
  twitter: {
    card: 'summary_large_image',
    title: 'Курс по Next.js',
    description: 'Полное руководство по Next.js.',
    images: ['https://purpleschool.ru/og/nextjs-course.jpg'],
    creator: '@purpleschool',
  },
};

Robots — управление индексацией

export const metadata: Metadata = {
  robots: {
    index: true,
    follow: true,
    googleBot: {
      index: true,
      follow: true,
      'max-image-preview': 'large',
      'max-snippet': -1,
    },
  },
};

Для страниц, которые не должны индексироваться (например, страница входа, корзина):

// app/login/page.tsx
export const metadata: Metadata = {
  robots: {
    index: false,
    follow: false,
  },
};

Canonical URL

Canonical URL указывает поисковику основной адрес страницы — важно при дублировании контента:

export const metadata: Metadata = {
  alternates: {
    canonical: 'https://purpleschool.ru/course/nextjs',
    languages: {
      'ru-RU': 'https://purpleschool.ru/course/nextjs',
    },
  },
};

Иконки и манифест приложения

// app/layout.tsx
export const metadata: Metadata = {
  icons: {
    icon: '/favicon.ico',
    shortcut: '/favicon-16x16.png',
    apple: '/apple-touch-icon.png',
  },
  manifest: '/site.webmanifest',
};

Файл opengraph-image и twitter-image

Для удобства Next.js поддерживает специальные файлы изображений. Если положить opengraph-image.jpg рядом с page.tsx, он автоматически станет OG-изображением для этой страницы:

app/
├── layout.tsx
├── page.tsx
├── opengraph-image.jpg   # OG-изображение для /
└── blog/
    ├── page.tsx
    └── [slug]/
        ├── page.tsx
        └── opengraph-image.tsx  # динамическое OG-изображение

Файл opengraph-image.tsx может генерировать изображение динамически через ImageResponse:

// app/blog/[slug]/opengraph-image.tsx
import { ImageResponse } from 'next/og';

export const runtime = 'edge';
export const size = { width: 1200, height: 630 };
export const contentType = 'image/png';

export default async function Image({ params }: { params: { slug: string } }) {
  const post = await fetchPost(params.slug);

  return new ImageResponse(
    (
      <div
        style={{
          background: '#1a1a2e',
          width: '100%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          fontSize: 48,
          color: 'white',
        }}
      >
        {post.title}
      </div>
    ),
    { ...size }
  );
}

Metadata в Pages Router

В Pages Router используется компонент <Head>. Metadata API там недоступен:

// pages/about.tsx
import Head from 'next/head';

export default function AboutPage() {
  return (
    <>
      <Head>
        <title>О компании | PurpleSchool</title>
        <meta name="description" content="Описание страницы" />
        <meta property="og:title" content="О компании" />
        <meta property="og:image" content="/og/about.jpg" />
      </Head>
      <main>...</main>
    </>
  );
}

Итог

Metadata API в App Router — декларативный и мощный способ управлять SEO:

  • metadata — статические метаданные для фиксированных страниц
  • generateMetadata — динамические метаданные для страниц с данными
  • title.template — шаблон заголовка для всего сайта
  • Open Graph / Twitter Card — красивые превью в социальных сетях
  • Canonical — управление дублированием контента
  • opengraph-image.tsx — динамическая генерация OG-изображений

Подробнее про Next.js — на курсе Next.js на PurpleSchool.

Стрелочка влевоnext/font — подключение и оптимизация шрифтов в Next.jsApp Router vs Pages Router в Next.js — сравнение и выборСтрелочка вправо

Все гайды по Next-js

Открыть базу знаний

Отправить комментарий