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:
pageMetadataengenerateMetadatay unJsonLdcon el grafo de la página. El resultado depageMetadataes elMetadatade Next tal cual, sin conversión. checkSeoen 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 })enprey 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:
pageMetadatadevuelve un objeto con la misma forma, pero escribir las etiquetas<meta>es cosa del proyecto;sitemapXmlyrobotsTxtsí 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.
| Prop | Tipo | Para qué sirve |
|---|---|---|
dataobligatoria | JsonLdDocument | readonly JsonLdDocument[] | — |
nonce | string | El `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:
