Inicio / Artículos

SEO técnico en el Next.js App Router: metadatos, mapas del sitio y JSON-LD

Aprenda cómo los ayudantes de metadatos compartidos, las configuraciones predeterminadas del diseño raíz, robots.ts, un mapa del sitio dinámico, JSON-LD preciso y las auditorías de páginas proporcionan a una aplicación Next.js una base SEO impecable.

Editor: REACTAPP.TOP4 min de lectura1024 palabras

Fuentes: How I Got a Next.js Project to 100% SEO on Lighthouse

Una aplicación Next.js puede parecer terminada y, aun así, resultar difícil de leer para los motores de búsqueda: las páginas carecen de URLs canónicas, no están definidas las reglas para los rastreadores, y el contenido nuevo nunca llega al mapa del sitio. Esta guía sigue a un sitio con API de datos ficticios que cuenta con muchas páginas de recursos, desde su primera auditoría SEO con Lighthouse hasta alcanzar una puntuación de 100, mostrando los siete cambios realizados con las API de metadatos integradas del App Router.

Generar metadatos de página a partir de una función auxiliar

Escribir los metadatos manualmente en cada página provoca desviaciones, como la falta de una URL canónica aquí o un título Open Graph obsoleto allá. Una pequeña función auxiliar soluciona esto: cada página solo envía su título, descripción, ruta y una bandera opcional noIndex, y la función auxiliar los expande en campos canónicos, para robots y Open Graph:

export function createPageMetadata({
  title,
  description,
  path,
  noIndex = false,
}: PageMetadata) {
  return {
    title,
    description,
    alternates: {
      canonical: path,
    },
    robots: noIndex ? "noindex, nofollow" : "index, follow",
    openGraph: {
      title,
      description,
      url: path,
      type: "website",
    },
  };
}

La indexación es opcional: una bandera convierte una página en noindex, nofollow. Dado que path es relativo, la herramienta depende de una URL base definida en el layout raíz.

Coloque los valores predeterminados para todo el sitio en el layout raíz

Todo lo que se comparte en todo el sitio debe incluirse en la exportación de metadata de layout.tsx:

  • metadataBase
  • un modelo de título
  • una descripción predeterminada
  • valores predeterminados para Open Graph
  • configuraciones de la tarjeta de Twitter
  • valores predeterminados para robots
  • el atributo lang en el elemento <html>

Una versión simplificada de esa exportación se ve así:

export const metadata: Metadata = {
  metadataBase: new URL("https://mockdata.ir"),
  title: {
    default: "MockData",
    template: "%s | MockData",
  },
  description: "...",
};

Con la plantilla %s | MockData, una página titulada “Users API” se muestra como “Users API | MockData”, mientras que las páginas sin título utilizan el valor default. metadataBase es lo que convierte los valores relativos canonical y de Open Graph url del helper en URLs absolutas. Tenga en cuenta que lang no es un campo de metadatos; úselo en la etiqueta <html> que muestra el layout.

Defina reglas para los rastreadores con robots.ts

En lugar de dejar las reglas para los rastreadores sin definir, genere un archivo robots.txt a partir de un archivo app/robots.ts que devuelva un objeto MetadataRoute.Robots de tipo especificado:

export default function robots(): MetadataRoute.Robots {
  return {
    rules: {
      userAgent: "*",
      allow: "/",
    },
    sitemap: "https://mockdata.ir/sitemap.xml",
  };
}

Está diseñado deliberadamente de forma minimalista: todos los agentes de usuario pueden rastrear todo, y se indica la ubicación del mapa del sitio.

Genere el mapa del sitio a partir de sus datos

Con páginas de recursos para usuarios, publicaciones, productos y más, un mapa del sitio XML mantenido manualmente no es escalable. La exportación por defecto de sitemap.ts puede ser async, lo que le permite consultar la misma fuente que utilizan las páginas:

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const resources = await getPublicResources();

