Skip to content
/ shotog Public

Screenshot & OG Images. One API Call. — Edge-native OG image generation API powered by Cloudflare Workers.

License

Notifications You must be signed in to change notification settings

nicepkg/shotog

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ShotOG

Beautiful OG images. One API call.

Generate stunning Open Graph images for your website with a single URL — no design tools, no headless browsers, no infrastructure to manage.

Live Demo License: MIT API Status

ShotOG Basic Template

Why ShotOG?

Every page you share on Twitter, Slack, or Discord needs an OG image. You can:

  1. Design each one manually in Figma (doesn't scale)
  2. Run a headless browser on your server (slow, expensive, breaks)
  3. Call ShotOG's API — one URL, beautiful image, ~50ms at the edge

ShotOG runs on Cloudflare Workers. No cold starts. No servers. Just fast images.

Quick Start

Option 1: Just use a URL

Drop this into your HTML <head>:

<meta property="og:image" content="https://shotog.2214962083.workers.dev/v1/og?title=My%20Page%20Title&template=blog&author=John" />

That's it. No signup required for up to 10 images/day.

Option 2: Use the TypeScript SDK

npm install shotog
import { ShotOG } from "shotog";

const og = new ShotOG({ apiKey: "sk_..." }); // optional, increases rate limit

// Generate a URL (no network request)
const imageUrl = og.url({
  title: "How We Scaled to 1M Users",
  subtitle: "A deep dive into our infrastructure",
  template: "blog",
  author: "Jane Smith",
});
// → https://shotog.2214962083.workers.dev/v1/og?title=How+We+Scaled...

// Or fetch the image binary directly
const imageBuffer = await og.generate({
  title: "Product Launch",
  template: "announcement",
});

Option 3: cURL

# GET — returns PNG directly
curl "https://shotog.2214962083.workers.dev/v1/og?title=Hello&template=basic" -o og.png

# POST — JSON body, more options
curl -X POST https://shotog.2214962083.workers.dev/v1/og \
  -H "Content-Type: application/json" \
  -d '{"title":"Hello World","template":"product","subtitle":"Built with ShotOG"}' \
  -o og.png

Templates

8 professionally designed templates for every use case:

Template Best For Preview
basic General pages, social sharing
blog Blog posts, articles
product SaaS products, launches
social Social media posts
event Events, webinars
changelog Release notes
testimonial Customer quotes
announcement Major updates, launches

Browse all templates →

API Reference

Generate OG Image

GET /v1/og?title=...&template=...
POST /v1/og  (JSON body)

Parameters:

Parameter Type Required Description
title string Yes Main heading text
template string No Template name (default: basic)
subtitle string No Secondary text
eyebrow string No Small text above title (category, label)
author string No Author name
avatar string No Avatar image URL (shown in blog/social/testimonial)
logo string No Logo image URL (shown in basic/product)
fontUrl string No URL to TTF/OTF font file (max 5MB, cached 1h)
domain string No Domain watermark
bgColor string No Background color (hex, e.g. 1a1a2e)
textColor string No Text color (hex)
accentColor string No Accent color (hex)
format string No png (default) or svg
width number No Image width 200-2400 (default: 1200)
height number No Image height 200-1260 (default: 630)
api_key string No API key for higher limits

Batch Generate (up to 20 images)

curl -X POST https://shotog.2214962083.workers.dev/v1/og/batch \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: sk_..." \
  -d '{
    "images": [
      {"id": "hero", "title": "My Product", "template": "product"},
      {"id": "blog-1", "title": "First Post", "template": "blog", "author": "Alice"},
      {"id": "blog-2", "title": "Second Post", "template": "blog", "author": "Bob"}
    ],
    "defaults": {"format": "png", "width": 1200, "domain": "example.com"}
  }'

Response:

{
  "results": [
    {"id": "hero", "success": true, "dataUri": "data:image/png;base64,..."},
    {"id": "blog-1", "success": true, "dataUri": "data:image/png;base64,..."},
    {"id": "blog-2", "success": true, "dataUri": "data:image/png;base64,..."}
  ],
  "summary": {"total": 3, "succeeded": 3, "failed": 0}
}

Batch features:

  • Max 20 images per request
  • defaults object applies to all images (individual params override)
  • Parallel rendering via Promise.allSettled
  • Quota pre-check: if insufficient quota, returns 429 before rendering
  • Only successful renders count toward usage

Get API Key (Self-Service)

curl -X POST https://shotog.2214962083.workers.dev/v1/keys \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com"}'

Returns:

{
  "id": "key_abc123",
  "key": "sk_live_...",
  "tier": "free",
  "monthly_limit": 500,
  "message": "Store your API key safely — it cannot be retrieved later."
}

Check Usage

curl https://shotog.2214962083.workers.dev/v1/keys/usage \
  -H "X-Api-Key: sk_live_..."

List Templates

curl https://shotog.2214962083.workers.dev/v1/og/templates

SDK

The TypeScript/JavaScript SDK wraps all API functionality:

import { ShotOG } from "shotog";

// Initialize
const og = new ShotOG({ apiKey: "sk_..." });

// Build image URL (no network call)
og.url({ title: "My Post", template: "blog" });

// Generate image binary
await og.generate({ title: "My Post", template: "blog" });

// List templates
await og.templates();

// Check usage
await og.usage();

// Create a new API key (static method)
await ShotOG.createKey("email@example.com");

Framework Examples

Next.js

// app/layout.tsx
export function generateMetadata({ params }) {
  return {
    openGraph: {
      images: [`https://shotog.2214962083.workers.dev/v1/og?title=${encodeURIComponent(params.title)}&template=blog`],
    },
  };
}

Astro

---
const ogImage = `https://shotog.2214962083.workers.dev/v1/og?title=${encodeURIComponent(title)}&template=product`;
---
<meta property="og:image" content={ogImage} />

Hugo

{{ $ogImage := printf "https://shotog.2214962083.workers.dev/v1/og?title=%s&template=blog&author=%s" (querify .Title) (querify .Params.author) }}
<meta property="og:image" content="{{ $ogImage }}" />

Tech Stack

  • Runtime: Cloudflare Workers (edge, ~17ms cold start)
  • Framework: Hono (lightweight, fast)
  • Rendering: @cf-wasm/satori (JSX → SVG at the edge)
  • Rasterizer: @cf-wasm/resvg (SVG → PNG)
  • Database: Cloudflare D1 (API keys + usage tracking)
  • Caching: Built-in CDN cache headers

Self-Hosting

ShotOG is MIT licensed. Deploy your own instance:

git clone https://github.com/nicepkg/shotog.git
cd shotog
npm install

# Set up D1 database
npx wrangler d1 create shotog-prod
# Update wrangler.toml with your database_id
npx wrangler d1 execute shotog-prod --file=./migrations/001_init.sql

# Deploy
npx wrangler deploy

Pricing

Plan Price Monthly Images Rate Limit
Demo Free 10/day 10/day
Free Free 500/month 60/min
Starter $9/mo 5,000/month 120/min
Pro $29/mo 25,000/month 300/min
Scale $79/mo 100,000/month 600/min

See pricing details →

License

MIT

Links