Пошук уроків, статей та іншого контенту
Перевірите технічне SEO Next.js-застосунку за покроковим списком перед публікацією та після релізу.
Технічне SEO Next.js-застосунку потрібно перевіряти не лише за наявністю title і description. Перед публікацією важливо переконатися, що пошукові роботи можуть:
отримати сторінки зі стабільними HTTP-відповідями;
знайти їх через внутрішні посилання або sitemap;
правильно зрозуміти канонічну адресу;
побачити контент без обов’язкової взаємодії користувача;
проіндексувати лише потрібні сторінки;
використати коректні заголовки, структуровані дані та прев’ю для соціальних мереж.
Нижче наведено checklist для застосунку на Next.js App Router.
До релізу потрібно обрати одну канонічну версію домену:
https://example.com;
або https://www.example.com.
Інші варіанти мають перенаправляти на основний домен через постійний редирект 301 або 308.
Перевірте окремо:
HTTP → HTTPS;
www → без www або навпаки;
/різні регістри символів у шляху;
альтернативні домени для preview або staging.
Не допускайте, щоб одна сторінка була доступна за кількома рівнозначними URL.
metadataBasemetadataBase потрібен Next.js для перетворення відносних URL у повні. Він впливає, зокрема, на:
canonical URL;
Open Graph URL;
URL зображень;
інші поля Metadata API.
// app/layout.tsx
import type { Metadata } from "next";
import type { ReactNode } from "react";
const siteUrl =
process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000";
export const metadata: Metadata = {
metadataBase: new URL(siteUrl),
title: {
default: "Acme Docs",
template: "%s | Acme Docs",
},
description:
"Документація та практичні матеріали для розробників.",
alternates: {
canonical: "/",
},
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
"max-image-preview": "large",
},
},
openGraph: {
type: "website",
siteName: "Acme Docs",
title: "Acme Docs",
description:
"Документація та практичні матеріали для розробників.",
url: "/",
images: [
{
url: "/og/default.png",
width: 1200,
height: 630,
alt: "Acme Docs",
},
],
},
twitter: {
card: "summary_large_image",
title: "Acme Docs",
description:
"Документація та практичні матеріали для розробників.",
images: ["/og/default.png"],
},
};
export default function RootLayout({
children,
}: {
children: ReactNode;
}) {
return (
<html lang="uk">
<body>{children}</body>
</html>
);
}У production змінна NEXT_PUBLIC_SITE_URL повинна містити справжню адресу сайту, наприклад:
NEXT_PUBLIC_SITE_URL=https://example.comПеревірте, що:
у значенні немає зайвого / в кінці;
використовується https;
значення однакове для всіх production-процесів;
preview-деплой не успадковує production-домен помилково.
Для кожної сторінки, яку потрібно показувати в пошуку, перевірте:
унікальний <title>;
унікальний description;
канонічний URL;
потрібний статус індексації;
коректну мову документа;
Open Graph-дані, якщо сторінкою мають ділитися в соціальних мережах.
title повинен:
описувати конкретний вміст сторінки;
бути зрозумілим без контексту навігації;
не дублювати заголовки інших сторінок;
не містити механічного переліку ключових слів.
Шаблон у layout.tsx зручний для спільного суфікса:
title: {
default: "Acme Docs",
template: "%s | Acme Docs",
}Після цього сторінка може задати:
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Налаштування маршрутизації",
description:
"Пояснення налаштування маршрутизації в Next.js.",
};У результаті title сторінки буде:
Налаштування маршрутизації | Acme Docsdescription повинен коротко пояснювати зміст сторінки. Не використовуйте один і той самий опис для всіх сторінок.
Для сторінок зі змінним вмістом метадані потрібно генерувати разом із даними сторінки. Перевірте, що під час помилки завантаження даних не формується метаопис на кшталт undefined, порожній рядок або внутрішнє повідомлення про помилку.
Канонічний URL повідомляє пошуковій системі, яка адреса є основною, якщо той самий або дуже схожий контент доступний за кількома адресами.
Перевірте canonical для:
сторінок із параметрами запиту;
пагінації;
фільтрів і сортування;
сторінок із локалізацією;
динамічних маршрутів;
сторінок, доступних через альтернативні шляхи.
Для сторінки з канонічним URL /guides/routing:
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Налаштування маршрутизації",
alternates: {
canonical: "/guides/routing",
},
};Перевірте результат у згенерованому HTML:
<link rel="canonical" href="https://example.com/guides/routing">Canonical має:
бути абсолютним у фінальному HTML;
використовувати правильний домен;
використовувати https;
вказувати на сторінку зі статусом 200;
не вести на URL із редиректом;
не вести на сторінку з noindex;
бути узгодженим із URL у sitemap.
Canonical не замінює редирект. Якщо адреса не повинна існувати, її краще перенаправити, а не лише додати canonical.
robots.txtУ Next.js App Router файл app/robots.ts генерує маршрут /robots.txt.
// app/robots.ts
import type { MetadataRoute } from "next";
export default function robots(): MetadataRoute.Robots {
const siteUrl =
process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000";
const isProduction =
process.env.NODE_ENV === "production";
return {
rules: {
userAgent: "*",
allow: isProduction ? "/" : undefined,
disallow: isProduction ? ["/api/", "/admin/"] : ["/"],
},
sitemap: `${siteUrl}/sitemap.xml`,
};
}У production перевірте:
GET /robots.txt повертає 200;
файл доступний без авторизації;
sitemap вказаний абсолютним URL;
публічні сторінки не заблоковані;
внутрішні API-маршрути не включені до індексації;
preview і staging не відкриті для пошукових роботів.
Важливо: robots.txt керує скануванням, але не є надійним способом приховати вже відому URL. Для сторінок, які не потрібно індексувати, використовуйте noindex і додатково обмежуйте доступ, якщо контент приватний.
Не блокуйте в robots.txt ресурси, необхідні для відображення сторінки. Пошуковий робот має отримувати CSS, JavaScript і зображення, якщо вони потрібні для коректного аналізу сторінки.
У Next.js App Router файл app/sitemap.ts генерує /sitemap.xml.
// app/sitemap.ts
import type { MetadataRoute } from "next";
const siteUrl =
process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000";
export default function sitemap(): MetadataRoute.Sitemap {
const pages = [
{
path: "/",
lastModified: new Date("2026-08-01"),
priority: 1,
},
{
path: "/guides",
lastModified: new Date("2026-08-01"),
priority: 0.8,
},
{
path: "/guides/routing",
lastModified: new Date("2026-07-28"),
priority: 0.7,
},
];
return pages.map((page) => ({
url: `${siteUrl}${page.path}`,
lastModified: page.lastModified,
changeFrequency: "weekly",
priority: page.priority,
}));
}До sitemap включайте лише URL, які:
мають статус 200;
є канонічними;
дозволені для індексації;
містять корисний контент;
доступні без авторизації.
Не додавайте:
URL із noindex;
сторінки помилок;
URL із параметрами фільтрації, якщо вони не є окремими сторінками;
сторінки редиректів;
дублікати;
внутрішні пошукові результати;
службові маршрути.
Якщо сторінки надходять із CMS або бази даних, sitemap має будуватися з того самого джерела, що й список опублікованих сторінок. Не включайте чернетки та видалені записи.
Після релізу перевірте:
GET /sitemap.xml повертає 200;
XML є валідним;
усі URL абсолютні;
URL відповідають production-домену;
дати lastModified не змінюються на кожен запит без реальної зміни контенту;
sitemap не містить staging-домен.
Не кожна сторінка застосунку повинна потрапляти до пошуку.
Зазвичай індексують:
головні сторінки;
документацію;
статті;
сторінки категорій;
публічні сторінки продуктів;
стабільні landing pages.
Зазвичай не індексують:
сторінки входу;
особистий кабінет;
кошик;
внутрішній пошук;
сторінки підтвердження;
службові сторінки;
дублікати з параметрами;
приватний або тимчасовий контент.
Для неіндексованого маршруту можна задати:
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Особистий кабінет",
robots: {
index: false,
follow: false,
},
};Перевірте, що noindex не потрапив у спільний layout для всіх дочірніх сторінок. Також переконайтеся, що production не використовує конфігурацію staging.
Зручно явно контролювати індексацію через змінну середовища:
import type { Metadata } from "next";
const isProduction =
process.env.NEXT_PUBLIC_SITE_ENV === "production";
export const metadata: Metadata = {
robots: {
index: isProduction,
follow: isProduction,
},
};Таку перевірку потрібно доповнити CI або smoke-тестом, щоб preview-деплой ніколи випадково не відкривався для індексації.
Для SEO важливо перевіряти не лише DOM після виконання JavaScript, а й HTML, який сервер повертає спочатку.
Для кожної важливої сторінки перевірте:
основний текст присутній у початковій відповіді;
є один зрозумілий <h1>;
заголовки мають логічну ієрархію;
посилання мають справжній href;
контент не з’являється лише після клієнтського кліку;
помилки завантаження не замінюють сторінку порожнім контейнером;
сторінка не залежить від window, localStorage або інших browser-only API для першого відображення основного контенту.
Для контентних сторінок перевагу слід надавати серверному рендерингу або статичній генерації. Клієнтські компоненти ("use client") допустимі, але основний індексований контент не повинен зникати без виконання браузерного JavaScript.
Перевіряйте відповідь безпосередньо:
curl -I https://example.com/guides/routing
curl https://example.com/guides/routingУ відповідях звертайте увагу на:
HTTP-статус;
content-type;
редиректи;
наявність заголовків і тексту сторінки;
випадкові повідомлення про помилки;
правильний домен у canonical і Open Graph URL.
Перед релізом складіть список основних URL і перевірте кожен із них.
Очікувано:
200 OKВикористовуйте постійний редирект:
301 Moved Permanentlyабо:
308 Permanent RedirectПеревірте, що:
немає ланцюжків редиректів;
немає циклічних редиректів;
canonical не веде через редирект;
sitemap не містить URL, які перенаправляють;
старі важливі URL мають відповідні нові адреси.
Сторінка повинна повертати 404 або 410, а не 200 із текстом «Сторінку не знайдено». Ситуація, коли всі невідомі URL повертають головну сторінку зі статусом 200, створює soft 404.
Окремо перевірте:
not-found.tsx;
помилки динамічних маршрутів;
неправильні локалі;
видалені записи з CMS;
URL із неправильним slug;
помилки upstream API.
Структуровані дані допомагають описати сторінку машиночитним форматом. Вони повинні відповідати фактичному вмісту сторінки.
Приклад для навчальної статті:
// app/guides/routing/page.tsx
const articleSchema = {
"@context": "https://schema.org",
"@type": "Article",
headline: "Налаштування маршрутизації в Next.js",
description:
"Практичний посібник із налаштування маршрутизації в Next.js.",
datePublished: "2026-07-20",
dateModified: "2026-07-28",
author: {
"@type": "Person",
name: "Команда Acme Docs",
},
publisher: {
"@type": "Organization",
name: "Acme Docs",
},
};
export default function RoutingGuidePage() {
return (
<main>
<article>
<h1>Налаштування маршрутизації в Next.js</h1>
<p>
У цьому матеріалі розглядається маршрутизація
в Next.js.
</p>
</article>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
// Символ "<" екранується, щоб дані не могли завершити script.
__html: JSON.stringify(articleSchema).replace(
/</g,
"\\u003c",
),
}}
/>
</main>
);
}Перевірте:
тип schema відповідає сторінці;
заголовок і опис збігаються з видимим контентом;
дата публікації реальна;
автор існує та вказаний на сторінці, якщо це потрібно;
немає вигаданих оцінок, відгуків або цін;
JSON-LD є валідним JSON;
однакові структуровані дані не дублюються без потреби.
Структуровані дані не гарантують розширений результат у пошуку. Вони лише дають пошуковій системі додатковий структурований опис сторінки.
Якщо застосунок має кілька мов, перевірте для кожної локалі:
lang у кореневому <html>;
перекладені title і description;
canonical на правильну мовну версію;
відсутність змішування мов у метаданих;
коректні URL у sitemap;
доступність усіх локалізованих сторінок;
редиректи між мовами.
Для альтернативних мов використовуйте alternates.languages лише тоді, коли відповідні сторінки справді існують:
import type { Metadata } from "next";
export const metadata: Metadata = {
alternates: {
canonical: "/uk/guides/routing",
languages: {
uk: "/uk/guides/routing",
en: "/en/guides/routing",
},
},
};Не оголошуйте мовну альтернативу для сторінки, яка повертає 404, має інший контент або перенаправляє на загальну сторінку.
Для важливих зображень перевірте:
наявність описового alt;
відсутність технічних назв файлів у alt;
розміри зображень;
доступність файлів без авторизації;
правильні URL у Open Graph;
наявність зображення розміром, придатним для соціального прев’ю;
відсутність битих шляхів після basePath або зміни домену.
alt має описувати зміст зображення. Для декоративних зображень використовуйте порожній alt, а не повторюйте заголовок сторінки.
До релізу перевірте основні публічні шаблони сторінок:
головну;
сторінку списку;
сторінку деталей;
статтю або документацію;
сторінку з динамічним маршрутом.
Зверніть увагу на:
час отримання першої відповіді;
розмір початкового HTML;
великі JavaScript-бандли;
зображення над областю першого екрана;
блокування рендерингу сторонніми скриптами;
стабільність layout під час завантаження;
помилки та довгі запити до API.
SEO-перевірка не повинна обмежуватися одним тестом Lighthouse. Порівнюйте результати для реальних сторінок і перевіряйте продуктивність після production build.
[ ] Визначено один основний домен.
[ ] Усі HTTP-запити перенаправляються на HTTPS.
[ ] Варіанти з www і без www узгоджені.
[ ] NEXT_PUBLIC_SITE_URL має production-значення.
[ ] Preview-домен не використовується в production-метаданих.
[ ] У кожної індексованої сторінки є унікальний title.
[ ] У кожної важливої сторінки є унікальний description.
[ ] metadataBase вказує на правильний домен.
[ ] Canonical URL коректний і абсолютний у фінальному HTML.
[ ] Open Graph-дані містять правильні title, description і image.
[ ] У сторінок із різним контентом немає однакових метаданих.
[ ] /robots.txt повертає 200.
[ ] Публічні маршрути не заблоковані.
[ ] API, адміністративні та службові маршрути не індексуються.
[ ] /sitemap.xml повертає 200.
[ ] Sitemap містить лише канонічні URL зі статусом 200.
[ ] У sitemap немає staging-адрес і чернеток.
[ ] Основний контент присутній у серверній відповіді.
[ ] На сторінці є один основний <h1>.
[ ] Заголовки мають логічну структуру.
[ ] Внутрішні посилання використовують справжні <a href>.
[ ] Важливі сторінки доступні через внутрішню навігацію.
[ ] Невідомі URL повертають справжній 404 або 410.
[ ] Structured data відповідає фактичному контенту.
[ ] JSON-LD валідний.
[ ] Дати, автори, назви та організація не вигадані.
[ ] Для локалізованих сторінок налаштовані коректні мовні альтернативи.
Одразу після публікації перевірте production-домен, а не локальне середовище.
Відкрийте кілька основних сторінок у браузері.
Перевірте HTML, отриманий без кешу браузера.
Виконайте перевірку заголовків і статусів через curl.
Перевірте /robots.txt.
Перевірте /sitemap.xml.
Перевірте canonical на головній, списковій і динамічній сторінках.
Перевірте сторінку з неіснуючим slug.
Перевірте стару URL після міграції маршруту.
Переконайтеся, що production не містить noindex.
Перевірте Open Graph-прев’ю для сторінки та зображення.
Перевірте структуровані дані після фактичного деплою.
Перегляньте логи на помилки рендерингу, редиректів і генерації sitemap.
У перші дні після релізу особливо важливо контролювати:
зростання кількості 404;
помилки 5xx;
сторінки, що несподівано стали noindex;
зникнення URL із sitemap;
зміну canonical на preview-домен;
збільшення кількості сторінок без внутрішніх посилань;
помилки завантаження даних для динамічних маршрутів.
noindexЦе часто трапляється, коли конфігурацію staging копіюють у production або перевіряють NODE_ENV у неправильному місці.
Рішення:
задавайте індексацію явно;
перевіряйте фінальний HTML після деплою;
додайте автоматичний smoke-тест для robots і noindex.
Sitemap повинна містити фінальні канонічні URL, а не старі адреси.
Це помилка спільного layout, який задає один canonical для всіх дочірніх сторінок. Кожна індексована сторінка повинна мати власний canonical або свідомо успадкований canonical.
Наприклад, sitemap містить https://example.com, а canonical формується через preview-домен. Причиною зазвичай є неправильний metadataBase або змінні середовища.
Якщо початковий HTML містить лише skeleton, а текст з’являється після запиту з браузера, пошуковий робот може обробити сторінку не так, як очікується. Основний контент має бути доступний під час серверного рендерингу або статичної генерації.
200Так виникає soft 404. Пошукова система отримує відповідь «успішно», хоча сторінки фактично не існує.
robots.txt використовується для приватностіЗаборона сканування не є контролем доступу. Секретні дані потрібно захищати автентифікацією та авторизацією, а не лише правилами для пошукових роботів.
Не додавайте schema лише заради потенційного розширеного результату. Дані в JSON-LD повинні бути правдивими та підтверджуватися вмістом сторінки.
Перед релізом Next.js-застосунку перевірте послідовність:
Визначте основний HTTPS-домен.
Налаштуйте metadataBase і метадані.
Переконайтеся, що canonical, sitemap і Open Graph використовують один домен.
Створіть коректні robots.txt і sitemap.xml.
Відокремте індексовані сторінки від службових.
Перевірте серверний HTML, заголовки, посилання та статуси.
Додайте лише релевантні структуровані дані.
Перевірте локалізацію, зображення та продуктивність.
Повторіть перевірку на production одразу після релізу.
Продовжуйте контролювати помилки, редиректи й індексацію після публікації.