Objeto Metadata y opciones de generateMetadata

Esta página cubre todas las opciones de Metadata basada en configuración con generateMetadata y el objeto de metadatos estáticos.

import { Metadata } from 'next'

// Metadata estática
export const metadata: Metadata = {
  title: '...',
}

// Metadata dinámica
export async function generateMetadata({ params }) {
  return {
    title: '...',
  }
}
// Metadata estática
export const metadata = {
  title: '...',
}

// Metadata dinámica
export async function generateMetadata({ params }) {
  return {
    title: '...',
  }
}

Es bueno saber:

  • Las exportaciones del objeto metadata y la función generateMetadata solo son compatibles en Componentes de Servidor.
  • No puede exportar tanto el objeto metadata como la función generateMetadata desde el mismo segmento de ruta.

El objeto metadata

Para definir metadatos estáticos, exporte un objeto Metadata desde un archivo layout.js o page.js.

import { Metadata } from 'next'

export const metadata: Metadata = {
  title: '...',
  description: '...',
}

export default function Page() {}
export const metadata = {
  title: '...',
  description: '...',
}

export default function Page() {}

Consulte los Campos de Metadata para ver una lista completa de opciones compatibles.

Función generateMetadata

Los metadatos dinámicos que dependen de información dinámica, como los parámetros de ruta actuales, datos externos o metadata en segmentos padres, pueden configurarse exportando una función generateMetadata que devuelve un objeto Metadata.

import { Metadata, ResolvingMetadata } from 'next'

type Props = {
  params: { id: string }
  searchParams: { [key: string]: string | string[] | undefined }
}

export async function generateMetadata(
  { params, searchParams }: Props,
  parent: ResolvingMetadata
): Promise<Metadata> {
  // leer parámetros de ruta
  const id = params.id

  // obtener datos
  const product = await fetch(`https://.../${id}`).then((res) => res.json())

  // opcionalmente acceder y extender (en lugar de reemplazar) metadatos padres
  const previousImages = (await parent).openGraph?.images || []

  return {
    title: product.title,
    openGraph: {
      images: ['/some-specific-page-image.jpg', ...previousImages],
    },
  }
}

export default function Page({ params, searchParams }: Props) {}
export async function generateMetadata({ params, searchParams }, parent) {
  // leer parámetros de ruta
  const id = params.id

  // obtener datos
  const product = await fetch(`https://.../${id}`).then((res) => res.json())

  // opcionalmente acceder y extender (en lugar de reemplazar) metadatos padres
  const previousImages = (await parent).openGraph?.images || []

  return {
    title: product.title,
    openGraph: {
      images: ['/some-specific-page-image.jpg', ...previousImages],
    },
  }
}

export default function Page({ params, searchParams }) {}

Parámetros

La función generateMetadata acepta los siguientes parámetros:

  • props - Un objeto que contiene los parámetros de la ruta actual:

    • params - Un objeto que contiene los parámetros de ruta dinámica desde el segmento raíz hasta el segmento donde se llama a generateMetadata. Ejemplos:

      RutaURLparams
      app/shop/[slug]/page.js/shop/1{ slug: '1' }
      app/shop/[tag]/[item]/page.js/shop/1/2{ tag: '1', item: '2' }
      app/shop/[...slug]/page.js/shop/1/2{ slug: ['1', '2'] }
    • searchParams - Un objeto que contiene los parámetros de búsqueda de la URL actual. Ejemplos:

      URLsearchParams
      /shop?a=1{ a: '1' }
      /shop?a=1&b=2{ a: '1', b: '2' }
      /shop?a=1&a=2{ a: ['1', '2'] }
  • parent - Una promesa de los metadatos resueltos de los segmentos de ruta padres.

Retornos

generateMetadata debe devolver un objeto Metadata que contenga uno o más campos de metadatos.

Es bueno saber:

  • Si los metadatos no dependen de información en tiempo de ejecución, deben definirse usando el objeto estático metadata en lugar de generateMetadata.
  • Las solicitudes fetch se memorizan automáticamente para los mismos datos en generateMetadata, generateStaticParams, Layouts, Pages y Server Components. Se puede usar cache de React si fetch no está disponible.
  • searchParams solo está disponible en segmentos page.js.
  • Los métodos redirect() y notFound() de Next.js también se pueden usar dentro de generateMetadata.

Campos de Metadata

title

El atributo title se usa para establecer el título del documento. Se puede definir como una cadena simple o un objeto de plantilla opcional.

String

layout.js | page.js
export const metadata = {
  title: 'Next.js',
}
<head> output
<title>Next.js</title>

Template object

import { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    template: '...',
    default: '...',
    absolute: '...',
  },
}
export const metadata = {
  title: {
    default: '...',
    template: '...',
    absolute: '...',
  },
}
Default

title.default se puede usar para proporcionar un título de respaldo a segmentos de ruta hijos que no definen un title.

app/layout.tsx
import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    default: 'Acme',
  },
}
app/about/page.tsx
import type { Metadata } from 'next'

export const metadata: Metadata = {}

// Output: <title>Acme</title>
Template

title.template se puede usar para agregar un prefijo o sufijo a los titles definidos en segmentos de ruta hijos.

import { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    template: '%s | Acme',
    default: 'Acme', // se requiere un valor predeterminado al crear una plantilla
  },
}
export const metadata = {
  title: {
    template: '%s | Acme',
    default: 'Acme', // se requiere un valor predeterminado al crear una plantilla
  },
}
import { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'About',
}

// Output: <title>About | Acme</title>
export const metadata = {
  title: 'About',
}

// Output: <title>About | Acme</title>

Es bueno saber:

  • title.template se aplica a segmentos de ruta hijos y no al segmento donde se define. Esto significa:

    • title.default es requerido cuando agrega un title.template.
    • title.template definido en layout.js no se aplicará a un title definido en un page.js del mismo segmento de ruta.
    • title.template definido en page.js no tiene efecto porque una página siempre es el segmento terminal (no tiene segmentos de ruta hijos).
  • title.template no tiene efecto si una ruta no ha definido un title o title.default.

Absolute

title.absolute se puede usar para proporcionar un título que ignora title.template establecido en segmentos padres.

import { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    template: '%s | Acme',
  },
}
export const metadata = {
  title: {
    template: '%s | Acme',
  },
}
import { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    absolute: 'About',
  },
}

// Output: <title>About</title>
export const metadata = {
  title: {
    absolute: 'About',
  },
}

// Output: <title>About</title>

Es bueno saber:

  • layout.js

    • title (string) y title.default definen el título predeterminado para segmentos hijos (que no definen su propio title). Aumentará title.template del segmento padre más cercano si existe.
    • title.absolute define el título predeterminado para segmentos hijos. Ignora title.template de segmentos padres.
    • title.template define una nueva plantilla de título para segmentos hijos.
  • page.js

    • Si una página no define su propio título, se usará el título resuelto del padre más cercano.
    • title (string) define el título de la ruta. Aumentará title.template del segmento padre más cercano si existe.
    • title.absolute define el título de la ruta. Ignora title.template de segmentos padres.
    • title.template no tiene efecto en page.js porque una página siempre es el segmento terminal de una ruta.

description

layout.js | page.js
export const metadata = {
  description: 'The React Framework for the Web',
}
<head> output
<meta name="description" content="The React Framework for the Web" />

Campos básicos

layout.js | page.js
export const metadata = {
  generator: 'Next.js',
  applicationName: 'Next.js',
  referrer: 'origin-when-cross-origin',
  keywords: ['Next.js', 'React', 'JavaScript'],
  authors: [{ name: 'Seb' }, { name: 'Josh', url: 'https://nextjs.org' }],
  creator: 'Jiachi Liu',
  publisher: 'Sebastian Markbåge',
  formatDetection: {
    email: false,
    address: false,
    telephone: false,
  },
}
<head> output
<meta name="application-name" content="Next.js" />
<meta name="author" content="Seb" />
<link rel="author" href="https://nextjs.org" />
<meta name="author" content="Josh" />
<meta name="generator" content="Next.js" />
<meta name="keywords" content="Next.js,React,JavaScript" />
<meta name="referrer" content="origin-when-cross-origin" />
<meta name="color-scheme" content="dark" />
<meta name="creator" content="Jiachi Liu" />
<meta name="publisher" content="Sebastian Markbåge" />
<meta name="format-detection" content="telephone=no, address=no, email=no" />

metadataBase

metadataBase es una opción conveniente para establecer un prefijo de URL base para campos metadata que requieren una URL completa.

  • metadataBase permite que los campos metadata basados en URL definidos en el segmento de ruta actual y siguientes usen una ruta relativa en lugar de una URL absoluta que de otro modo sería requerida.
  • La ruta relativa del campo se combinará con metadataBase para formar una URL completa.
  • Si no se configura, metadataBase se rellena automáticamente con un valor predeterminado.
layout.js | page.js
export const metadata = {
  metadataBase: new URL('https://acme.com'),
  alternates: {
    canonical: '/',
    languages: {
      'en-US': '/en-US',
      'de-DE': '/de-DE',
    },
  },
  openGraph: {
    images: '/og-image.png',
  },
}
<head> output
<link rel="canonical" href="https://acme.com" />
<link rel="alternate" hreflang="en-US" href="https://acme.com/en-US" />
<link rel="alternate" hreflang="de-DE" href="https://acme.com/de-DE" />
<meta property="og:image" content="https://acme.com/og-image.png" />

Es bueno saber:

  • metadataBase normalmente se establece en el app/layout.js raíz para aplicar a campos metadata basados en URL en todas las rutas.
  • Todos los campos metadata basados en URL que requieren URLs absolutas se pueden configurar con una opción metadataBase.
  • metadataBase puede contener un subdominio, por ejemplo, https://app.acme.com o una ruta base, por ejemplo, https://acme.com/start/from/here.
  • Si un campo metadata proporciona una URL absoluta, metadataBase se ignorará.
  • Usar una ruta relativa en un campo metadata basado en URL sin configurar un metadataBase causará un error de compilación.
  • Next.js normalizará barras diagonales duplicadas entre metadataBase (por ejemplo, https://acme.com/) y un campo relativo (por ejemplo, /path) a una sola barra (por ejemplo, https://acme.com/path).

Valor predeterminado

Si no se configura, metadataBase tiene un valor predeterminado:

  • Cuando se detecta VERCEL_URL: https://${process.env.VERCEL_URL}, de lo contrario, recurre a http://localhost:${process.env.PORT || 3000}.
  • Al anular el valor predeterminado, recomendamos usar variables de entorno para calcular la URL. Esto permite configurar una URL para entornos de desarrollo local, staging y producción.

Composición de URL

La composición de URL favorece la intención del desarrollador sobre la semántica predeterminada de recorrido de directorios.

  • Las barras diagonales finales entre metadataBase y campos metadata se normalizan.
  • Una ruta "absoluta" en un campo metadata (que normalmente reemplazaría toda la ruta de la URL) se trata como una ruta "relativa" (comenzando desde el final de metadataBase).

Por ejemplo, dado el siguiente metadataBase:

import { Metadata } from 'next'

export const metadata: Metadata = {
  metadataBase: new URL('https://acme.com'),
}
export const metadata = {
  metadataBase: new URL('https://acme.com'),
}

Cualquier campo metadata que herede el metadataBase anterior y establezca su propio valor se resolverá de la siguiente manera:

Campo metadataURL resuelta
/https://acme.com
./https://acme.com
paymentshttps://acme.com/payments
/paymentshttps://acme.com/payments
./paymentshttps://acme.com/payments
../paymentshttps://acme.com/payments
https://beta.acme.com/paymentshttps://beta.acme.com/payments

openGraph

layout.js | page.js
export const metadata = {
  openGraph: {
    title: 'Next.js',
    description: 'The React Framework for the Web',
    url: 'https://nextjs.org',
    siteName: 'Next.js',
    images: [
      {
        url: 'https://nextjs.org/og.png', // Debe ser una URL absoluta
        width: 800,
        height: 600,
      },
      {
        url: 'https://nextjs.org/og-alt.png', // Debe ser una URL absoluta
        width: 1800,
        height: 1600,
        alt: 'Mi texto alternativo personalizado',
      },
    ],
    videos: [
      {
        url: 'https://nextjs.org/video.mp4', // Debe ser una URL absoluta
        width: 800,
        height: 600,
      },
    ],
    audio: [
      {
        url: 'https://nextjs.org/audio.mp3', // Debe ser una URL absoluta
      },
    ],
    locale: 'en_US',
    type: 'website',
  },
}
<head> output
<meta property="og:title" content="Next.js" />
<meta property="og:description" content="The React Framework for the Web" />
<meta property="og:url" content="https://nextjs.org/" />
<meta property="og:site_name" content="Next.js" />
<meta property="og:locale" content="en_US" />
<meta property="og:image:url" content="https://nextjs.org/og.png" />
<meta property="og:image:width" content="800" />
<meta property="og:image:height" content="600" />
<meta property="og:image:url" content="https://nextjs.org/og-alt.png" />
<meta property="og:image:width" content="1800" />
<meta property="og:image:height" content="1600" />
<meta property="og:image:alt" content="Mi texto alternativo personalizado" />
<meta property="og:video" content="https://nextjs.org/video.mp4" />
<meta property="og:video:width" content="800" />
<meta property="og:video:height" content="600" />
<meta property="og:audio" content="https://nextjs.org/audio.mp3" />
<meta property="og:type" content="website" />
layout.js | page.js
export const metadata = {
  openGraph: {
    title: 'Next.js',
    description: 'The React Framework for the Web',
    type: 'article',
    publishedTime: '2023-01-01T00:00:00.000Z',
    authors: ['Seb', 'Josh'],
  },
}
<head> output
<meta property="og:title" content="Next.js" />
<meta property="og:description" content="The React Framework for the Web" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2023-01-01T00:00:00.000Z" />
<meta property="article:author" content="Seb" />
<meta property="article:author" content="Josh" />

Nota importante:

  • Puede ser más conveniente usar la API de Metadata basada en archivos para imágenes de Open Graph. En lugar de tener que sincronizar la exportación de configuración con archivos reales, la API basada en archivos generará automáticamente los metadatos correctos.

robots

import type { Metadata } from 'next'

export const metadata: Metadata = {
  robots: {
    index: false,
    follow: true,
    nocache: true,
    googleBot: {
      index: true,
      follow: false,
      noimageindex: true,
      'max-video-preview': -1,
      'max-image-preview': 'large',
      'max-snippet': -1,
    },
  },
}
<head> output
<meta name="robots" content="noindex, follow, nocache" />
<meta
  name="googlebot"
  content="index, nofollow, noimageindex, max-video-preview:-1, max-image-preview:large, max-snippet:-1"
/>

icons

Nota importante: Recomendamos usar la API de Metadata basada en archivos para iconos cuando sea posible. En lugar de tener que sincronizar la exportación de configuración con archivos reales, la API basada en archivos generará automáticamente los metadatos correctos.

layout.js | page.js
export const metadata = {
  icons: {
    icon: '/icon.png',
    shortcut: '/shortcut-icon.png',
    apple: '/apple-icon.png',
    other: {
      rel: 'apple-touch-icon-precomposed',
      url: '/apple-touch-icon-precomposed.png',
    },
  },
}
<head> output
<link rel="shortcut icon" href="/shortcut-icon.png" />
<link rel="icon" href="/icon.png" />
<link rel="apple-touch-icon" href="/apple-icon.png" />
<link
  rel="apple-touch-icon-precomposed"
  href="/apple-touch-icon-precomposed.png"
/>
layout.js | page.js
export const metadata = {
  icons: {
    icon: [
      { url: '/icon.png' },
      new URL('/icon.png', 'https://example.com'),
      { url: '/icon-dark.png', media: '(prefers-color-scheme: dark)' },
    ],
    shortcut: ['/shortcut-icon.png'],
    apple: [
      { url: '/apple-icon.png' },
      { url: '/apple-icon-x3.png', sizes: '180x180', type: 'image/png' },
    ],
    other: [
      {
        rel: 'apple-touch-icon-precomposed',
        url: '/apple-touch-icon-precomposed.png',
      },
    ],
  },
}
<head> output
<link rel="shortcut icon" href="/shortcut-icon.png" />
<link rel="icon" href="/icon.png" />
<link rel="icon" href="https://example.com/icon.png" />
<link rel="icon" href="/icon-dark.png" media="(prefers-color-scheme: dark)" />
<link rel="apple-touch-icon" href="/apple-icon.png" />
<link
  rel="apple-touch-icon-precomposed"
  href="/apple-touch-icon-precomposed.png"
/>
<link
  rel="apple-touch-icon"
  href="/apple-icon-x3.png"
  sizes="180x180"
  type="image/png"
/>

Nota importante: Las etiquetas meta msapplication-* ya no son compatibles en las versiones Chromium de Microsoft Edge, por lo que ya no son necesarias.

themeColor

Obsoleto: La opción themeColor en metadata está obsoleta a partir de Next.js 14. Por favor, use la configuración viewport en su lugar.

manifest

Un manifiesto de aplicación web, como se define en la especificación de Manifiesto de Aplicación Web.

layout.js | page.js
export const metadata = {
  manifest: 'https://nextjs.org/manifest.json',
}
<head> output
<link rel="manifest" href="https://nextjs.org/manifest.json" />

twitter

La especificación de Twitter se usa (sorprendentemente) para más que solo X (anteriormente conocido como Twitter).

Aprenda más sobre la referencia de marcado de Twitter Card.

layout.js | page.js
export const metadata = {
  twitter: {
    card: 'summary_large_image',
    title: 'Next.js',
    description: 'The React Framework for the Web',
    siteId: '1467726470533754880',
    creator: '@nextjs',
    creatorId: '1467726470533754880',
    images: ['https://nextjs.org/og.png'], // Debe ser una URL absoluta
  },
}
<head> output
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site:id" content="1467726470533754880" />
<meta name="twitter:creator" content="@nextjs" />
<meta name="twitter:creator:id" content="1467726470533754880" />
<meta name="twitter:title" content="Next.js" />
<meta name="twitter:description" content="The React Framework for the Web" />
<meta name="twitter:image" content="https://nextjs.org/og.png" />
layout.js | page.js
export const metadata = {
  twitter: {
    card: 'app',
    title: 'Next.js',
    description: 'The React Framework for the Web',
    siteId: '1467726470533754880',
    creator: '@nextjs',
    creatorId: '1467726470533754880',
    images: {
      url: 'https://nextjs.org/og.png',
      alt: 'Next.js Logo',
    },
    app: {
      name: 'twitter_app',
      id: {
        iphone: 'twitter_app://iphone',
        ipad: 'twitter_app://ipad',
        googleplay: 'twitter_app://googleplay',
      },
      url: {
        iphone: 'https://iphone_url',
        ipad: 'https://ipad_url',
      },
    },
  },
}
<head> output
<meta name="twitter:site:id" content="1467726470533754880" />
<meta name="twitter:creator" content="@nextjs" />
<meta name="twitter:creator:id" content="1467726470533754880" />
<meta name="twitter:title" content="Next.js" />
<meta name="twitter:description" content="The React Framework for the Web" />
<meta name="twitter:card" content="app" />
<meta name="twitter:image" content="https://nextjs.org/og.png" />
<meta name="twitter:image:alt" content="Next.js Logo" />
<meta name="twitter:app:name:iphone" content="twitter_app" />
<meta name="twitter:app:id:iphone" content="twitter_app://iphone" />
<meta name="twitter:app:id:ipad" content="twitter_app://ipad" />
<meta name="twitter:app:id:googleplay" content="twitter_app://googleplay" />
<meta name="twitter:app:url:iphone" content="https://iphone_url" />
<meta name="twitter:app:url:ipad" content="https://ipad_url" />
<meta name="twitter:app:name:ipad" content="twitter_app" />
<meta name="twitter:app:name:googleplay" content="twitter_app" />

viewport

Obsoleto: La opción viewport en metadata está obsoleta a partir de Next.js 14. Por favor, use la configuración viewport en su lugar.

verification

layout.js | page.js
export const metadata = {
  verification: {
    google: 'google',
    yandex: 'yandex',
    yahoo: 'yahoo',
    other: {
      me: ['my-email', 'my-link'],
    },
  },
}
<head> output
<meta name="google-site-verification" content="google" />
<meta name="y_key" content="yahoo" />
<meta name="yandex-verification" content="yandex" />
<meta name="me" content="my-email" />
<meta name="me" content="my-link" />

appleWebApp

layout.js | page.js
export const metadata = {
  itunes: {
    appId: 'myAppStoreID',
    appArgument: 'myAppArgument',
  },
  appleWebApp: {
    title: 'Apple Web App',
    statusBarStyle: 'black-translucent',
    startupImage: [
      '/assets/startup/apple-touch-startup-image-768x1004.png',
      {
        url: '/assets/startup/apple-touch-startup-image-1536x2008.png',
        media: '(device-width: 768px) and (device-height: 1024px)',
      },
    ],
  },
}
<head> output
<meta
  name="apple-itunes-app"
  content="app-id=myAppStoreID, app-argument=myAppArgument"
/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Apple Web App" />
<link
  href="/assets/startup/apple-touch-startup-image-768x1004.png"
  rel="apple-touch-startup-image"
/>
<link
  href="/assets/startup/apple-touch-startup-image-1536x2008.png"
  media="(device-width: 768px) and (device-height: 1024px)"
  rel="apple-touch-startup-image"
/>
<meta
  name="apple-mobile-web-app-status-bar-style"
  content="black-translucent"
/>

alternates

layout.js | page.js
export const metadata = {
  alternates: {
    canonical: 'https://nextjs.org',
    languages: {
      'en-US': 'https://nextjs.org/en-US',
      'de-DE': 'https://nextjs.org/de-DE',
    },
    media: {
      'only screen and (max-width: 600px)': 'https://nextjs.org/mobile',
    },
    types: {
      'application/rss+xml': 'https://nextjs.org/rss',
    },
  },
}
<head> output
<link rel="canonical" href="https://nextjs.org" />
<link rel="alternate" hreflang="en-US" href="https://nextjs.org/en-US" />
<link rel="alternate" hreflang="de-DE" href="https://nextjs.org/de-DE" />
<link
  rel="alternate"
  media="only screen and (max-width: 600px)"
  href="https://nextjs.org/mobile"
/>
<link
  rel="alternate"
  type="application/rss+xml"
  href="https://nextjs.org/rss"
/>
layout.js | page.js
export const metadata = {
  appLinks: {
    ios: {
      url: 'https://nextjs.org/ios',
      app_store_id: 'app_store_id',
    },
    android: {
      package: 'com.example.android/package',
      app_name: 'app_name_android',
    },
    web: {
      url: 'https://nextjs.org/web',
      should_fallback: true,
    },
  },
}
<head> output
<meta property="al:ios:url" content="https://nextjs.org/ios" />
<meta property="al:ios:app_store_id" content="app_store_id" />
<meta property="al:android:package" content="com.example.android/package" />
<meta property="al:android:app_name" content="app_name_android" />
<meta property="al:web:url" content="https://nextjs.org/web" />
<meta property="al:web:should_fallback" content="true" />

archives

Describe una colección de registros, documentos u otros materiales de interés histórico (fuente).

layout.js | page.js
export const metadata = {
  archives: ['https://nextjs.org/13'],
}
<head> output
<link rel="archives" href="https://nextjs.org/13" />

assets

layout.js | page.js
export const metadata = {
  assets: ['https://nextjs.org/assets'],
}
<head> output
<link rel="assets" href="https://nextjs.org/assets" />

bookmarks

layout.js | page.js
export const metadata = {
  bookmarks: ['https://nextjs.org/13'],
}
<head> output
<link rel="bookmarks" href="https://nextjs.org/13" />

category

layout.js | page.js
export const metadata = {
  category: 'technology',
}
<head> output
<meta name="category" content="technology" />

facebook

Puede conectar una aplicación de Facebook o una cuenta de Facebook a su página web para ciertos Plugins Sociales de Facebook Documentación de Facebook

Nota importante: Puede especificar appId o admins, pero no ambos.

layout.js | page.js
export const metadata = {
  facebook: {
    appId: '12345678',
  },
}
<head> output
<meta property="fb:app_id" content="12345678" />
layout.js | page.js
export const metadata = {
  facebook: {
    admins: '12345678',
  },
}
<head> output
<meta property="fb:admins" content="12345678" />

Si desea generar múltiples etiquetas meta fb:admins, puede usar un valor de array.

layout.js | page.js
export const metadata = {
  facebook: {
    admins: ['12345678', '87654321'],
  },
}
<head> output
<meta property="fb:admins" content="12345678" />
<meta property="fb:admins" content="87654321" />

other

Todas las opciones de metadatos deberían estar cubiertas usando el soporte incorporado. Sin embargo, puede haber etiquetas meta personalizadas específicas para su sitio, o nuevas etiquetas meta recién lanzadas. Puede usar la opción other para renderizar cualquier etiqueta meta personalizada.

layout.js | page.js
export const metadata = {
  other: {
    custom: 'meta',
  },
}
<head> output
<meta name="custom" content="meta" />

Si desea generar múltiples etiquetas meta con la misma clave, puede usar un valor de array.

layout.js | page.js
export const metadata = {
  other: {
    custom: ['meta1', 'meta2'],
  },
}
<head> output
<meta name="custom" content="meta1" /> <meta name="custom" content="meta2" />

Metadatos no admitidos

Los siguientes tipos de metadatos no tienen soporte incorporado actualmente. Sin embargo, aún pueden renderizarse en el layout o la página misma.

MetadatosRecomendación
<meta http-equiv="...">Use encabezados HTTP apropiados mediante redirect(), Middleware, o Encabezados de Seguridad
<base>Renderice la etiqueta en el layout o la página misma.
<noscript>Renderice la etiqueta en el layout o la página misma.
<style>Más información sobre estilos en Next.js.
<script>Más información sobre uso de scripts.
<link rel="stylesheet" />importe hojas de estilo directamente en el layout o la página misma.
<link rel="preload />Use el método preload de ReactDOM
<link rel="preconnect" />Use el método preconnect de ReactDOM
<link rel="dns-prefetch" />Use el método prefetchDNS de ReactDOM

Pistas de recursos (Resource hints)

El elemento <link> tiene varias palabras clave rel que pueden usarse para indicar al navegador que es probable que se necesite un recurso externo. El navegador usa esta información para aplicar optimizaciones de precarga según la palabra clave.

Aunque la API de Metadatos no admite directamente estas pistas, puede usar los nuevos métodos de ReactDOM para insertarlas de forma segura en el <head> del documento.

'use client'

import ReactDOM from 'react-dom'

export function PreloadResources() {
  ReactDOM.preload('...', { as: '...' })
  ReactDOM.preconnect('...', { crossOrigin: '...' })
  ReactDOM.prefetchDNS('...')

  return null
}
'use client'

import ReactDOM from 'react-dom'

export function PreloadResources() {
  ReactDOM.preload('...', { as: '...' })
  ReactDOM.preconnect('...', { crossOrigin: '...' })
  ReactDOM.prefetchDNS('...')

  return null
}

Inicia la carga de un recurso temprano en el ciclo de vida del renderizado de la página (navegador). Documentación MDN.

ReactDOM.preload(href: string, options: { as: string })
<head> output
<link rel="preload" href="..." as="..." />

Inicia preventivamente una conexión a un origen. Documentación MDN.

ReactDOM.preconnect(href: string, options?: { crossOrigin?: string })
<head> output
<link rel="preconnect" href="..." crossorigin />

Intenta resolver un nombre de dominio antes de que se soliciten los recursos. Documentación MDN.

ReactDOM.prefetchDNS(href: string)
<head> output
<link rel="dns-prefetch" href="..." />

Nota importante:

  • Estos métodos actualmente solo son compatibles con Componentes de Cliente (Client Components), que aún se renderizan en el servidor en la carga inicial de la página.
  • Las funciones integradas de Next.js como next/font, next/image y next/script manejan automáticamente las pistas de recursos relevantes.
  • React 18.3 aún no incluye definiciones de tipo para ReactDOM.preload, ReactDOM.preconnect y ReactDOM.preconnectDNS. Puede usar // @ts-ignore como solución temporal para evitar errores de tipo.

Tipos

Puede agregar seguridad de tipos a sus metadatos usando el tipo Metadata. Si está utilizando el plugin de TypeScript incorporado en su IDE, no necesita agregar manualmente el tipo, pero aún puede hacerlo explícitamente si lo desea.

Objeto metadata

import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'Next.js',
}

Función generateMetadata

Función regular

import type { Metadata } from 'next'

export function generateMetadata(): Metadata {
  return {
    title: 'Next.js',
  }
}

Función asíncrona

import type { Metadata } from 'next'

export async function generateMetadata(): Promise<Metadata> {
  return {
    title: 'Next.js',
  }
}

Con props de segmento

import type { Metadata } from 'next'

type Props = {
  params: { id: string }
  searchParams: { [key: string]: string | string[] | undefined }
}

export function generateMetadata({ params, searchParams }: Props): Metadata {
  return {
    title: 'Next.js',
  }
}

export default function Page({ params, searchParams }: Props) {}

Con metadatos padre

import type { Metadata, ResolvingMetadata } from 'next'

export async function generateMetadata(
  { params, searchParams }: Props,
  parent: ResolvingMetadata
): Promise<Metadata> {
  return {
    title: 'Next.js',
  }
}

Proyectos JavaScript

Para proyectos JavaScript, puede usar JSDoc para agregar seguridad de tipos.

/** @type {import("next").Metadata} */
export const metadata = {
  title: 'Next.js',
}

Historial de versiones

VersiónCambios
v13.2.0viewport, themeColor, y colorScheme obsoletos en favor de la configuración viewport.
v13.2.0Se introdujeron metadata y generateMetadata.