Пошук уроків, статей та іншого контенту
Налаштуєте Open Graph для коректних заголовків, описів, зображень і прев’ю сторінок у соцмережах.
Open Graph — це набір метатегів, за якими соціальні мережі та месенджери формують прев’ю сторінки:
заголовок;
опис;
зображення;
URL;
тип контенту;
назву сайту.
Коли користувач поширює сторінку, наприклад у Facebook, LinkedIn або Telegram, сервіс читає ці метатеги з HTML-документа. Якщо їх не налаштувати, платформа може використати випадковий заголовок, перше зображення зі сторінки або взагалі показати неповне прев’ю.
У Next.js з App Router Open Graph налаштовується через Metadata API.
layout.tsxМетадані, оголошені в кореневому app/layout.tsx, застосовуються до всіх сторінок застосунку, якщо їх не перевизначити на нижчому рівні.
Структура файлів:
app/
layout.tsx
page.tsx
public/
images/
og-default.pngФайл зображення повинен розташовуватися в папці public. Він буде доступний за адресою /images/og-default.png.
// app/layout.tsx
import type { Metadata } from 'next';
import './globals.css';
export const metadata: Metadata = {
metadataBase: new URL('https://example.com'),
title: {
default: 'DevSpace',
template: '%s | DevSpace',
},
description: 'Практичні матеріали для розробників програмного забезпечення.',
openGraph: {
type: 'website',
locale: 'uk_UA',
url: '/',
siteName: 'DevSpace',
title: 'DevSpace',
description: 'Практичні матеріали для розробників програмного забезпечення.',
images: [
{
url: '/images/og-default.png',
width: 1200,
height: 630,
alt: 'DevSpace — матеріали для розробників',
},
],
},
twitter: {
card: 'summary_large_image',
},
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="uk">
<body>{children}</body>
</html>
);
}metadataBase використовується Next.js для перетворення відносних URL на абсолютні. Наприклад:
/images/og-default.pngперетвориться на:
https://example.com/images/og-default.pngДля реального проєкту замініть https://example.com на домен вашого сайту.
titleЗаголовок сторінки, який відображатиметься у прев’ю.
openGraph: {
title: 'Курс Next.js для розробників',
}Зазвичай заголовок має бути коротким і зрозумілим. Не варто дублювати в ньому весь текст сторінки.
descriptionКороткий опис вмісту сторінки:
openGraph: {
description: 'Вивчіть маршрутизацію, серверні компоненти та Metadata API у Next.js.',
}Опис має пояснювати користувачу, що він побачить після переходу за посиланням.
imagesЗображення для прев’ю можна передати як рядок:
openGraph: {
images: ['/images/og-default.png'],
}Але об’єкт дає змогу додати розміри та альтернативний текст:
openGraph: {
images: [
{
url: '/images/og-default.png',
width: 1200,
height: 630,
alt: 'Обкладинка курсу Next.js',
},
],
}Для стандартного горизонтального прев’ю часто використовують співвідношення сторін 1200 × 630. Зображення повинно бути доступне без авторизації та повертатися сервером зі статусом 200.
urlКанонічна адреса сторінки:
openGraph: {
url: '/courses/nextjs',
}Якщо URL залежить від поточної сторінки, його потрібно змінювати разом з іншими метаданими.
typeТип контенту:
openGraph: {
type: 'website',
}Для звичайних сторінок використовуйте website. Для публікацій можна використовувати article.
siteName і localesiteName — назва всього сайту, а locale — локаль контенту:
openGraph: {
siteName: 'DevSpace',
locale: 'uk_UA',
}Ці поля не замінюють title і description, а доповнюють їх.
Метадані в page.tsx мають вищий пріоритет, ніж метадані з батьківського layout.tsx. Це дає змогу створювати окреме прев’ю для кожної сторінки.
// app/courses/nextjs/page.tsx
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Курс Next.js',
description: 'Практичний курс зі створення сучасних застосунків на Next.js.',
openGraph: {
type: 'website',
url: '/courses/nextjs',
title: 'Курс Next.js',
description: 'Практичний курс зі створення сучасних застосунків на Next.js.',
images: [
{
url: '/images/nextjs-course.png',
width: 1200,
height: 630,
alt: 'Курс Next.js',
},
],
},
};
export default function NextJsCoursePage() {
return (
<main>
<h1>Курс Next.js</h1>
<p>Практичний курс зі створення сучасних застосунків на Next.js.</p>
</main>
);
}Якщо metadataBase визначено в кореневому layout, URL /images/nextjs-course.png буде коректно перетворено на абсолютний URL.
Для динамічних маршрутів, наприклад /blog/[slug], статичного metadata недостатньо. Для кожної статті потрібно сформувати власний заголовок, опис і зображення.
У такому випадку використовується асинхронна функція generateMetadata.
// app/blog/[slug]/page.tsx
import type { Metadata } from 'next';
import { notFound } from 'next/navigation';
type Post = {
title: string;
description: string;
image: string;
};
const posts: Record<string, Post> = {
'nextjs-metadata': {
title: 'Metadata API у Next.js',
description: 'Як налаштувати SEO-метадані та Open Graph у Next.js.',
image: '/images/metadata-api.png',
},
'server-components': {
title: 'Серверні компоненти Next.js',
description: 'Основні принципи роботи серверних компонентів у Next.js.',
image: '/images/server-components.png',
},
};
type PageProps = {
params: Promise<{
slug: string;
}>;
};
export async function generateMetadata({
params,
}: PageProps): Promise<Metadata> {
const { slug } = await params;
const post = posts[slug];
if (!post) {
return {
title: 'Статтю не знайдено',
description: 'Запитана стаття не існує.',
};
}
return {
title: post.title,
description: post.description,
openGraph: {
type: 'article',
url: `/blog/${slug}`,
title: post.title,
description: post.description,
images: [
{
url: post.image,
width: 1200,
height: 630,
alt: post.title,
},
],
},
};
}
export default async function BlogPostPage({ params }: PageProps) {
const { slug } = await params;
const post = posts[slug];
if (!post) {
notFound();
}
return (
<main>
<h1>{post.title}</h1>
<p>{post.description}</p>
</main>
);
}У цьому прикладі:
slug отримується з URL.
За slug знаходиться потрібна стаття.
generateMetadata повертає унікальні метадані.
Для кожної статті використовується власне зображення.
Якщо статті не існує, сторінка повертає метадані для помилки, а компонент викликає notFound().
На практиці дані можуть надходити з бази даних або CMS. Важливо, щоб запит для метаданих повертав ті самі основні дані, які потрібні для побудови заголовка, опису та зображення.
Next.js об’єднує метадані з layout-файлів і сторінок відповідно до структури маршруту.
Наприклад:
app/layout.tsx
app/blog/layout.tsx
app/blog/[slug]/page.tsxЗначення з app/layout.tsx є глобальними. Значення з app/blog/layout.tsx застосовуються до всіх статей блогу, а page.tsx може перевизначити їх для конкретної статті.
Приміром, у layout можна зберігати загальні поля:
// app/blog/layout.tsx
import type { Metadata } from 'next';
export const metadata: Metadata = {
openGraph: {
siteName: 'DevSpace Blog',
type: 'article',
},
};
export default function BlogLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return <section>{children}</section>;
}А в конкретній сторінці вказати власні title, description, url та images.
Для вкладених об’єктів, зокрема openGraph, не варто покладатися на злиття окремих полів без перевірки результату. Якщо сторінка має власне Open Graph-зображення, явно вкажіть потрібний масив images на рівні цієї сторінки.
Twitter, який нині також називають X, використовує власні метатеги Twitter Card. Next.js може згенерувати їх через поле twitter.
export const metadata: Metadata = {
openGraph: {
title: 'Курс Next.js',
description: 'Практичний курс зі створення застосунків на Next.js.',
images: ['/images/nextjs-course.png'],
},
twitter: {
card: 'summary_large_image',
title: 'Курс Next.js',
description: 'Практичний курс зі створення застосунків на Next.js.',
images: ['/images/nextjs-course.png'],
},
};summary_large_image вказує, що картка повинна використовувати велике зображення.
Open Graph і Twitter Card — окремі набори метатегів. Тому важливі сторінки краще налаштовувати для обох форматів.
Перевірте, що зображення:
має достатню роздільну здатність;
використовує горизонтальну композицію;
не містить важливого тексту біля країв;
доступне за публічним URL;
не вимагає cookies, токена або авторизації;
має правильний MIME-тип, наприклад image/png або image/jpeg;
має описовий alt.
Не використовуйте URL, доступний лише в локальному середовищі:
metadataBase: new URL('http://localhost:3000')Соціальна мережа не зможе отримати зображення з вашого локального комп’ютера. Для перевірки потрібен доступний ззовні домен, наприклад тестовий deployment.
Після запуску застосунку відкрийте сторінку в браузері та перегляньте її HTML-код. У ньому повинні бути метатеги, подібні до таких:
<meta property="og:title" content="Курс Next.js">
<meta property="og:description" content="Практичний курс зі створення сучасних застосунків на Next.js.">
<meta property="og:url" content="https://example.com/courses/nextjs">
<meta property="og:image" content="https://example.com/images/nextjs-course.png">
<meta property="og:type" content="website">Також перевірте, що:
og:title відповідає конкретній сторінці;
og:description не залишився від кореневого layout;
og:image є абсолютним URL;
зображення справді відкривається без авторизації;
og:url містить правильний маршрут;
на сторінці немає кількох конфліктних значень одного поля.
Соціальні платформи можуть кешувати отримані метадані. Тому після зміни зображення або опису прев’ю не завжди оновлюється миттєво. Спочатку переконайтеся, що нові метатеги вже присутні в HTML, а потім повторіть перевірку через потрібний сервіс.
metadataBaseЯкщо застосунок не має налаштованого metadataBase, відносний шлях до зображення може не перетворитися на коректний абсолютний URL.
export const metadata: Metadata = {
metadataBase: new URL('https://example.com'),
};localhostURL на кшталт http://localhost:3000/images/og.png працює лише на вашому комп’ютері. Зовнішня платформа не зможе його завантажити.
Глобальний опис підходить для головної сторінки, але сторінки статей, товарів або курсів повинні мати власні description.
Якщо сторінка має власне зображення, вкажіть повний набір потрібних Open Graph-полів, а не лише одне поле, яке може залишити частину глобальної конфігурації неочікуваною.
Metadata API використовується в layout і page-файлах серверної частини. Не оголошуйте metadata у файлі з директивою 'use client'.
alt для зображенняalt не замінює візуальне прев’ю, але описує його зміст і робить конфігурацію зрозумілішою.
Open Graph визначає, як сторінка виглядатиме під час поширення в соціальних мережах.
У Next.js метадані налаштовуються через metadata або generateMetadata.
Глобальні значення зручно оголошувати в app/layout.tsx.
Для конкретних сторінок можна оголосити власний metadata.
Для динамічних маршрутів використовуйте generateMetadata.
Зображення повинні бути публічними, доступними за абсолютним URL і мати відповідні розміри.
metadataBase допомагає Next.js правильно створювати абсолютні URL.
Для повного покриття соціальних платформ налаштовуйте і openGraph, і twitter.
Результат потрібно перевіряти в згенерованому HTML, а не лише в коді конфігурації.