Saltar al contenido
EspañolEnglish
Todos los componentes (204)

SEO de página

Más · JsonLd

Qué es y cuándo usarlo

Todo lo que una página necesita para que los buscadores y las redes la entiendan, en @amset/ui/seo: los metadatos (título, descripción, canónica, Open Graph, tarjeta de X, robots), los datos estructurados de schema.org, el sitemap.xml y el robots.txt. Corre en el servidor, no lleva 'use client', no trae CSS y no añade JavaScript al navegador: JsonLd es el único componente y es de servidor.

import { JsonLd, jsonLdGraph, organization, pageMetadata, webPage, webSite } from '@amset/ui/seo'

// app/anillos/page.tsx (Next, App Router)
export function generateMetadata() {
  return pageMetadata({
    siteUrl: 'https://aurelia.example',
    siteName: 'Joyería Aurelia',
    title: 'Anillos de oro artesanales',
    description: 'Anillos de oro de 18 quilates hechos a mano…',
    path: '/anillos',
    image: { url: '/og/anillos.jpg', alt: 'Tres anillos de oro', width: 1200, height: 630 },
  })
}

export default function Page() {
  return <JsonLd data={jsonLdGraph(organization(…), webSite(…), webPage(…))} />
}

// app/sitemap.ts   →  sitemapEntries(siteUrl, páginas)
// app/robots.ts    →  robotsRules({ siteUrl, blockAll: process.env.VERCEL_ENV !== 'production' })

Cuándo usarlo

  • En cada página pública: pageMetadata en generateMetadata y un JsonLd con el grafo de la página. El resultado de pageMetadata es el Metadata de Next tal cual, sin conversión.
  • checkSeo en una prueba o en el CI: devuelve avisos (título que se corta, descripción corta, imagen sin medidas) y errores que impiden publicar.
  • robotsRules({ blockAll: true }) en pre y en cualquier entorno que no sea producción: una copia de pruebas indexada compite con la buena.

Cuándo no

  • Para una pantalla de una aplicación tras el inicio de sesión: ahí no hay nada que indexar (noindex).
  • Fuera de Next: pageMetadata devuelve un objeto con la misma forma, pero escribir las etiquetas <meta> es cosa del proyecto; sitemapXml y robotsTxt sí dan los ficheros.

Qué valida y qué no deja pasar: pageMetadata lanza SeoError (con la lista de issues) si falta el título o la descripción, el siteUrl no es absoluto, la ruta no empieza por «/», la imagen no tiene texto alternativo o una fecha no es ISO 8601. Los constructores de JSON-LD lanzan ante un titular de más de 110 caracteres, un precio negativo, una moneda que no es ISO 4217, un artículo sin autor o una plantilla de buscador sin {search_term_string}. sitemapEntries lanza ante direcciones repetidas, prioridades fuera de 0–1 y más de 50.000 entradas. Fallar al construir es a propósito: una página sin descripción no debería llegar a producción.

Seguridad: serializeJsonLd escapa <, >, & y los separadores de línea de Unicode. Un texto con </script> (el nombre de un producto escrito por un usuario) no puede cerrar la etiqueta ni inyectar HTML. JsonLd acepta el nonce de la política de seguridad del sitio.

Teclado y accesibilidad: no pinta nada visible, así que no tiene teclado. El texto alternativo de la imagen social es obligatorio, y el título y la descripción son lo que lee un lector de pantalla al abrir la pestaña.

Aspecto fino: no tiene; no pinta nada.

Cómo se ve

{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Organization",
      "@id": "https://aurelia.example/#organization",
      "name": "Joyería Aurelia",
      "url": "https://aurelia.example/"
    }
  ]
}

<JsonLd
  data={jsonLdGraph(organization({ name: 'Joyería Aurelia', url: 'https://aurelia.example' }))}
/>

Props

Se importa con import { JsonLd } from '@amset/ui/seo'. Las obligatorias van marcadas.

PropTipoPara qué sirve
dataobligatoriaJsonLdDocument | readonly JsonLdDocument[]—
noncestringEl `nonce` de la politica de seguridad del sitio, si la tiene.

En el banco de pruebas

Cada estado y cada variante, para tocarlos de uno en uno, en su ficha de ui.amset.tech: