Next.js Sitemap i robots.txt — automatyczna generacja z App Routera
Sitemap i robots.txt w Next.js App Router bez zewnętrznych paczek. Dynamiczne sitemaps, lastmod i jak nie wyeksponować staging przez przypadek.
Maciej Sala
Founder StriveLab
4 min czytaniaOpublikowano 10 kwietnia 2026 (Aktualizacja 25 maja 2026)
Dlaczego sitemap i robots.txt są ważne w Next.js?
.xml informuje wyszukiwarki o wszystkich stronach w serwisie — ich lokalizacji, dacie ostatniej modyfikacji i opcjonalnych wskazówkach, a plik kontroluje, które ścieżki crawlery mogą swobodnie odwiedzać. Oba generujesz natywnym konwencji plików Next.js. Choć żaden z nich nie gwarantuje indeksacji ani jej blokady, są fundamentem technicznego .
Natywna sitemap w Next.js App Router
Statyczna sitemap w app/sitemap.ts
Najprostszym sposobem jest eksport tablicy obiektów z pliku sitemap.ts:
Code
// app/sitemap.tsimport type { MetadataRoute } from 'next'export default function sitemap(): MetadataRoute.Sitemap { return [ { url: 'https://example.com', lastModified: new Date('2025-01-15'), changeFrequency: 'monthly', priority: 1, }, { url: 'https://example.com/uslugi', lastModified: new Date('2025-01-15'), changeFrequency: 'monthly', priority: 0.9, }, { url: 'https://example.com/blog', lastModified: new Date('2025-03-01'), changeFrequency: 'weekly', priority: 0.8, }, { url: 'https://example.com/kontakt', lastModified: new Date('2025-01-15'), changeFrequency: 'yearly', priority: 0.5, }, ]}
Next.js generuje /sitemap.xml automatycznie.
Pułapka: lastModified: new Date() dla stron statycznych. Użycie new Date() (aktualny czas buildu) dla stron, które rzadko się zmieniają, spowoduje, że przy każdym deployu Google zobaczy nową datę modyfikacji. Może to zmylić crawlera i zmarnować . Dla stron statycznych używaj konkretnej daty lub pomijaj pole lastModified całkowicie. Dla treści z bazy danych pobieraj faktyczne pole updatedAt z rekordu.
changeFrequency i priority Google oficjalnie deklaruje, że oba pola traktuje tylko jako wskazówki i w praktyce je ignoruje. Z kolei inne wyszukiwarki (Bing, Yandex) mogą je uwzględniać, więc warto je wypełniać, ale nie skupiaj się na ich optymalizacji, kosztem innych działań SEO.
Dynamiczna sitemap z wpisami z CMS lub bazy
Code
// app/sitemap.tsimport type { MetadataRoute } from 'next'import { db } from '@/lib/db'export default async function sitemap(): Promise<MetadataRoute.Sitemap> { const baseUrl = 'https://example.com' // Statyczne strony — konkretna data, nie new Date() const staticPages: MetadataRoute.Sitemap = [ { url: baseUrl, lastModified: new Date('2025-01-15'), changeFrequency: 'monthly', priority: 1, }, { url: `${baseUrl}/uslugi`, lastModified: new Date('2025-01-15'), changeFrequency: 'monthly', priority: 0.9, }, { url: `${baseUrl}/kontakt`, lastModified: new Date('2025-01-15'), changeFrequency: 'yearly', priority: 0.5, }, ] // Dynamiczne strony — posty blogowe const posts = await db.post.findMany({ where: { published: true }, select: { slug: true, updatedAt: true }, orderBy: { updatedAt: 'desc' }, }) const blogPages: MetadataRoute.Sitemap = posts.map((post) => ({ url: `${baseUrl}/blog/${post.slug}`, lastModified: post.updatedAt, // faktyczna data z bazy — poprawne changeFrequency: 'monthly' as const, priority: 0.7, })) return [...staticPages, ...blogPages]}
Wielojęzyczna sitemap z hreflang
Natywne API obsługuje pole alternates, służy do deklarowania wersji językowych strony, co Google wymaga przy implementacji hreflang:
next-sitemap: kiedy natywne API Next.js nie wystarczy?
Biblioteka next-sitemap oferuje dodatkowe funkcje, czyli automatyczne wykrywanie statycznie wygenerowanych stron po buildzie, wielojęzyczne sitemaps z hreflang, server-side sitemap regeneration i konfigurację per-ścieżka.
Dla większości projektów, zwłaszcza tych z przewidywalną strukturą, natywne API Next.js jest w zupełności wystarczające, prostsze i nie wprowadza dodatkowych zależności. Sięgnij po next-sitemap tylko w wyjątkowych sytuacjach, gdy masz bardzo duży, nietypowy serwis, gdzie automatyczne wykrywanie stron i zaawansowane transformacje oszczędzą Ci mnóstwa pracy manualnej.
Weryfikacja sitemap i robots.txt w Google Search Console
Nie. Sitemap pomaga wyszukiwarkom odkrywać adresy i daty zmian, ale nie gwarantuje indeksacji ani wysokiej pozycji. Strona nadal musi być dostępna i wartościowa.
Czy robots.txt blokuje indeksację?
Robots.txt kontroluje crawling, a nie zawsze samą indeksację. Jeśli chcesz usunąć stronę z indeksu, zwykle potrzebujesz noindex lub usunięcia adresu, a nie tylko blokady w robots.txt.
Kiedy użyć next-sitemap zamiast natywnego app/sitemap.ts?
Natywne API App Routera wystarcza w wielu projektach. next-sitemap może być wygodny przy bardziej rozbudowanych konfiguracjach, starszych strukturach lub gotowym workflow opartym o ten pakiet.
Czy sitemap jest wymagana do indeksowania?
Nie, Google może indeksować strony bez sitemap (przez linki wewnętrzne i zewnętrzne), ale sitemap przyspiesza odkrywanie nowych stron i informuje o zmianach. Jest to szczególnie w dużych serwisach lub przy braku zewnętrznych linków.
Jak często Google czyta sitemap?
Google sprawdza sitemap okresowo i nie ma jakiejś z góry ustalonej częstotliwości. Możesz wymusić ponowne sprawdzenie w Search Console (przycisk „Prześlij ponownie") i czekać na wynik.
Czy `changefreq` i `priority` wpływają na pozycje w Google?
Nie, Google wskazuje, że oba pola traktuje tylko jako wskazówki i w praktyce je ignoruje. Warto je wypełniać dla innych wyszukiwarek (Bing, Yandex), które mogą je respektować, ale nie mają żadnego wpływu na wyniki w Google - oczywiście, jeśli przyjmujemy, że wszystko co twierdzi Google odpowiada rzeczywistości.
Czy blokowanie botów AI w robots.txt jest skuteczne?
Działa dla botów, które respektują plik robots.txt. Zarówno GPTBot (OpenAI), jak i Google-Extended (Gemini) deklarują, że to robią. Jednak robots.txt to tylko prośba, a nie techniczna zapora — złośliwy lub źle skonfigurowany crawler może zignorować te dyrektywy. Jest to jednak obecnie standardowa metoda komunikowania swoich preferencji botom AI.
O autorze
Maciej Sala
Maciej Sala — Product Manager i Frontend Developer z bogatym doświadczeniem w marketingu internetowym oraz SEO. Na co dzień pracuje z Reactem, Next.js i TypeScriptem, a ostatnio także z Astro i narzędziami do automatyzacji procesów AI. Sprawnie łączy perspektywę produktową z praktycznym podejściem do kodu. Przez kilka lat był związany z branżą gier wideo jako project manager i game designer. Absolwent historii na Uniwersytecie Jagiellońskim oraz studiów podyplomowych z marketingu internetowego na AGH w Krakowie. Po godzinach trenuje na siłowni, maluje figurki i rozwijam własne projekty.
Masz Astro, masz też headless CMS Payload albo Sanity i masz problem: po każdej publikacji albo ręcznie dopisujesz URL-e do sitemapy, albo liczysz, że Googlebot sam wpadnie na nowy artykuł. Pierwsze nie skaluje się powyżej kilkunastu podstron. Drugie zostawia odkrywanie URL-i przypadkowi. Pokażę architekturę i kod w dwóch wariantach: prostszym @astrojs/sitemap z serialize oraz z pełną kontrolą własny endpoint XML . Obie wersje generują statyczny plik na buildzie, więc serwer nie odpytuje CMS-a przy każdym wejściu Googlebota.
Maciej Sala
Founder StriveLab
Trudno wyobrazić sobie współczesną analitykę bez Google Search Console GSC , czyli podstawowego narzędzia pokazującego dane bezpośrednio z Google Search. PageSpeed Insights mierzy wydajność, Ahrefs śledzi backlinki, ale GSC pokazuje całą paletę danych ale też problemów/błędów dotyczących strony internetowej. Przykładowo, które strony są zaindeksowane, jakie błędy crawlowania występują, na jakie frazy rankujesz i jakie wyniki Core Web Vitals Dane Core Web Vitals w GSC pochodzą z Chrome UX Report, czyli realnych wizyt użytkowników, a nie z pojedynczego testu laboratoryjnego Lighthouse. mają istniejący użytkownicy.
Maciej Sala
Founder StriveLab
Hreflang i link kanoniczny rozwiązują dwa różne problemy wielojęzycznego SEO: właściwy język wyniku i właściwy adres do indeksowania. W Next.js App Router oba mechanizmy da się generować spójnie przez Metadata API , bez ręcznego utrzymywania tagów w każdej podstronie.