Langsung ke konten
Tutorial

Hasilkan gambar Open Graph dengan satu panggilan API, tidak diperlukan Next.js

| 6 min read

Gunakan API gambar botoi OG untuk menghasilkan kartu sosial PNG 1200x630 dari kerangka apa pun. Bekerja dengan platform Astro, Django, Rails, Laravel, dan CMS tanpa kepala.

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

Posting blog Anda dibagikan di Twitter. Alih-alih pratinjau kaya dengan kartu judul, tautannya menampilkan a kotak abu-abu kosong. Atau lebih buruk lagi, favicon yang memanjang. Setiap pembagian tanpa gambar OG yang tepat adalah klik yang terlewat.

Solusi yang populer adalah solusi Vercel @vercel/og perpustakaan. Ini berfungsi dengan baik, tetapi terkunci Infrastruktur Next.js dan Vercel. Satori (mesin di baliknya) membutuhkan runtime Node.js dengan spesifik kemampuan memuat font. Jika Anda membangun dengan Astro, Django, Rails, Laravel, Hugo, atau lainnya kerangka kerja, Anda sendirian.

Ada pendekatan yang lebih sederhana: kirim satu permintaan POST ke API dan dapatkan kembali PNG 1200x630 yang sudah jadi. Tidak ada ketergantungan Node.js. Tidak ada penguncian kerangka kerja. Tidak ada pipeline rendering gambar yang perlu dipertahankan.

Satu permintaan POST, satu PNG kembali

Itu botoi DAN API gambar menerima isi JSON dengan judul, deskripsi, dan preferensi tema Anda. Ini mengembalikan data biner PNG mentah.

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

Itu saja. Responsnya adalah file PNG yang dapat Anda simpan, sajikan, atau unggah ke CDN:

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

(binary PNG data, 1200x630px)

API menangani tipografi, tata letak, dan ukuran yang tepat. Anda memasukkan teks, Anda mengeluarkan gambar.

Integrasi Astro: menghasilkan gambar OG pada waktu pembuatan

Pembuatan situs statis Astro menjadikannya sangat bersih. Buat rute API dinamis yang mengambil Gambar OG selama pembuatan dan menyajikannya sebagai gambar statis .png file.

// 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',
    },
  });
};

Selama astro build, rute ini menghasilkan PNG untuk setiap postingan. File keluaran masuk milikmu dist/og/ direktori sebagai aset statis. Tidak ada pembuatan gambar runtime, tidak ada serverless berfungsi, tidak ada start dingin.

Referensi gambar di kepala halaman Anda:

<!-- 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\`} />

Setiap halaman mendapat kartu sosial unik, dihasilkan satu kali selama pembuatan dan disimpan dalam cache selamanya oleh CDN.

Integrasi Django dan Rails

Kerangka kerja yang dirender oleh server dapat menghasilkan gambar OG sesuai permintaan dan menyimpan hasilnya dalam cache.

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'),
]

Itu @cache_page dekorator menyimpan gambar yang dihasilkan selama 24 jam. Setelah yang pertama permintaan, Django menyajikan PNG yang di-cache secara langsung tanpa menekan API lagi.

Rel

# 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'

Kedua contoh tersebut mengikuti pola yang sama: cari postingan berdasarkan slug, POST judul dan deskripsinya ke API, dan kembalikan PNG dengan header cache. Kerangka kerja ini menangani caching; yang ditangani API generasi gambar.

Integrasi CMS tanpa kepala: hasilkan saat dipublikasikan

Jika konten Anda berada di CMS tanpa kepala seperti Strapi, Contentful, atau Sanity, Anda dapat membuat OG gambar setiap kali editor menerbitkan atau memperbarui postingan. Pasang webhook yang mengaktifkan konten perubahan.

Pengendali webhook umum

// 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}\`);
}

Kait siklus hidup 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' },
    });
  },
};

Pendekatan ini berguna untuk tim yang editor kontennya mempublikasikan melalui CMS dan pengembang tidak ingin menjalankan pipeline build untuk setiap perubahan teks. Gambar OG dibuat ulang secara otomatis ketika perubahan judul atau deskripsi postingan.

Bonus: ekstrak metadata OG dari URL mana pun

Botoi API juga menyediakan /v1/url-metadata, yang melakukan kebalikannya: jika diberi URL, URL akan diambil halaman dan mengekstrak tag Open Graph-nya. Ini berguna untuk membangun pratinjau tautan, kartu sosial validator, atau alat audit 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"}'

Tanggapan:

{
  "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"
    }
  }
}

Gunakan ini untuk membuat komponen pratinjau tautan di aplikasi Anda:

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,
  };
}

Gabungkan kedua titik akhir: gunakan /v1/url-metadata untuk memeriksa bagaimana halaman Anda muncul di media sosial platform, dan /v1/og/generate untuk membuat gambar yang membuatnya terlihat bagus.

Mengapa tidak menjalankan Satori sendiri?

Anda bisa. Satori bersifat open source dan menghasilkan keluaran berkualitas. Namun menjalankannya sendiri berarti:

  • Menginstal dan menggabungkan font khusus (Satori tidak menggunakan font sistem)
  • Menyiapkan runtime Node.js atau Fungsi Edge untuk rendering gambar
  • Menulis template JSX-ke-SVG dan mengonversi SVG ke PNG dengan resvg
  • Menangani batas memori pada platform tanpa server saat merender gambar berukuran besar
  • Mempertahankan jalur pipa seiring berkembangnya API Satori

Panggilan API menggantikan semua itu dengan satu permintaan HTTP. Jika kebutuhan gambar OG Anda adalah lugas (judul + deskripsi + branding), pendekatan API menghemat waktu penyiapan dan pemeliharaan berkelanjutan.

FAQ

Berapa ukuran gambar OG yang dihasilkan?
Setiap gambar berukuran 1200x630 piksel, ukuran gambar Open Graph standar yang direkomendasikan oleh Facebook, Twitter/X, LinkedIn, dan Slack. Outputnya adalah file PNG.
Apakah saya memerlukan kunci API?
Tidak. Tingkat gratis mengizinkan 5 permintaan per menit tanpa kunci API. Untuk membangun saluran pipa atau situs dengan lalu lintas tinggi yang menghasilkan gambar pada setiap tampilan halaman, ambil kunci dari halaman dokumen botoi API untuk membuka batas kecepatan yang lebih tinggi.
Bisakah saya menyesuaikan font, warna, atau tata letak?
Parameter tema menerima "terang" atau "gelap" untuk mengontrol skema warna keseluruhan. API menangani tipografi dan tata letak secara otomatis berdasarkan judul dan panjang deskripsi Anda. Untuk desain kustom lengkap, buat gambar dasar Anda dengan API dan pasca-proses dengan logika overlay Anda sendiri.
Seberapa cepat pembuatan gambar?
API ini berjalan pada Cloudflare Workers di edge. Sebagian besar permintaan mengembalikan PNG yang sudah selesai dalam waktu kurang dari 500 md. Jika Anda menyimpan hasilnya dalam cache (disarankan untuk situs statis), pembuatan hanya terjadi satu kali per kombinasi unik judul, deskripsi, dan tema.
Apa yang dilakukan titik akhir /v1/url-metadata?
POST URL ke /v1/url-metadata dan API mengambil halaman tersebut, mengurai HTML-nya, dan mengembalikan metadata Open Graph terstruktur: og:title, og:description, og:image, og:type, dan tag Twitter Card. Gunakan untuk melihat pratinjau tampilan URL apa pun saat dibagikan di media sosial, atau untuk menarik metadata ke pratinjau tautan Anda sendiri.

Mulai membangun dengan botoi

150+ endpoint API untuk pencarian, pemrosesan teks, pembuatan gambar, dan utilitas developer. Paket gratis, tanpa kartu kredit.