Los problemas de SEO técnico que aparecen en casi todos los sitios con Next.js

Respuesta corta

Los problemas de SEO técnico que se repiten en proyectos Next.js son títulos y descripciones idénticos heredados del layout raíz, títulos y descripciones con la longitud equivocada, URL canónicas ausentes o incorrectas, un openGraph a nivel de página que reemplaza al del layout, noindex heredado de un layout, URL duplicadas con www, http y barra final, falta de sitemap o de archivo robots, y datos estructurados ausentes o invisibles. También son habituales el contenido que solo existe tras la hidratación, las imágenes sin dimensiones o sin texto alternativo, los niveles de encabezado saltados y la falta de hreflang. Cada sección da la corrección, con código del App Router cuando aplica.

Next.js te da mucho SEO gratis, como el HTML renderizado en el servidor y una API de metadatos tipada. También hace muy fáciles unos cuantos errores. Estos son los que se repiten, con la corrección de cada uno. Los ejemplos usan el App Router; consulta la documentación de tu versión de Next.js, porque los detalles cambian entre versiones.

1. Todas las páginas heredan el mismo título y la misma descripción

Si defines un título y una descripción en el layout raíz y te olvidas del resto, todas las páginas salen con los mismos. Entonces los buscadores muestran resultados idénticos para páginas distintas, y pierdes la oportunidad de ajustar cada página a su consulta.

app/pricing/page.tsx
export const metadata = {
  title: "Pricing",
  description: "What each plan includes and how billing works.",
};

Para las rutas dinámicas, exporta generateMetadata() y construye los valores con los mismos datos que renderiza la página. Usa una plantilla de título en el layout raíz (title: { default, template: "%s | Brand" }) para que las páginas solo aporten su propia parte.

2. Títulos y descripciones con la longitud equivocada

Google recorta el enlace del título según haga falta, normalmente para que quepa en el ancho del dispositivo, y no con un número fijo de caracteres, pero como regla práctica los títulos de unos 50 a 60 caracteres y las descripciones de unos 120 a 160 rara vez se cortan. Los muy cortos desperdician espacio; los muy largos se truncan a mitad de frase. Es una comprobación barata de automatizar y un hallazgo común en páginas antiguas.

3. URL canónicas ausentes o incorrectas

Sin una canónica, la misma página puede indexarse bajo una URL con parámetros de seguimiento, una variante con barra final o un dominio de vista previa (consulta la guía de Google sobre URL canónicas). Define metadataBase una sola vez y luego una canónica relativa por página:

// app/layout.tsx
export const metadata = { metadataBase: new URL("https://example.com") };

// app/blog/[slug]/page.tsx
export async function generateMetadata({ params }) {
  const { slug } = await params;
  return { alternates: { canonical: `/blog/${slug}` } };
}

4. Un openGraph a nivel de página que reemplaza al del layout

Los metadatos se combinan de forma superficial: si una página exporta su propio openGraph, este reemplaza el objeto openGraph del layout en lugar de ampliarlo. Los campos que definiste en el layout, como siteName o images, desaparecen en silencio en esa página. Repite los campos compartidos o constrúyelos con un único helper.

5. noindex heredado de un lugar que olvidaste

Un robots: { index: false } en un layout se aplica a todas las páginas que hay debajo. Es habitual durante el staging y es fácil que llegue a producción. Si falta una sección de tu sitio en los buscadores, revisa la cadena de layouts antes que nada.

6. www, barras finales y http, todos resolviendo

Si las versiones www.example.com, example.com y http:// devuelven 200, tienes duplicados. Elige una y redirige el resto de forma permanente. En Next.js puedes hacerlo con redirects(), donde permanent: true envía un 308, o en tu hosting o proxy.

7. Sin sitemap ni archivo robots

El App Router puede generar ambos desde código:

app/sitemap.ts
import type { MetadataRoute } from "next";

export default function sitemap(): MetadataRoute.Sitemap {
  return [{ url: "https://example.com/", lastModified: "2026-01-15" }];
}

Usa fechas reales de última modificación. Google usa ese campo solo si es constante y verificablemente preciso, y una fecha que cambia en cada build no lo es. Lista solo las URL que quieres indexar y asegúrate de que ninguna sea noindex, esté redirigida o esté bloqueada en robots.txt.

8. Datos estructurados ausentes, inválidos o invisibles

Añade JSON-LD para lo que la página realmente es: Organization, Article, BreadcrumbList, FAQPage cuando la página de verdad contiene esas preguntas y respuestas. Serialízalo de forma segura, para que el texto de la página no pueda cerrar la etiqueta script:

<script
  type="application/ld+json"
  dangerouslySetInnerHTML={{
    __html: JSON.stringify(data).replace(/</g, "\\u003c"),
  }}
/>

Marca solo lo que los visitantes pueden ver en la página. Un marcado que describe contenido que no está ahí es peor que no tener ninguno.

9. Contenido principal que solo existe tras la hidratación

Un componente de cliente que obtiene datos en useEffect renderiza una carcasa vacía en el HTML. Los rastreadores que no ejecutan JavaScript ven esa carcasa, y la documentación de rastreadores de OpenAI, Anthropic y Perplexity no dice si sus bots ejecutan JavaScript. Obtén los datos en el servidor para todo lo que quieras indexar y deja la obtención en el cliente para los extras interactivos.

10. Imágenes sin dimensiones ni texto alternativo

Si faltan width y height, se produce un desplazamiento de diseño que perjudica las Core Web Vitals. Si falta alt, se pierde accesibilidad y contexto para la búsqueda de imágenes. next/image hace difícil olvidar lo primero; lo segundo corre por tu cuenta.

11. Encabezados que saltan niveles o repiten el H1

Un solo <h1> descriptivo por página, y después <h2> y <h3> en orden. Los sistemas de diseño suelen renderizar un encabezado visual con el elemento equivocado, algo invisible en el navegador y evidente en una vista de esquema.

12. Falta de hreflang en sitios multilingües

Si publicas la misma página en varios idiomas, cada versión debe listar a las demás mediante alternates.languages, y las referencias deben ser recíprocas. El hreflang unidireccional se ignora.

Cómo comprobar todo esto automáticamente

Ninguno de estos problemas es difícil por separado. El problema es que retroceden en silencio a medida que el sitio crece. Crawlmend busca estos patrones en cada rastreo y abre un pull request contra tus archivos de metadatos para los que puede corregir; consulta las configuraciones compatibles para ver qué cubre en Next.js y qué no. O pruébalo en tu repositorio.