return [
    {
      url: "https://mockdata.ir",
      lastModified: new Date(),
    },
    ...resources.map((resource) => ({
      url: `https://mockdata.ir/${resource.slug}`,
      lastModified: resource.updatedAt,
    })),
  ];
}

Cada recurso se asocia a una URL donde updatedAt funciona como lastModified, de modo que los nuevos recursos públicos se integran automáticamente en el mapa del sitio. Una mejora: new Date() para la página principal indica un cambio en cada generación; un timestamp real del contenido es más preciso.

Agregue datos estructurados solo cuando sea necesario

JSON-LD con el vocabulario de Schema.org indica a los motores de búsqueda qué representa una página. La propia aplicación se describe como SoftwareApplication, y los tipos utilizados son:

  • WebSite
  • Organization
  • SoftwareApplication
  • BreadcrumbList
  • Busque la precisión, no la cantidad: el marcado debe describir el contenido que realmente se encuentra en la página. Las reseñas inventadas, las calificaciones u otras propiedades fabricadas son engañosas y pueden violar las pautas de los motores de búsqueda.

    Mantenga coherentes las pistas de navegación entre la interfaz de usuario y el esquema

    Las páginas de documentación anidadas muestran una ruta visible como Inicio → Documentos → API de usuarios, y la misma jerarquía se emite como datos estructurados BreadcrumbList. La ruta visible y el marcado deben describir siempre la misma estructura.

    Haga una auditoría manual de cada página indexable

    Finalmente, revise cada página pública por separado:

    • ¿Tiene exactamente un H1 claro?
    • ¿El título describe esta página específica?
    • ¿La descripción coincide con el contenido real?
    • ¿Existen enlaces internos útiles hacia y desde ella?
    • ¿Debería esta página ser indexada en absoluto?
    • ¿Hay alguna página vacía o de bajo valor expuesta a los rastreadores?

    No toda ruta debe aparecer en los resultados de búsqueda; a menudo noindex es la opción adecuada. Para conocer más sobre la estructura de encabezados, consulte esta guía sobre HTML semántico en lo que respecta a la marcación.

    Qué significa y qué no significa una puntuación perfecta en Lighthouse SEO

    Después de aplicar estas correcciones, Lighthouse indicó una puntuación SEO de 100. Esa cifra verifica aspectos técnicos básicos como títulos, descripciones y capacidad de rastreo; no dice nada sobre el posicionamiento. El posicionamiento depende de la calidad del contenido, la intención de búsqueda, la autoridad, los enlaces de retroceso, la competencia, el rendimiento y muchos otros factores.

    El verdadero valor radica en la base sólida que se crea. Realizar la auditoría antes de publicar cualquier aplicación Next.js es económico y permite detectar muchos errores menores.

    Puntos clave

    • Centralice los metadatos por página en una función auxiliar y establezca valores predeterminados compartidos, incluyendo metadataBase, en el diseño raíz.
    • Utilice robots.ts y un sitemap.ts asíncrono para que las reglas de los rastreadores y las URLs estén sincronizadas con sus datos.
    • Agregue solo datos estructurados que describan fielmente la página, y mantenga los breadcrumbs idénticos tanto en la interfaz de usuario como en el esquema.
    • Considere noindex como una opción legítima para páginas que no deben aparecer en los resultados de búsqueda.
    • Interprete una puntuación de Lighthouse de 100 como “técnicamente sólida”, y no como una garantía de clasificación.

    Lecturas relacionadas

  • Contratos tipados y protecciones Zod para un panel de analíticas en WebSocket en tiempo real — Cómo crear un panel confiable en tiempo real con TypeScript: definir contratos de carga, validar mensajes WebSocket con Zod y evitar conexiones duplicadas.
  • Un flujo de trabajo asistido por IA para subir un pequeño sitio web a Cloudflare — Un flujo de trabajo reutilizable y plantillas de instrucciones para diseñar, mejorar e implementar un sitio pequeño con la ayuda de un asistente de programación por IA, GitHub y la versión gratuita de Cloudflare.