SEO para Next.js
Como tornar um site Next.js rastreável, indexável e ranqueável — os dois roteadores, modos de renderização (SSG/SSR/ISR/Server Components), a API de Metadados do App Router, sitemap.ts, robots.ts, next/image, next/link e os erros que silenciosamente quebram isso.
Idiomas
O Next.js resolve os problemas mais difíceis de SEO em JavaScript por padrão — se você usá-lo corretamente. Os Server Components do App Router e SSG/ISR colocam o conteúdo no HTML, então não há atraso na fila de renderização; a API de Metadados nativa resolve títulos, canônicos e Open Graph no servidor; sitemap.ts e robots.ts são convenções de arquivo. O framework fornece a infraestrutura, mas não escreve nenhuma das suas tags. As falhas são previsíveis: metadataBase ausente, sem prioridade na imagem LCP, metadados exportados de um Client Component (silenciosamente não faz nada) e visualizações 404 retornando 200.
TL;DR — Next.js é um dos melhores frameworks para SEO quando você o usa corretamente. Construa suas páginas no servidor ou no momento da compilação (não inteiramente no navegador), defina um título, descrição e canônico exclusivos em cada página, e use os componentes integrados
next/imageenext/link. O Next.js fornece todas as ferramentas — mas não escreve suas tags de SEO por você.
O que é SEO em Next.js
Next.js é um framework popular construído sobre React para criar sites e aplicativos web. Como é React por baixo dos panos, grande parte da página pode ser construída com JavaScript — e é aí que surgem as questões de SEO. SEO em Next.js é simplesmente a prática de garantir que os mecanismos de busca possam rastrear, renderizar e indexar um site Next.js, e usar os recursos integrados do framework para fazer isso bem.
A boa notícia: o Next.js pode construir suas páginas antecipadamente ou no servidor, então os mecanismos de busca recebem o HTML final imediatamente. Isso evita o maior risco com sites JavaScript — conteúdo que só aparece depois que os scripts são executados. (Para uma visão mais ampla, veja SEO em JavaScript.)
A grande decisão: onde a página é construída
Quando alguém — ou o Googlebot — solicita uma página, de onde vem o HTML final? O Next.js oferece algumas opções:
- No momento da compilação (Estático / SSG) — a página é construída em um arquivo HTML simples antecipadamente. Rápido, e os mecanismos de busca recebem tudo imediatamente.
- No servidor, por solicitação (SSR) — o servidor constrói a página completa a cada vez. Também é amigável para busca e sempre atualizado.
- Uma mistura (ISR) — páginas estáticas que são atualizadas em um temporizador. Um bom padrão para a maioria dos conteúdos.
- No navegador (Client-Side / CSR) — o servidor envia um shell quase vazio e o JavaScript o preenche. Este é o arriscado para SEO; evite-o para o seu conteúdo principal.
O App Router moderno usa Server Components por padrão, o que significa que seu conteúdo acaba no HTML automaticamente — um ótimo ponto de partida para SEO.
A lista de verificação simples
- Dê a cada página um título e descrição exclusivos.
- Defina uma URL canônica em cada página.
- Use o componente
next/imagepara imagens (ele impede que a página fique pulando enquanto as imagens carregam e as torna menores). - Use
next/linkpara links internos (ele cria links reais que o Google pode seguir). - Não coloque seu conteúdo principal atrás de renderização no lado do cliente.
- Crie um sitemap e um robots.txt (o Next.js tem maneiras simples baseadas em arquivos para fazer ambos). Evidence for this claim Next.js App Router supports special metadata files for sitemap and robots output. Scope: Next.js App Router file conventions. Confidence: high · Verified: Next.js: Metadata files
O que as pessoas entendem errado
“O Next.js lida com SEO automaticamente.” Não — não nas partes que importam. O Next.js fornece a maquinaria (um sistema de metadados, convenções de sitemap e robots, um componente de imagem), mas você ainda precisa escrever seus títulos, descrições e canônicos você mesmo. Evidence for this claim Next.js provides metadata APIs, but developers supply page-specific metadata values. Scope: Next.js App Router metadata and generateMetadata APIs. Confidence: high · Verified: Next.js: Metadata and OG images Cada página precisa dos seus. Um site onde cada página compartilha um título, ou não tem canônico, é a maneira mais comum de uma compilação Next.js ter desempenho abaixo do esperado.
Quer a versão mais aprofundada — os dois routers, a Metadata API, metadataBase, o truque
de imagem LCP e os erros que quebram a indexação silenciosamente? Mude para a aba Avançado.
TL;DR — O Next.js resolve os problemas mais difíceis de SEO em JavaScript por padrão quando você o usa corretamente. O App Router usa Server Components por padrão e suporta SSG/SSR/ISR — todos os quais enviam HTML renderizado, então não há atraso na fila de renderização. Defina metadados com a Metadata API nativa (
metadata/generateMetadata), e lembre-se demetadataBaseou seus canônicos e imagens OG ficarão relativos. Useapp/sitemap.tseapp/robots.ts, pré-construa rotas dinâmicas comgenerateStaticParams, definapriorityna imagem LCP e mantenha os links como âncoras reais denext/link. O Pages Router também é capaz de SEO vianext/head. As falhas são previsíveis — e a maioria delas não é culpa do Next.js, é sua.
Onde o Next.js se encaixa
Next.js é um framework React, então tudo em SEO de JavaScript se aplica. O que faz valer a pena ter um guia próprio é que o Next.js oferece respostas de primeira linha para a maioria dos problemas de SEO em JS: renderização no servidor, geração estática, um sistema de metadados e convenções de sitemap/robots. A parte difícil não é se o Google consegue ler — o Google renderiza JavaScript há anos — é escolher o modo de renderização certo e não deixar o básico de SEO sem conexão. Este é um caso especializado de SEO de CMS headless: o CMS quase não importa, as decisões de renderização do frontend decidem tudo.
Uma estrutura para manter em mente: “este é um site Next.js” não diz como qualquer URL individual é entregue. O modo de renderização, o cache e os limites de Server/Client Components são definidos por rota (às vezes por segmento) — um projeto pode misturar uma página de marketing estática, uma página de produto com SSR e um dashboard com Client Components. Não extrapole o comportamento de uma rota para “todo o app”; teste a URL específica.
Dois roteadores, dois conjuntos de mecânicas
O Next.js tem dois roteadores, e eles lidam com SEO de maneiras diferentes:
- Pages Router (o modelo mais antigo) — busca de dados via
getStaticProps/getServerSideProps; metadados via<Head>denext/head(ou o pacotenext-seo); sem Server Components. - App Router (v13+, a abordagem atual e recomendada) — React Server Components
por padrão; a Metadata API nativa (exportação
metadata/generateMetadata); convenções de arquivo paraapp/sitemap.tseapp/robots.ts;generateStaticParamspara rotas dinâmicas. Evidence for this claim The App Router uses Server Components and supports generateStaticParams plus metadata file conventions. Scope: Current Next.js App Router behavior; route rendering can become dynamic based on APIs used. Confidence: high · Verified: Next.js: Server and Client Components Next.js: generateStaticParams
Ambos podem ranquear bem. O App Router oferece um sistema de metadados mais limpo e integrado (sem
manipulação de next/head) e Server Components prontos para uso, por isso eu o escolheria em um
novo projeto. Mas “App Router ou você não consegue fazer SEO” é um mito — muitos sites com Pages Router
ranqueiam bem.
Modos de renderização e o que cada um significa para SEO
Como o Google lida com JavaScript é um pipeline de três fases — rastreamento, depois uma onda de renderização adiada, e então indexação. “Todas as páginas com código de status HTTP 200 são enviadas para a fila de renderização.” Todo o jogo no Next.js é escolher um modo que coloque seu conteúdo no HTML antes dessa onda de renderização, para que não haja nada para esperar. Evidence for this claim Google crawls, renders, and indexes JavaScript pages, and successful pages can enter the rendering queue. Scope: Google Search processing, not a promise that a URL will be indexed. Confidence: high · Verified: Google: JavaScript SEO basics
- Static Site Generation (SSG) — páginas pré-renderizadas no momento do build. O HTML fica
imediatamente disponível, sem risco de fila de renderização. Melhor para conteúdo que não muda
a cada minuto.
generateStaticParams()(App Router) /getStaticPaths()(Pages Router) decide quais rotas dinâmicas são pré-construídas. - Incremental Static Regeneration (ISR) — páginas estáticas que revalidam após um
intervalo definido (
export const revalidate = 3600). Os rastreadores recebem HTML estático com TTFB baixo e o conteúdo permanece atualizado. Um padrão forte — com uma armadilha: após o intervalo expirar, a próxima solicitação (possivelmente Googlebot) ainda recebe a página desatualizada; a versão atualizada é servida na solicitação seguinte. Para dados realmente voláteis (preços, estoque), SSR é mais seguro. - Server-Side Rendering (SSR) — HTML renderizado por solicitação. Os rastreadores recebem HTML
totalmente renderizado imediatamente; o trade-off é a latência do servidor, então observe TTFB e LCP.
export const dynamic = 'force-dynamic'ou o uso de APIs em tempo de solicitação (cookies, headers) opta por uma rota em SSR. - React Server Components (padrão do App Router) — renderizam no servidor e enviam HTML;
nenhum JavaScript é enviado para o próprio componente. O conteúdo está na resposta inicial, sem
lacuna de hidratação. Este é o melhor padrão para SEO. A interatividade vive em Client Components
marcados com
'use client'. - Client-Side Rendering (CSR) — renderizado inteiramente no navegador. O Googlebot pode indexar
após a onda de renderização (mediana de ~10 segundos, mas o percentil 90 se estende a
horas), e outros rastreadores — Bingbot, bots de IA, bots de pré-visualização social — podem receber uma página
vazia. No App Router, CSR é opt-in (
'use client'); no Pages Router, evite buscar conteúdo principal emuseEffect. Não use para conteúdo que você quer ranquear.
Um lembrete ao qual sempre volto: “Googlebot can render it” não é o mesmo que “you should make Googlebot render it.” Renderizar é caro, adiado e não é universal entre rastreadores.
A Metadata API (App Router)
A Metadata API é somente para Server Components — os metadados são resolvidos no servidor antes de
a página renderizar, então eles chegam no HTML inicial. Exporte metadata de layout.js ou
page.js:
export const metadata: Metadata = {
title: 'My Page',
description: 'Page description',
}Ou, quando as tags dependem de dados buscados, use generateMetadata():
export async function generateMetadata({ params }) {
const post = await getPost(params.slug)
return { title: post.title, description: post.description }
}Os campos que importam para SEO:
title— suporta uma string, um template ('%s | Brand'), um padrão e uma substituição absoluta. Defina o template uma vez no layout raiz e os títulos por página o herdam.description,alternates.canonical(a maneira correta de definir uma canonical no App Router),openGraph(as imagens devem resolver para URLs absolutas),twitter(também usado nas pré-visualizações do LinkedIn e do Slack) erobots(index/follow além de diretivas específicas do googleBot, como max-snippet, max-image-preview).metadataBase— obrigatório para que as URLs canônicas e de imagem OG sejam resolvidas corretamente. Esquecer isso é o erro de metadados mais comum no Next.js: URLs relativas vazam para suas tags canônicas e Open Graph, quebrando pré-visualizações sociais e confundindo os sinais canônicos.
Um exemplo de template de título:
// app/layout.tsx
export const metadata: Metadata = {
metadataBase: new URL('https://example.com'),
title: { template: '%s | Brand Name', default: 'Brand Name' },
}
// app/blog/page.tsx
export const metadata: Metadata = { title: 'My Blog Post' }
// Output: <title>My Blog Post | Brand Name</title>Duas pegadinhas. Primeiro, os metadados são mesclados superficialmente do layout para a página — um
objeto aninhado como openGraph definido em um segmento filho substitui o do pai por completo, então
um openGraph: { title: 'Home' } no nível da página descarta silenciosamente qualquer openGraph.images definido no
layout. Segundo — e esta pega muita gente — metadata só funciona em Server
Components. Exporte de um arquivo 'use client' e ele silenciosamente não faz nada.
Streaming metadata. Para páginas renderizadas dinamicamente, o generateMetadata pode transmitir os metadados após o HTML inicial. O Googlebot executa JavaScript e inspeciona o DOM completo, então metadados transmitidos funcionam para o Google. Mas o Next.js detecta “bots limitados a HTML” — Bingbot, Twitterbot, Slackbot, facebookexternalhit — e envia a eles metadados bloqueantes no <head>. Conforme a documentação do Next.js, “streaming metadata is disabled for bots and crawlers that expect metadata to be in the <head> tag.” (tradução) «o streaming de metadados é desativado para bots e rastreadores que esperam metadados na tag <head>». Isso é automático; nenhuma configuração é necessária. É um detalhe que quase nenhum guia concorrente cobre, e é por isso que o streaming de metadados não é um risco para os bots que não podem esperar por ele. Páginas pré-renderizadas são um caso completamente diferente — os metadados ali são resolvidos no momento da compilação, então não há stream com o qual se preocupar. Esse comportamento é específico da versão (atual a partir do Next.js 16.2.10); verifique novamente a documentação do generateMetadata ao atualizar. E como os caminhos de entrega diferem por ponto de entrada, verifique os metadados de duas maneiras, não apenas uma: uma solicitação direta/de produção (curl -I ou View Source) e uma navegação no lado do cliente para a mesma rota — o head pode ser atualizado de forma diferente entre as duas.
Metadados com next/head (Pages Router)
No Pages Router, os metadados ficam em <Head> de next/head:
import Head from 'next/head'
export default function Page() {
return (
<>
<Head>
<title>My Page | Brand</title>
<meta name="description" content="Description" />
<link rel="canonical" href="https://example.com/my-page" />
</Head>
{/* page content */}
</>
)
}Defina title e description por página (não apenas em _app.js) e coloque uma canonical em todas as páginas, incluindo variantes paginadas. O pacote next-seo padroniza isso com um componente <NextSeo> e auxiliares de dados estruturados. Migrar para o App Router significa principalmente trocar next/head e next-seo pelo export nativo metadata.
Você precisa do pacote next-seo? É um plugin de terceiros (não faz parte do Next.js em si) — mantido ativamente, na v7.2,0 no momento em que este texto foi escrito, não arquivado. A própria documentação é explícita sobre onde ele se encaixa: para meta tags padrão no App Router, o README do pacote recomenda usar o export generateMetadata/metadata nativo do Next.js em vez de <NextSeo>; no Pages Router, <NextSeo> ainda é uma camada de conveniência razoável sobre next/head. O único caso de uso do App Router que o pacote ainda cobre são seus componentes auxiliares de JSON-LD (ArticleJsonLd, FAQPageJsonLd, etc. com useAppDir), que algumas equipes preferem em vez de criar manualmente <script type="application/ld+json">. Resumindo: em uma nova compilação do App Router, use primeiro a API de Metadados nativa — o pacote é opcional, não um requisito, e os próprios mantenedores dizem isso.
Sitemaps
No App Router, app/sitemap.ts é uma convenção de arquivo que gera /sitemap.xml:
import type { MetadataRoute } from 'next'
export default function sitemap(): MetadataRoute.Sitemap {
return [
{ url: 'https://acme.com', lastModified: new Date(), priority: 1 },
{ url: 'https://acme.com/blog', lastModified: new Date(), priority: 0.8 },
]
}Para sites grandes, generateSitemaps() divide em vários arquivos (o limite do Google é de 50 000 URLs por sitemap), cada um servido em /.../sitemap/[id].xml. A saída do sitemap também suporta sitemaps de imagem, sitemaps de vídeo e alternates.languages localizados. No Pages Router, use next-sitemap ou gere pages/sitemap.xml.js com getServerSideProps.
robots.txt
app/robots.ts gera seu arquivo robots programaticamente:
export default function robots(): MetadataRoute.Robots {
return {
rules: [{ userAgent: '*', allow: '/', disallow: '/private/' }],
sitemap: 'https://acme.com/sitemap.xml',
}
}Regras por user-agent e múltiplos sitemaps são suportados. O Pages Router usa um public/robots.txt estático. A regra que você não pode errar em nenhum dos roteadores: nunca desautorize seu JavaScript ou CSS — o Google não renderiza a partir de arquivos bloqueados, e em um framework JS isso pode esvaziar a página inteira.
next/image e Core Web Vitals
next/image é uma das razões mais fortes para usar o framework para SEO. Ele carrega preguiçosamente imagens abaixo da dobra, exige width/height (ou fill) para reservar espaço e evitar mudança de layout / CLS, serve WebP/AVIF automaticamente e emite um srcset adequado a partir da prop sizes. A otimização mais importante de CWV é a prop priority na sua imagem hero / acima da dobra, que a pré-carrega para um LCP mais rápido:
<Image src="/hero.jpg" width={1200} height={630} priority alt="Hero" />Esquecer o priority na imagem LCP é o erro mais comum de CWV em Next.js — e os problemas de CWV são generalizados em sites Next.js reais (veja a aba Stats para os dados da Salt Agency). O alt é obrigatório: vazio para imagens decorativas, descritivo para imagens de conteúdo.
next/link e links internos
O next/link renderiza âncoras <a href> padrão no HTML, então o Google as segue normalmente, e ele adiciona navegação no lado do cliente além de pré-busca em segundo plano de links visíveis na viewport em produção. A regra de SEO é simples: use next/link para links internos e nunca substitua por um manipulador onClick ou navegação JavaScript que não produza uma âncora real — esses links não são rastreáveis. Use prefetch={false} em links de baixo valor para economizar largura de banda, se necessário.
Rotas dinâmicas e generateStaticParams
generateStaticParams() informa ao Next.js quais rotas dinâmicas devem ser pré-renderizadas no momento do build:
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await getPosts()
return posts.map((post) => ({ slug: post.slug }))
}Páginas construídas dessa forma são HTML totalmente estático — o melhor para SEO. Sem isso, as rotas dinâmicas são renderizadas sob demanda (SSR) por padrão, o que é aceitável, mas reintroduz latência do servidor. Combine com revalidate (ISR) para conteúdo que é atualizado regularmente. Certifique-se de que todas as URLs dinâmicas importantes estejam em generateStaticParams para que nada fique esperando na fila de renderização.
Dados estruturados (JSON-LD)
A Metadata API não tem campo de dados estruturados — você injeta JSON-LD como um <script> em um Server Component, o que o mantém no HTML renderizado no servidor sem custo no bundle do cliente:
const jsonLd = { '@context': 'https://schema.org', '@type': 'Article', /* … */ }
return <script type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />Article/BlogPosting, BreadcrumbList, Product e FAQPage são os tipos usuais. Valide com o Rich Results Test após qualquer alteração de renderização.
Erros comuns de SEO em Next.js
Baseado em auditorias reais e nos padrões acima:
- Canônicas ausentes ou relativas — frequentemente por um
metadataBaseesquecido, que também quebra as URLs de imagem OG. - Sem
priorityna imagem LCP — a maior falha de CWV. - Views de 404 retornando
200— use onotFound()embutido para retornar um status real; soft 404s são comuns em sites Next.js. metadataexportado de um Client Component — silenciosamente não faz nada; é apenas para Server Component.- CSR para conteúdo principal — buscar conteúdo crítico em
useEffectsignifica que crawlers não-Google recebem páginas vazias. - Roteamento por hash (
#) em vez da History API — essas views não são rastreáveis separadamente. - Não exportar
generateStaticParams— rotas dinâmicas são renderizadas sob demanda em vez de serem pré-construídas. openGraphsobrescrito pela herança de layout — segmentos filhos substituem, não mesclam.- JS/CSS bloqueados em robots.txt ou via Content Security Policy que impede o Chrome headless do Googlebot de carregar scripts — teste com URL Inspection.
Notas de implantação
Next.js é desenvolvido pela Vercel; hospedar lá oferece integração estreita (CDN de borda para páginas estáticas e ISR, bom TTFB), mas não é obrigatório. Defina redirecionamentos permanentes em redirects() no next.config.js (retorna 308, ou 301 com permanent: true) para sinalização confiável aos crawlers, defina cabeçalhos de segurança e cache via headers() e use cabeçalhos de resposta X-Robots-Tag para regras de noindex baseadas em caminho quando os metadados robots por página forem inconvenientes.
O que verificar onde. Estado de cache, códigos de status, redirecionamentos e metadados transmitidos não aparecem todos no mesmo teste — uma rota pode parecer correta em uma verificação e ainda estar quebrada em outra:
| Verificação | Onde procurar | Por que pode diferir do que você vê renderizado |
|---|---|---|
| Idade do cache/revalidação | Cabeçalhos de resposta em uma solicitação direta (curl -I) | O ISR pode servir uma página obsoleta na solicitação logo após a janela expirar |
| Status HTTP direto | curl -I na URL de produção, não na UI renderizada | Uma view de “não encontrado” sem notFound() ainda retorna 200 |
| Comportamento de redirecionamento | O contexto real que o aciona — redirect() em uma Server Action, um Route Handler, vs. um onClick no cliente | O código de status e o caminho de resposta diferem pelo contexto de invocação, não apenas pelo destino |
| Metadados transmitidos | Solicitação direta e navegação no lado do cliente para a mesma rota | Clientes comuns podem obter metadados transmitidos; bots limitados a HTML obtêm metadados de bloqueio; os dois caminhos não são idênticos |
| Transições no lado do cliente | Navegue no aplicativo e verifique novamente o <head> | Uma rota correta no primeiro carregamento pode divergir após uma transição no cliente |
Nada disso é garantido pelo framework — o Next.js fornece os mecanismos
(redirects(), notFound(), revalidação, streaming), mas chaves de cache, invalidação,
estado de preview e configuração de implantação ainda são de sua responsabilidade acertar e
testar em produção, não apenas localmente.
Uma última nota sobre renderização dinâmica — servir HTML pré-renderizado para bots e JavaScript para usuários. O Google a descontinuou como recomendação: “dynamic rendering was a workaround and not a long-term solution.” (tradução) «a renderização dinâmica era uma solução alternativa e não uma solução de longo prazo.» Você não precisa dela no Next.js de qualquer forma — SSR, SSG, ISR e Server Components colocam todo o conteúdo no HTML nativamente. Mencione-a para reconhecê-la em uma auditoria; não construa com base nela.
O caminho feliz: App Router + Server Components + ISR + a Metadata API (com
metadataBase) + next/image com priority. Acertando isso, a maior parte do SEO do Next.js está
resolvida.
Resumo de IA
Uma visão condensada da versão Avançada:
- O Next.js resolve a maioria dos problemas de SEO em JavaScript por padrão — se você escolher o modo de renderização certo e configurar o básico. O framework fornece a infraestrutura; ele não escreve nenhuma das suas tags.
- Dois roteadores: App Router (v13+, recomendado) usa Server Components e a Metadata API nativa; Pages Router usa
next/head/next-seo. Ambos podem ranquear. - Modos de renderização: SSG e Server Components são o melhor padrão (conteúdo no HTML, sem atraso na fila de renderização). ISR é um meio-termo forte, mas tem uma armadilha de conteúdo obsoleto na primeira solicitação após a revalidação. SSR para dados voláteis. CSR é arriscado — crawlers que não são do Google podem receber uma página vazia.
- Metadata API (App Router): exportação
metadataougenerateMetadata(), somente em Server Component.metadataBaseé obrigatório ou canonicals e imagens OG ficam relativas.openGraphem um segmento filho substitui o do pai; metadata em um arquivo'use client'não faz nada. - Metadata em streaming funciona para o Google, mas o Next.js envia metadata bloqueante para bots com limitação de HTML (Bingbot, Twitterbot, Slackbot, facebookexternalhit) automaticamente.
- Convenções de arquivo:
app/sitemap.ts(comgenerateSitemaps()para mais de 50 mil URLs) eapp/robots.ts. Nunca bloqueie.js/.css. next/imageprevine CLS, serve WebP/AVIF; definapriorityna imagem LCP — a maior vitória de CWV.next/linkrenderiza âncoras<a href>reais e rastreáveis e faz prefetch.generateStaticParamspré-constroi rotas dinâmicas; sem ele, elas renderizam sob demanda.- JSON-LD é injetado como um
<script>em um Server Component (sem campo na Metadata API). - O pacote
next-seoé opcional, não obrigatório. É um software de terceiros ativamente mantido (v7.2,0, não arquivado), e sua própria documentação recomenda a exportaçãogenerateMetadata/metadataintegrada para meta tags do App Router —<NextSeo>continua útil principalmente no Pages Router, ou para seus componentes auxiliares de JSON-LD. - O modo de renderização é definido por rota, não por projeto — não assuma o comportamento de uma URL com base em outra; teste a rota específica (solicitação direta e navegação do cliente).
- Principais erros: falta de
metadataBase, sempriorityno LCP, 404 retornando200(usenotFound()),metadataem um Client Component, conteúdo principal em CSR. - Renderização dinâmica está obsoleta — você não precisa dela; SSR/SSG/ISR/Server Components cobrem isso.
Documentação oficial
Documentação de fonte primária do Next.js e dos mecanismos de busca.
Next.js
- Metadata e imagens OG — o sistema de metadata do App Router,
metadataBasee geração de imagens OG. - Referência da API generateMetadata —
metadataestático vs.generateMetadata, metadata em streaming e a lista de bots com limitação de HTML. - Convenção de arquivo sitemap.xml —
app/sitemap.ts,generateSitemaps(), sitemaps de imagem/vídeo/localizados. - Convenção de arquivo robots.txt —
app/robots.ts, regras por user-agent e múltiplos sitemaps. - Aprenda: SEO — o caminho de aprendizado de SEO do próprio Next.js (introdutório; parcialmente anterior ao App Router).
- Entenda os fundamentos de SEO em JavaScript — o pipeline de rastreamento → renderização → indexação, a fila de renderização com status 200, soft 404s em SPAs, canonicals e a History API.
- Renderização dinâmica (solução obsoleta) — por que o Google a tornou obsoleta e o que usar em vez disso (SSR, renderização estática, hidratação).
- Guia aprofundado de como o Google Search funciona — onde a renderização se encaixa no fluxo de rastreamento → indexação → exibição.
Bing / Microsoft
- IndexNow / indexnow.org — o protocolo push para conectar a um evento de publicação/revalidação do Next.js.
Citações da fonte
Declarações oficiais do Google, Next.js e representantes do Google. Cada link é um link profundo que salta para a passagem citada na página de origem.
Google — como as páginas com JavaScript são processadas
- “All pages with a 200 HTTP status code are sent to the rendering queue, no matter whether JavaScript is present on the page.” (tradução) «Todas as páginas com código de status HTTP 200 são enviadas para a fila de renderização, independentemente de haver JavaScript na página.» — Documentação do Google Search Central. Ir para a citação
Google — a renderização dinâmica está obsoleta
- “Dynamic rendering was a workaround and not a long-term solution for problems with JavaScript-generated content in search engines.” (tradução) «A renderização dinâmica era uma solução alternativa e não uma solução de longo prazo para problemas com conteúdo gerado por JavaScript nos mecanismos de busca.» — Documentação do Google Search Central. Ir para a citação
- “…creates additional complexities and resource requirements.” (tradução) «…cria complexidades adicionais e requisitos de recursos.» — Documentação do Google Search Central. Ir para a citação
Next.js — streaming de metadados e bots com HTML limitado
- “Streaming metadata is disabled for bots and crawlers that expect metadata to be in the
<head>tag (e.g. Twitterbot, Slackbot, Bingbot).” (tradução) «O streaming de metadados é desativado para bots e rastreadores que esperam metadados na tag<head>(por exemplo, Twitterbot, Slackbot, Bingbot).» — Documentação do Next.js,generateMetadata. Ir para a citação
John Mueller, Google (via cobertura do Search Engine Journal)
- Sobre o papel crescente do JavaScript em SEO: “You’re going to run into significantly more JavaScript over the next years than in the 2-ish decades in SEO before. If you’re keen on technical SEO, then past HTML you’re going to need to understand JS more and more.” (tradução) «Você vai encontrar significativamente mais JavaScript nos próximos anos do que nas cerca de duas décadas anteriores em SEO. Se você é interessado em SEO técnico, além do HTML, você vai precisar entender JS cada vez mais.» Leia a cobertura
Lista de verificação de SEO para Next.js
Uma passagem rápida para confirmar que um site Next.js é rastreável, indexável e rápido:
- O conteúdo principal é renderizado em HTML na primeira solicitação (Server Components / SSG / SSR / ISR) — não apenas após JavaScript no lado do cliente.
- Nenhuma página importante depende de CSR para seu conteúdo principal.
- Cada página tem um título e descrição únicos (use um
templatede título no layout raiz). -
metadataBaseestá definido no layout raiz (App Router) para que canônicos e imagens OG sejam absolutos. - Um canônico é definido por página via
alternates.canonical(App Router) ou<link rel="canonical">(Pages Router) — não um único canônico compartilhado da página inicial. -
metadataé exportado apenas de Server Components, nunca de um arquivo'use client'. -
generateStaticParamscobre todas as rotas dinâmicas importantes. -
app/sitemap.ts(ounext-sitemap) gera um sitemap atual;generateSitemaps()divide sites com mais de 50 mil URLs. -
app/robots.ts/public/robots.txtexiste e não bloqueia.jsou.css. - Imagens usam
next/imagecomwidth/heightoufill; a imagem LCP tempriority; todas têmalt. - Links internos usam
next/link(um<a href>real) — sem navegação apenas comonClick. - Visualizações de 404 chamam
notFound()e retornam um404real (sem 404s suaves). - JSON-LD é injetado em um Server Component
<head>/body e passa no Teste de Resultados Rich. - Redirecionamentos permanentes vivem em
redirects()emnext.config.js(308 /permanent).
Os modelos mentais
1. O modo de renderização é o produto. Antes de depurar qualquer coisa em um site Next.js, responda a uma pergunta: como esta rota é renderizada? Server Components / SSG / SSR / ISR colocam o conteúdo no HTML e são de baixo risco; CSR é o arriscado. Quase todo problema de SEO do Next.js se resume a isso.
2. O framework fornece infraestrutura, não conteúdo. O Next.js oferece a Metadata API, convenções de sitemap/robots e o componente Image — mas não escreve nenhum dos seus títulos, descrições, canônicos ou dados estruturados. “O Next.js lida com SEO automaticamente” é o mito mais caro aqui.
3. Uma única fonte de verdade para URLs.
Defina metadataBase uma vez e construa canônicos, imagens OG e entradas de sitemap a partir dele (absolutos, nunca relativos). Uma URL base elimina a classe de bugs de canônico relativo e imagem OG quebrada.
4. Server Components primeiro, Client Components apenas onde necessário.
Use Server Components por padrão para que o conteúdo e os metadados cheguem ao HTML. Recorra a 'use client' apenas para interatividade — e lembre-se de que metadata não pode vir de um Client Component.
5. A regra de decisão para renderização. Majoritariamente estático (blogs, documentação, marketing) → SSG (ou ISR com temporizador). Sempre atualizado / volátil (preços, estoque) → SSR. Mudanças a cada hora/dia, quer velocidade estática → ISR (cuidado com a armadilha da primeira solicitação obsoleta). Interativo, atrás de login, não indexado → CSR é aceitável. Conteúdo público que você quer ranquear → nunca CSR.
Next.js SEO — folha de referência
Modos de renderização
| Modo | Onde o HTML é construído | SEO | Melhor para | Cuidado com |
|---|---|---|---|---|
| SSG | Tempo de build → estático | ✅ Melhor | Conteúdo majoritariamente estático | Obsoleto até o rebuild |
| Server Components | Servidor (padrão do App Router) | ✅ Melhor | A maioria do conteúdo | Interatividade precisa de Client Components |
| ISR | Estático + regeneração agendada | ✅ Bom | Conteúdo por hora/dia | Primeira solicitação após revalidação é obsoleta |
| SSR | Servidor, por solicitação | ✅ Bom | Dados sempre atualizados | TTFB maior / custo de infraestrutura |
| CSR | No navegador | ⚠️ Arriscado | Dashboards para usuários logados | Página vazia para crawlers não-Google |
App Router vs Pages Router
| Recurso | App Router | Pages Router |
|---|---|---|
| Metadados | metadata / generateMetadata | next/head + next-seo |
| Server Components | Padrão | Não disponível |
| Metadados de streaming (ciente de bots) | Sim | Não |
| Sitemap | app/sitemap.ts | next-sitemap / manual |
| Robots | app/robots.ts | public/robots.txt |
| Canônico | alternates.canonical | <link rel="canonical"> em <Head> |
| Busca de dados | Server Components assíncronos | getStaticProps / getServerSideProps |
Regras rápidas
- Defina
metadataBaseou canônicos/OG images ficam relativos. metadataé apenas para Server Components — exports'use client'não fazem nada.openGraphde segmento filho substitui o do pai (sem merge).priorityna imagem LCP = a maior vitória de CWV.- Links internos =
next/link(real<a href>); sem navegação só comonClick. - 404 → chame
notFound()(404 real, não soft 404). - Nunca bloqueie
.js/.css. - Metadados de streaming → bloqueio para Bingbot, Twitterbot, Slackbot, facebookexternalhit.
- Renderização dinâmica: obsoleta — use SSR / SSG / ISR / Server Components.
Verificações rápidas para um build Next.js
Algumas verificações de linha de comando antes de recorrer a um crawler completo.
Seu conteúdo está no HTML bruto (ou só depois que o JS roda)?
macOS / Linux:
# Raw HTML as the server sends it — the "first fetch", before any client JS
curl -sL -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" \
https://example.com/page/ -o raw.html
# Is your headline actually in the raw HTML? (empty result = CSR / JS-dependent)
grep -o "Your headline text" raw.html
# Did metadataBase do its job? Canonical and OG URLs should be absolute, not relative
grep -iE 'rel="canonical"|og:(url|image)' raw.htmlWindows (PowerShell):
$ua = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
Invoke-WebRequest -Uri "https://example.com/page/" -UserAgent $ua -OutFile raw.html
Select-String -Path raw.html -Pattern "Your headline text"
Select-String -Path raw.html -Pattern 'rel="canonical"','og:url','og:image'Se o título estiver ausente em raw.html mas aparecer no seu navegador, essa rota é
renderizada no cliente. Se canônicos ou URLs de OG image saírem relativos, você esqueceu
metadataBase.
Confirme que você não está bloqueando JS/CSS (incluindo o diretório _next do Next.js)
macOS / Linux:
curl -sL https://example.com/robots.txt | \
grep -iE "disallow.*\.(js|css)|Disallow:\s*/_next"Windows (PowerShell):
(Invoke-WebRequest "https://example.com/robots.txt").Content |
Select-String -Pattern "Disallow.*\.(js|css)","Disallow:\s*/_next"Qualquer correspondência aqui é quase sempre um erro — o Google não renderiza a partir de arquivos bloqueados. Um
curl simples não consegue executar JavaScript, então para o DOM renderizado use a “View Crawled
Page → rendered HTML” da URL Inspection.
Ferramentas para auditar um site Next.js
- URL Inspection (Google Search Console) — a fonte da verdade. Execute um teste ao vivo,
depois veja o HTML renderizado, screenshot e recursos da página (o que carregou vs.
o que foi bloqueado) para pegar lacunas de CSR e recursos
_nextbloqueados. - Rich Results Test — confirme que o JSON-LD entrou na saída renderizada após qualquer mudança de renderização.
- Lighthouse / Chrome DevTools — meça LCP, CLS e INP; verifique se sua imagem hero
está pré-carregada (
priority). - Ahrefs Site Audit — rastreia com renderização de JavaScript, revelando canônicos ausentes/relativos, metadados quebrados, cadeias de redirecionamento e problemas de indexabilidade no frontend.
- Screaming Frog SEO Spider — rastreie com renderização de JS ligada/desligada para comparar HTML bruto vs. renderizado, e construa comparações pré/pós rastreamento para migrações.
- Bing Webmaster Tools — a URL Inspection do Bing e onde as submissões do IndexNow aparecem.
Erros a evitar no Next.js
Padrões concretos que quebram silenciosamente o SEO em builds reais de Next.js — previna-os antes de entregá-los, em vez de depurá-los após uma queda de tráfego.
Enviando sem metadataBase no layout raiz
Por que está errado: sem metadataBase, alternates.canonical e openGraph.images
resolvem para caminhos relativos em vez de URLs absolutas. Um canonical relativo pode confundir
os sinais de canonicalização, e URLs de imagem OG relativas quebram as pré-visualizações de links em redes sociais e
apps de mensagens.
O que fazer em vez disso: defina metadataBase: new URL('https://example.com') uma vez em
app/layout.tsx e deixe cada página herdar isso. Verifique com grep -iE 'rel="canonical"|og:(url|image)' contra um fetch de HTML bruto — as URLs devem começar com https://.
Sobrescrevendo o openGraph de um layout a partir de um segmento filho
Por que está errado: os metadados são mesclados superficialmente do layout para a página. Um openGraph: { title: 'Home' } no nível da página não mescla com o openGraph.images do layout — ele
substitui o objeto inteiro, descartando silenciosamente as imagens.
O que fazer em vez disso: ou repita o objeto openGraph completo (incluindo as imagens) em
cada nível que o sobrescreve, ou apenas sobrescreva os campos específicos de metadados de nível superior que você
realmente precisa alterar, e deixe openGraph intocado onde o padrão do layout é suficiente.
Exportando metadata de um Client Component
Por que está errado: a Metadata API é exclusiva para Server Components. Adicione 'use client' a um arquivo
que também exporta metadata e a exportação não faz nada — sem erro, sem aviso, apenas uma
página sem título ou descrição.
O que fazer em vez disso: mantenha as exportações de metadata / generateMetadata em um arquivo Server
Component simples (page.tsx ou layout.tsx sem 'use client'). Se uma página precisar de interatividade
no cliente, coloque isso em um componente filho separado e importe-o — não adicione
'use client' ao arquivo que possui a exportação de metadados.
Buscando conteúdo primário em useEffect (ou confiando em CSR total)
Por que está errado: conteúdo renderizado apenas no navegador não está no HTML inicial. O Google acabará renderizando, mas o atraso mediano de renderização é real e o percentil 90 se estende por horas — e rastreadores não-Google (Bing, bots de pré-visualização social, a maioria dos rastreadores de IA) muitas vezes não renderizam JavaScript, então veem uma página vazia.
O que fazer em vez disso: use por padrão Server Components, SSG, ISR ou SSR para qualquer coisa que você
queira indexar. Reserve 'use client' e busca de dados com useEffect para UI interativa que
não precisa ser rastreável — um widget de filtro, não o corpo do artigo.
Retornando 200 para uma visualização de “não encontrado”
Por que está errado: renderizar uma mensagem de “não encontrado” sem chamar notFound() retorna um
status 200 normal. Isso é um soft 404 — o Google pode indexar a página de conteúdo vazio em vez de
reconhecê-la como ausente, e soft 404s são um dos problemas de SEO Next.js mais comuns no mundo real.
O que fazer em vez disso: chame a função embutida notFound() para que a rota retorne um 404 real.
Confirme com curl -I em uma URL conhecida como ausente e verifique o código de status diretamente,
não apenas o que renderiza no navegador.
Pulando generateStaticParams em rotas dinâmicas importantes
Por que está errado: sem isso, rotas dinâmicas caem para renderização sob demanda (SSR), que ainda funciona para SEO, mas adiciona latência de servidor a cada primeira solicitação para essa URL — incluindo a do Googlebot.
O que fazer em vez disso: enumere as URLs que importam (páginas de produto, posts de blog,
páginas de categoria) em generateStaticParams() para que sejam pré-construídas, e combine com
revalidate (ISR) para conteúdo que muda após o lançamento.
Teste-se: SEO Next.js
Cinco perguntas rápidas sobre tornar um site Next.js rastreável, indexável e rápido. Escolha uma resposta para cada uma e depois confira.
Recursos que valem seu tempo
Meus escritos relacionados
- JavaScript SEO: Um Guia Definitivo — meu guia completo sobre renderização, paridade de DOM, canônicos em JS, sitemaps e as compensações de modo de renderização sobre as quais o Next.js se baseia. Este guia de Next.js é a camada específica do framework sobre ele.
- O Guia do Iniciante para SEO Técnico — onde renderização e rastreamento se encaixam no panorama geral.
Minhas palestras
- JavaScript SEO — Ungagged 2019 (SlideShare) — minha explicação sobre como os frameworks separam o frontend do backend e como o Googlebot renderiza. (Aviso permanente: a recomendação de renderização dinâmica nessa apresentação está desatualizada — o Google a descontinuou.)
Da indústria
- Metadata and OG Images (documentação do Next.js) — o sistema de metadados do App Router,
metadataBasee geração de imagens OG. - generateMetadata API Reference (documentação do Next.js) — metadados estáticos vs. dinâmicos e o comportamento de bots limitados a HTML / metadados em streaming.
- sitemap.xml File Convention (documentação do Next.js) —
app/sitemap.ts,generateSitemaps()e sitemaps localizados/de imagens. - Common SEO Issues on Next.js Websites (Salt Agency) — um estudo de auditoria em 50 sites com dados reais sobre soft 404s e falhas de LCP.
- How Google Handles JavaScript Throughout the Indexing Process (Vercel) — dados de tempo de renderização dos próprios beacons do servidor do nextjs.org.
- The Complete Next.js SEO Guide (Strapi) — um guia completo do framework cobrindo modos de renderização, metadados e dados estruturados.
- App Router vs Pages Router for SEO (Wisp) — uma comparação focada dos dois roteadores sob a ótica de SEO.
- r/TechSEO — a comunidade para depuração de renderização/indexação.
Estatísticas que valem citar
- O tempo de renderização geralmente é rápido, ocasionalmente muito lento. A análise da Vercel de mais de 37 000 pares de beacons do servidor no nextjs.org encontrou um tempo mediano de renderização de ~10 segundos, mas um percentil 90 de ~3 horas e um percentil 99 de ~18 horas — exatamente por isso você não quer que o conteúdo principal fique esperando na fila de renderização. Fonte
- CWV e soft 404s são comuns em sites Next.js reais. A auditoria da Salt Agency em 50
sites Next.js encontrou 41/50 retornando soft 404s (visualizações de 404 com status
200) e apenas 3/50 passando nos limites de LCP — um lembrete de que as vantagens de CWV do framework só ajudam se você usarnext/imagecomprioritye retornar códigos de status reais. Fonte
Registro de alterações
Atualizado em 18 de jul. de 2026.
Resumo editorial e detalhes registrados da alteração.Detalhes da alteração
-
As notas detalhadas sobre as alterações estão disponíveis atualmente em inglês.
-
As notas detalhadas sobre as alterações estão disponíveis atualmente em inglês.
-
As notas detalhadas sobre as alterações estão disponíveis atualmente em inglês.
-
As notas detalhadas sobre as alterações estão disponíveis atualmente em inglês.
Não é possível fazer a comparação completa — nenhum instantâneo anterior foi arquivado para esta revisão.