ewan's projects — docs
← all docs

@ewanc26/og

August 20, 2026 2 min read
typescriptsvelteimage-generationlibrarypkgs

@ewanc26/og generates OpenGraph images on the fly — bold typography, ALL CAPS site names, and a unique @ewanc26/noise background seeded per page. Built on Satori for the actual rendering, so it works in SvelteKit endpoints, edge runtimes, and plain build scripts alike, with zero native dependencies.

Part of the @ewanc26/pkgs monorepo.

Install

pnpm add @ewanc26/og

SvelteKit endpoint

// src/routes/og/[...path]/+server.ts
import { createOgEndpoint } from '@ewanc26/og';

export const GET = createOgEndpoint({
  siteName: 'ewancroft.uk',
  defaultTemplate: 'blog',
  cacheMaxAge: 86400, // 24 hours
});

Then reference it from a page:

<script>
  import { createOgImageUrl } from '@ewanc26/og';
</script>

<svelte:head>
  <meta property="og:image" content={createOgImageUrl('/og', {
    title: data.post.title,
    description: data.post.excerpt,
  })} />
</svelte:head>

Direct generation

Outside SvelteKit — a build script, a different framework, a one-off image — call the generator directly:

import { generateOgImage } from '@ewanc26/og';
import { writeFileSync } from 'fs';

const png = await generateOgImage({
  title: 'My Blog Post',
  description: 'A compelling description',
  siteName: 'ewancroft.uk',
  template: 'blog', // 'blog' | 'profile' | 'default'
});

writeFileSync('./og-image.png', png);

Templates

Template Description
blog (default) Massive title (72px), ALL CAPS site name, noise background, accent bar. Built for blog posts and articles.
profile Centered layout with a prominent avatar. Works well for user pages and about pages.
default Bold but minimal — a good fallback for generic pages.

Customisation

Colours — override the background, text, and accent used by a template:

await generateOgImage({
  title: 'My Page',
  siteName: 'mysite.com',
  colors: {
    background: '#1a1a2e',
    text: '#ffffff',
    accent: '#00d4ff',
  },
});

Fonts — the package bundles Inter; swap in your own:

await generateOgImage({
  title: 'My Page',
  siteName: 'mysite.com',
  fonts: {
    heading: './static/fonts/CustomFont-Bold.ttf',
    body: './static/fonts/CustomFont-Regular.ttf',
  },
});

Noise — disable it, or tune opacity and colour mode; the seed defaults to the title, so the same title always produces the same background:

await generateOgImage({
  title: 'My Page',
  siteName: 'mysite.com',
  noise: {
    enabled: true,
    opacity: 0.3,
    colorMode: 'grayscale',
  },
  noiseSeed: 'custom-seed', // optional, defaults to title
});

API

Function Returns
generateOgImage(options) Promise<Buffer> — PNG buffer
generateOgImageDataUrl(options) Promise<string> — base64 data URL
createOgEndpoint(options) RequestHandler — SvelteKit GET handler
createOgImageUrl(baseUrl, params) string — OG image URL with query parameters

Licence

AGPL-3.0-only.


← all docs