Skip to content
EspañolEnglish
All components (204)

Page SEO

More · JsonLd

What it is and when to use it

Everything a page needs for search engines and social networks to understand it, in @amset/ui/seo: the metadata (title, description, canonical, Open Graph, X card, robots), the schema.org structured data, the sitemap.xml and the robots.txt. It runs on the server, carries no 'use client', ships no CSS and adds no JavaScript to the browser: JsonLd is the only component and it is a server component.

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' })

When to use it

  • On every public page: pageMetadata in generateMetadata and a JsonLd with the page graph. The result of pageMetadata is the Next Metadata as is, with no conversion.
  • checkSeo in a test or in CI: it returns warnings (a title that gets cut, a short description, an image without dimensions) and errors that prevent publishing.
  • robotsRules({ blockAll: true }) in pre and in any environment that is not production: an indexed test copy competes with the real one.

When not to

  • For an application screen behind the login: there is nothing to index there (noindex).
  • Outside Next: pageMetadata returns an object with the same shape, but writing the <meta> tags is up to the project; sitemapXml and robotsTxt do give you the files.

What it validates and what it does not let through: pageMetadata throws SeoError (with the list of issues) if the title or the description is missing, siteUrl is not absolute, the path does not start with "/", the image has no alternative text or a date is not ISO 8601. The JSON-LD builders throw on a headline longer than 110 characters, a negative price, a currency that is not ISO 4217, an article without an author or a search template without {search_term_string}. sitemapEntries throws on repeated addresses, priorities outside 0–1 and more than 50,000 entries. Failing at build time is on purpose: a page without a description should not reach production.

Security: serializeJsonLd escapes <, >, & and the Unicode line separators. A text with </script> (a product name typed by a user) cannot close the tag or inject HTML. JsonLd accepts the nonce of the site security policy.

Keyboard and accessibility: it draws nothing visible, so it has no keyboard. The alternative text of the social image is mandatory, and the title and the description are what a screen reader reads when the tab opens.

Fine-tuning: it has none; it draws nothing.

What it looks like

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

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

Props

Import it with import { JsonLd } from '@amset/ui/seo'. Required props are marked.

PropTypeWhat it does
datarequiredJsonLdDocument | readonly JsonLdDocument[]—
noncestringEl `nonce` de la politica de seguridad del sitio, si la tiene.

In the test bench

Every state and variant, to try one at a time, on its page at ui.amset.tech: