Checklist SEO para Next.js App Router: visibilidad SSR, canonicals, hreflang y crawlers de IA
Neaptide · 30 de octubre de 2026 · 8 min de lectura
Compruebe qué entrega realmente Next.js App Router en el HTML inicial: encabezados SSR visibles sin opacity:0, herencia de alternates, enlaces de idioma y redirecciones.
En este artículo

Un sitio en Next.js App Router puede verse perfecto en el navegador y, al mismo tiempo, entregar el título <h1> oculto con style="opacity:0" en el HTML inicial, perder etiquetas <link rel="alternate"> al sobrescribir metadatos en rutas hijas o esconder el selector de idioma dentro de botones sin href. Audite siempre la respuesta HTTP y el HTML renderizado en servidor antes de dar por buena una publicación.
Aunque los Server Components renderizan HTML en el servidor por defecto, los contenedores de animación en cliente, generateMetadata() y middleware.ts determinan lo que reciben Googlebot y los rastreadores de IA (GPTBot, OAI-SearchBot, ClaudeBot, PerplexityBot). A continuación documentamos cinco fallos reales corregidos en la web multilingüe en Next.js 15 de Neaptide y una lista de verificación repetible.
¿Qué detectó y corrigió nuestra auditoría sobre Next.js 15 en Neaptide?
En octubre de 2026 revisamos el HTML servido, las cabeceras HTTP, los metadatos y el sitemap en los seis idiomas de Neaptide. La tabla recoge los cinco defectos técnicos detectados y el resultado verificado tras el despliegue.
| Capa revisada | Defecto en el HTML SSR inicial | Corrección aplicada y resultado verificado |
|---|---|---|
| Componentes de animación Reveal.tsx y Hero.tsx | El <h1>, la introducción y las tarjetas se servían con style="opacity:0;transform:translateY(12px)" hasta la hidratación (~1,2 s) | Se eliminó opacity:0 del estado SSR inicial; títulos y textos quedan visibles desde el primer byte |
| Helper generateMetadata() en lib/meta.ts | El objeto alternates: { canonical, languages } de las páginas sobrescribía el layout y eliminaba <link rel="alternate" type="application/rss+xml"> | Se añadió types: { "application/rss+xml": "https://www.neaptide.ai/feed.xml" } en pageMetadata() |
| Selector de idioma components/LangSwitcher.tsx | Los idiomas solo se montaban al hacer clic mediante elementos <button> sin atributo href | Los 6 idiomas se renderizan en el DOM SSR como enlaces <a href={...} hrefLang={l} lang={l}> |
| Redirección raíz (/) en middleware.ts | Los bots que pedían / sin cabeceras geo ni Accept-Language no recibían una cabecera Vary explícita | Redirección determinista a x-default (/en) con Vary: Accept-Language, Cookie, x-vercel-ip-country, cf-ipcountry |
| Datos estructurados lib/schema.ts y app/sitemap.ts | Tres páginas de servicio fijaban areaServed: United States; el sitemap omitía imágenes de casos y artículos | Se alineó areaServed y se añadieron portadas y gráficos localizados en sitemap.xml |
Estas observaciones describen mejoras técnicas verificadas en nuestro propio código. Corregirlas elimina barreras de renderizado e indexación; el posicionamiento orgánico y las citas en motores de IA siguen dependiendo de la competencia y de la autoridad del sitio.
¿Por qué style="opacity:0" en las animaciones perjudica el LCP y el rastreo?
Muchos sitios en Next.js envuelven sus encabezados y bloques principales en componentes de aparición o Framer Motion con estado inicial opacity: 0. Como Next.js pre-renderiza los Client Components en el servidor usando ese estado inicial, el HTML llega con style="opacity:0" en el <h1> y en el texto principal.
Esto retrasa el cálculo de Largest Contentful Paint (LCP) hasta que finaliza la hidratación de JavaScript y presenta el contenido principal como oculto ante los rastreadores que leen el HTML sin ejecutar scripts. Mantenga el texto visible en el SSR usando solo una traslación suave (transform: translateY(12px)) sin opacity: 0.
¿Cómo puede generateMetadata borrar las etiquetas alternates del layout?
En Next.js App Router, la combinación de metadatos entre layout y página es superficial. Si una página devuelve su propio objeto alternates con canonical y languages, reemplaza por completo el objeto alternates del layout padre.
Centralice canonical, languages (incluido x-default) y types (como el feed RSS) en una única función compartida:
export function pageMetadata(locale: Locale, opts: PageMetaInput): Metadata {
const canonicalUrl = `${SITE.url}${localeHref(locale, opts.path)}`;
const languages: Record<string, string> = {};
for (const l of LOCALES) {
languages[l] = `${SITE.url}${localeHref(l, opts.path)}`;
}
languages["x-default"] = `${SITE.url}${localeHref(X_DEFAULT_LOCALE, opts.path)}`;
return {
alternates: {
canonical: canonicalUrl,
languages,
types: {
"application/rss+xml": `${SITE.url}/feed.xml`,
},
},
};
}- Documentación de Next.js sobre generateMetadata
- Guía de Google Search Central sobre versiones localizadas (hreflang)
¿Por qué el selector de idioma y la redirección raíz deben ser explícitos para los bots?
Un selector de idioma que solo monta sus opciones al hacer clic o usa botones <button> no deja enlaces HTML rastreables entre idiomas. Renderizar enlaces <a href="/en/..." hrefLang="en" lang="en"> en el DOM de la cabecera refuerza el descubrimiento interno en todas las páginas.
Compruebe también qué ocurre cuando un bot solicita / sin cookies ni cabecera Accept-Language: el middleware debe redirigir de forma determinista al idioma x-default (/en) e incluir la cabecera Vary adecuada.
Cómo verificar un despliegue en Next.js App Router en seis pasos
Ejecute estas seis comprobaciones antes de aprobar un lanzamiento:
- Visibilidad en el HTML SSR: descargue la página con curl -s y confirme que el único <h1> y el texto principal aparecen sin style="opacity:0".
- Paridad de canonical y hreflang: verifique que cada URL localizada incluye su canonical autorreferencial, los 6 idiomas, x-default y el enlace RSS.
- Enlaces rastreables: confirme que el menú, el pie de página y el selector de idioma usan etiquetas <a href="..."> en el HTML inicial.
- Redirección raíz: pruebe / con curl -I y una cabecera Accept-Language vacía para confirmar un único salto permanente al destino previsto.
- Coherencia de JSON-LD: compruebe que WebPage, Service, Article, BreadcrumbList y FAQPage coinciden con el texto visible y el idioma de la página.
- Cobertura en sitemap.xml y llms.txt: verifique que todas las rutas e imágenes clave estén incluidas en /sitemap.xml y /llms.txt.
curl -s https://www.neaptide.ai/en | grep -E '<h1|rel="canonical"|hrefLang|application/rss\+xml'
curl -I -H 'Accept-Language:' https://www.neaptide.ai/Si necesita una revisión técnica de su sitio o plataforma en Next.js, en Neaptide realizamos auditorías SEO y GEO con pruebas HTTP reproducibles y tareas listas para desarrollo.