Cómo agregar metadatos y crear imágenes OG

Las API de Metadata pueden usarse para definir los metadatos de tu aplicación para mejorar el SEO y la capacidad de compartir en la web, e incluyen:

  1. El objeto estático metadata
  2. La función dinámica generateMetadata
  3. Convenciones especiales de archivos que pueden usarse para agregar favicons e imágenes OG estáticas o generadas dinámicamente.

Con todas las opciones anteriores, Next.js generará automáticamente las etiquetas <head> relevantes para tu página, las cuales pueden inspeccionarse en las herramientas de desarrollo del navegador.

Campos predeterminados

Hay dos etiquetas meta predeterminadas que siempre se agregan, incluso si una ruta no define metadatos:

<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

Los demás campos de metadatos pueden definirse con el objeto Metadata (para metadatos estáticos) o la función generateMetadata (para metadatos generados).

Metadatos estáticos

Para definir metadatos estáticos, exporta un objeto Metadata desde un archivo estático layout.js o page.js. Por ejemplo, para agregar un título y descripción a la ruta del blog:

import type { Metadata } from 'next'

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

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

export default function Page() {}

Puedes ver una lista completa de opciones disponibles en la documentación de generateMetadata.

Metadatos generados

Puedes usar la función generateMetadata para obtener (fetch) metadatos que dependen de datos. Por ejemplo, para obtener el título y descripción de una publicación de blog específica:

import type { Metadata, ResolvingMetadata } from 'next'

type Props = {
  params: Promise<{ slug: string }>
  searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}

export async function generateMetadata(
  { params, searchParams }: Props,
  parent: ResolvingMetadata
): Promise<Metadata> {
  const slug = (await params).slug

  // obtener información de la publicación
  const post = await fetch(`https://api.vercel.app/blog/${slug}`).then((res) =>
    res.json()
  )

  return {
    title: post.title,
    description: post.description,
  }
}

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

Internamente, Next.js transmitirá los metadatos por separado de la interfaz de usuario y los inyectará en el HTML tan pronto como se resuelvan.

Memorización de solicitudes de datos

Puede haber casos donde necesites obtener los mismos datos para los metadatos y la página en sí. Para evitar solicitudes duplicadas, puedes usar la función cache de React para memorizar el valor de retorno y obtener los datos solo una vez. Por ejemplo, para obtener la información de la publicación de blog tanto para los metadatos como para la página:

import { cache } from 'react'
import { db } from '@/app/lib/db'

// getPost se usará dos veces, pero se ejecutará solo una vez
export const getPost = cache(async (slug: string) => {
  const res = await db.query.posts.findFirst({ where: eq(posts.slug, slug) })
  return res
})

Metadatos basados en archivos

Los siguientes archivos especiales están disponibles para metadatos:

Puedes usarlos para metadatos estáticos, o generar estos archivos programáticamente con código.

Favicons

Los favicons son iconos pequeños que representan tu sitio en marcadores y resultados de búsqueda. Para agregar un favicon a tu aplicación, crea un archivo favicon.ico y colócalo en la raíz de la carpeta app.

Archivo especial Favicon dentro de la carpeta App junto a archivos layout y page

También puedes generar favicons programáticamente usando código. Consulta la documentación de favicons para más información.

Imágenes Open Graph estáticas

Las imágenes Open Graph (OG) son imágenes que representan tu sitio en redes sociales. Para agregar una imagen OG estática a tu aplicación, crea un archivo opengraph-image.png en la raíz de la carpeta app.

Archivo especial de imagen OG dentro de la carpeta App junto a archivos layout y page

También puedes agregar imágenes OG para rutas específicas creando un archivo opengraph-image.png más abajo en la estructura de carpetas. Por ejemplo, para crear una imagen OG específica para la ruta /blog, agrega un archivo opengraph-image.jpg dentro de la carpeta blog.

Archivo especial de imagen OG dentro de la carpeta blog

La imagen más específica tendrá prioridad sobre cualquier imagen OG que esté por encima en la estructura de carpetas.

También se admiten otros formatos de imagen como jpeg, png y webp. Consulta la documentación de Open Graph Image para más información.

Imágenes Open Graph generadas

El constructor ImageResponse te permite generar imágenes dinámicas usando JSX y CSS. Esto es útil para imágenes OG que dependen de datos.

Por ejemplo, para generar una imagen OG única para cada publicación de blog, agrega un archivo opengraph-image.ts dentro de la carpeta blog e importa el constructor ImageResponse desde next/og:

import { ImageResponse } from 'next/og'
import { getPost } from '@/app/lib/data'

// Metadatos de la imagen
export const size = {
  width: 1200,
  height: 630,
}

export const contentType = 'image/png'

// Generación de imagen
export default async function Image({ params }: { params: { slug: string } }) {
  const post = await getPost(params.slug)

  return new ImageResponse(
    (
      // Elemento JSX de ImageResponse
      <div
        style={{
          fontSize: 128,
          background: 'white',
          width: '100%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        {post.title}
      </div>
    )
  )
}

ImageResponse admite propiedades CSS comunes incluyendo flexbox y posicionamiento absoluto, fuentes personalizadas, ajuste de texto, centrado e imágenes anidadas. Consulta la lista completa de propiedades CSS admitidas.

Nota importante:

  • Hay ejemplos disponibles en el Vercel OG Playground.
  • ImageResponse usa @vercel/og, satori y resvg para convertir HTML y CSS a PNG.
  • Solo se admiten flexbox y un subconjunto de propiedades CSS. Los diseños avanzados (ej. display: grid) no funcionarán.

On this page