Ir al contenido
Tutorial

Genere imágenes Open Graph con una llamada API, no se requiere Next.js

| 6 min read

Utilice la API de imágenes botoi OG para generar tarjetas sociales PNG de 1200x630 desde cualquier marco. Funciona con plataformas Astro, Django, Rails, Laravel y CMS sin cabeza.

Social media preview cards on various platforms
Photo by dole777 on Unsplash

La publicación de tu blog se comparte en Twitter. En lugar de una vista previa enriquecida con una tarjeta de título, el enlace muestra una cuadro gris en blanco. O peor aún, un favicon estirado. Cada acción sin una imagen OG adecuada es un clic perdido.

La solución popular es la de Vercel. @vercel/og biblioteca. Funciona bien, pero está bloqueado. Next.js y la infraestructura de Vercel. Satori (el motor detrás de esto) necesita un tiempo de ejecución de Node.js con características específicas. capacidades de carga de fuentes. Si estás construyendo con Astro, Django, Rails, Laravel, Hugo o cualquier otro marco, estás solo.

Existe un enfoque más simple: envíe una solicitud POST a una API y obtenga un PNG terminado de 1200x630. Sin dependencia de Node.js. Sin bloqueo del marco. No hay canalización de renderizado de imágenes que mantener.

Una solicitud POST, un PNG de regreso

La botoi Y API de imagen acepta un cuerpo JSON con su título, descripción y preferencia de tema. Devuelve datos binarios PNG sin formato.

curl -X POST https://api.botoi.com/v1/og/generate \\
  -H "Content-Type: application/json" \\
  -d '{
    "title": "How to build a REST API in Go",
    "description": "A step-by-step guide with net/http and no frameworks",
    "theme": "dark"
  }' \\
  --output og-image.png

Eso es todo. La respuesta es un archivo PNG que puede guardar, servir o cargar en una CDN:

HTTP/1.1 200 OK
Content-Type: image/png
Content-Length: 48271

(binary PNG data, 1200x630px)

La API maneja la tipografía, el diseño y el tamaño adecuado. Pasas texto y obtienes una imagen.

Integración Astro: genere imágenes OG en el momento de la construcción

La generación de sitios estáticos de Astro hace que esto sea especialmente limpio. Cree una ruta API dinámica que obtenga Imágenes OG durante la construcción y las sirve como estáticas .png archivos.

// src/pages/og/[slug].png.ts
import type { APIRoute, GetStaticPaths } from 'astro';

// Your posts data source (markdown, CMS, database, etc.)
import { getAllPosts } from '@/lib/posts';

export const getStaticPaths: GetStaticPaths = async () => {
  const posts = await getAllPosts();
  return posts.map((post) => ({
    params: { slug: post.slug },
    props: { title: post.title, description: post.description },
  }));
};

export const GET: APIRoute = async ({ props }) => {
  const res = await fetch('https://api.botoi.com/v1/og/generate', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      title: props.title,
      description: props.description,
      theme: 'dark',
    }),
  });

  const imageBuffer = await res.arrayBuffer();

  return new Response(imageBuffer, {
    headers: {
      'Content-Type': 'image/png',
      'Cache-Control': 'public, max-age=31536000, immutable',
    },
  });
};

Durante astro build, esta ruta genera un PNG para cada publicación. Los archivos de salida aterrizan en tu dist/og/ directorio como activos estáticos. Sin generación de imágenes en tiempo de ejecución, sin servidor función, sin arranques en frío.

Haga referencia a las imágenes en el encabezado de su página:

<!-- In your BaseLayout.astro or page head -->
<meta property="og:image" content={\`https://yoursite.com/og/\${slug}.png\`} />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content={\`https://yoursite.com/og/\${slug}.png\`} />

Cada página recibe una tarjeta social única, generada una vez durante la construcción y almacenada en caché para siempre por las CDN.

Integración de Django y Rails

Los marcos renderizados por el servidor pueden generar imágenes OG a pedido y almacenar en caché el resultado.

Django

# views.py
import requests
from django.http import HttpResponse
from django.views.decorators.cache import cache_page


@cache_page(60 * 60 * 24)  # Cache for 24 hours
def og_image(request, slug):
    post = get_object_or_404(Post, slug=slug)

    response = requests.post(
        'https://api.botoi.com/v1/og/generate',
        json={
            'title': post.title,
            'description': post.description,
            'theme': 'dark',
        },
        timeout=5,
    )

    return HttpResponse(
        response.content,
        content_type='image/png',
    )
# urls.py
urlpatterns = [
    path('og/<slug:slug>.png', views.og_image, name='og_image'),
]

La @cache_page El decorador almacena la imagen generada durante 24 horas. Después del primero solicitud, Django sirve el PNG almacenado en caché directamente sin volver a acceder a la API.

Rieles

# app/controllers/og_images_controller.rb
class OgImagesController < ApplicationController
  def show
    post = Post.find_by!(slug: params[:slug])

    response = HTTP.post(
      'https://api.botoi.com/v1/og/generate',
      json: {
        title: post.title,
        description: post.description,
        theme: 'dark'
      }
    )

    expires_in 24.hours, public: true
    send_data response.body.to_s, type: 'image/png', disposition: 'inline'
  end
end
# config/routes.rb
get 'og/:slug.png', to: 'og_images#show'

Ambos ejemplos siguen el mismo patrón: buscar la publicación por slug, PUBLICAR el título y la descripción. a la API y devolver el PNG con encabezados de almacenamiento en caché. El marco maneja el almacenamiento en caché; la API maneja generación de imágenes.

Integración de CMS sin cabeza: generar al publicar

Si su contenido se encuentra en un CMS sin cabeza como Strapi, Contentful o Sanity, puede generar OG imágenes cada vez que un editor publica o actualiza una publicación. Conecte un webhook que se active en el contenido cambios.

Controlador de webhook genérico

// Webhook handler (any Node.js server or serverless function)
import { writeFileSync } from 'fs';

export async function handleCmsPublish(payload) {
  const { title, description, slug } = payload.entry;

  const res = await fetch('https://api.botoi.com/v1/og/generate', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ title, description, theme: 'light' }),
  });

  const buffer = Buffer.from(await res.arrayBuffer());

  // Save to your public/static directory or upload to S3/R2
  writeFileSync(\`./public/og/\${slug}.png\`, buffer);

  console.log(\`Generated OG image for: \${slug}\`);
}

Gancho del ciclo de vida de Strapi

// Strapi lifecycle hook: src/api/post/content-types/post/lifecycles.js
module.exports = {
  async afterUpdate(event) {
    const { result } = event;

    const res = await fetch('https://api.botoi.com/v1/og/generate', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        title: result.title,
        description: result.description,
        theme: 'dark',
      }),
    });

    // Upload to your CDN or save locally
    const buffer = Buffer.from(await res.arrayBuffer());
    await strapi.plugins.upload.services.upload.upload({
      data: { path: \`og/\${result.slug}.png\` },
      files: { buffer, name: \`\${result.slug}.png\`, type: 'image/png' },
    });
  },
};

Este enfoque es útil para equipos donde los editores de contenido publican a través de un CMS y los desarrolladores no. desea ejecutar una canalización de compilación para cada cambio de texto. La imagen OG se regenera automáticamente cuando cambios en el título o descripción de la publicación.

Bonificación: extrae metadatos de OG de cualquier URL

La API de botoi también proporciona /v1/url-metadata, que hace lo contrario: dada una URL, recupera la página y extrae sus etiquetas Open Graph. Esto es útil para crear vistas previas de enlaces y tarjetas sociales. validadores o herramientas de auditoría SEO.

curl -X POST https://api.botoi.com/v1/url-metadata \\
  -H "Content-Type: application/json" \\
  -d '{"url": "https://github.com/astro-community/astro-embed"}'

Respuesta:

{
  "success": true,
  "data": {
    "url": "https://github.com/astro-community/astro-embed",
    "status": 200,
    "title": "GitHub - astro-community/astro-embed",
    "description": "Components to embed third-party media in Astro projects",
    "og": {
      "title": "astro-embed",
      "description": "Components to embed third-party media in Astro projects",
      "image": "https://opengraph.githubassets.com/...",
      "type": "object",
      "url": "https://github.com/astro-community/astro-embed",
      "site_name": "GitHub"
    }
  }
}

Utilice esto para crear componentes de vista previa de enlaces en su aplicación:

async function getLinkPreview(url: string) {
  const res = await fetch('https://api.botoi.com/v1/url-metadata', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ url }),
  });

  const { data } = await res.json();

  return {
    title: data.og?.title ?? data.title,
    description: data.og?.description ?? data.description,
    image: data.og?.image,
    siteName: data.og?.site_name,
  };
}

Combine ambos puntos finales: use /v1/url-metadata para comprobar cómo aparecen sus páginas en las redes sociales plataformas, y /v1/og/generate para crear las imágenes que las hagan lucir bien.

¿Por qué no diriges Satori tú mismo?

Puede. Satori es de código abierto y produce resultados de calidad. Pero ejecutarlo usted mismo significa:

  • Instalar y agrupar fuentes personalizadas (Satori no usa fuentes del sistema)
  • Configurar un tiempo de ejecución de Node.js o una función Edge para renderizar imágenes
  • Escribir plantillas JSX a SVG y convertir SVG a PNG con resvg
  • Manejo de límites de memoria en plataformas sin servidor al renderizar imágenes grandes
  • Mantener el proceso a medida que evoluciona la API de Satori

Una llamada API reemplaza todo eso con una única solicitud HTTP. Si su imagen OG necesita son Sencillo (título + descripción + marca), el enfoque API ahorra horas de configuración y mantenimiento continuo.

FAQ

¿De qué tamaño son las imágenes OG generadas?
Cada imagen tiene 1200x630 píxeles, el tamaño de imagen estándar de Open Graph recomendado por Facebook, Twitter/X, LinkedIn y Slack. El resultado es un archivo PNG.
¿Necesito una clave API?
No. El nivel gratuito permite 5 solicitudes por minuto sin clave API. Para crear canalizaciones o sitios de alto tráfico que generan imágenes en cada vista de página, obtenga una clave de la página de documentos de la API de botoi para desbloquear límites de velocidad más altos.
¿Puedo personalizar fuentes, colores o diseño?
El parámetro del tema acepta "claro" u "oscuro" para controlar la combinación de colores general. La API maneja la tipografía y el diseño automáticamente según el título y la longitud de la descripción. Para diseños completamente personalizados, genere su imagen base con la API y postprocésela con su propia lógica de superposición.
¿Qué tan rápida es la generación de imágenes?
La API se ejecuta en Cloudflare Workers en el borde. La mayoría de las solicitudes devuelven un PNG terminado en menos de 500 ms. Si almacena en caché el resultado (recomendado para sitios estáticos), la generación solo ocurre una vez por combinación única de título, descripción y tema.
¿Qué hace el punto final /v1/url-metadata?
PUBLICAR una URL en /v1/url-metadata y la API buscará esa página, analizará su HTML y devolverá metadatos estructurados de Open Graph: og:title, og:description, og:image, og:type y etiquetas de Twitter Card. Úselo para obtener una vista previa de cómo aparece cualquier URL cuando se comparte en las redes sociales o para incorporar metadatos en sus propias vistas previas de enlaces.

Empieza a construir con botoi

150+ endpoints de API para consultas, procesamiento de texto, generacion de imagenes y utilidades para desarrolladores. Plan gratuito, sin tarjeta de credito.