npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@ogify/core

v0.1.4

Published

Core types and utilities for OGify Open Graph image generator

Downloads

374

Readme

OGify - Beautiful Dynamic OG Images in Seconds

npm version License: MIT TypeScript

Generate stunning Open Graph images in seconds, not hours. OGify eliminates the complexity of OG image generation with zero-config font loading, automatic caching, and production-ready templates.

⚡ Why OGify?

  • 🔌 Zero-config: Works out of the box with Next.js, Remix, Astro, etc.
  • 🎨 No font management: Just specify a Google Font name - no downloads, no font files, no hassle.
  • 📦 No asset pipeline: Emojis load dynamically from CDNs.
  • 🖼️ Rich templates: OGify provides a set of production-ready templates with zero configuration.
  • Smart caching: OGify automatically caches fonts, emojis, and generated images - no configuration required.
  • 🛡️ Type-safe: Full TypeScript support catches errors before runtime.

📦 Installation

pnpm add @ogify/core

🚀 Quick Start

1. Define a Template

Create a template using defineTemplate with an HTML renderer function:

import { defineTemplate, OgTemplateOptions } from '@ogify/core';

const blogTemplate = defineTemplate({
  id: 'blog-post',
  name: 'Blog Post',
  description: 'Template for blog post OG images',
  fonts: [
    { name: 'Inter', weight: 700 },
    { name: 'Inter', weight: 400 }
  ],
  renderer: ({ params }: OgTemplateOptions) => {
    return `
      <div style="display: flex; flex-direction: column; width: 100%; height: 100%; background: white; padding: 40px;">
        <h1 style="font-size: 60px; font-weight: 700; color: #000;">
          ${params.title}
        </h1>
        <p style="font-size: 30px; color: #666;">
          ${params.description}
        </p>
      </div>
    `;
  },
});

2. Create a Renderer

Create a renderer instance and register your templates:

import { createTemplateRenderer } from '@ogify/core';

const renderer = createTemplateRenderer({
  templates: [blogTemplate],
  defaultParams: {
    brand: 'My Company'
  }
});

3. Generate an Image

Render a template to a PNG buffer:

// Basic usage (1200x630)
const imageBuffer = await renderer.renderToImage('blog-post', {
  title: 'Hello World',
  description: 'My first OG image'
});

// Custom dimensions for Twitter (1200x675)
const twitterImage = await renderer.renderToImage('blog-post', {
  title: 'Hello World'
}, {
  width: 1200,
  height: 675
});

That's it! You're ready for production. No font files to download, no build configuration, no asset pipeline.

🚀 Time-Saving Features

Zero-Config Google Fonts

Traditional approach (manual setup):

// ❌ Manual: Download fonts, manage files, configure paths
import fs from 'fs';
const fontData = fs.readFileSync('./fonts/Inter-Bold.ttf');
const font2Data = fs.readFileSync('./fonts/Inter-Regular.ttf');

const fonts = [
  { name: 'Inter', data: fontData, weight: 700 },
  { name: 'Inter', data: font2Data, weight: 400 }
];

OGify approach (zero config):

// ✅ OGify: Just specify the font name - we handle the rest
const template = defineTemplate({
  fonts: [
    { name: 'Inter', weight: 700 },  // Automatically loaded from Google Fonts
    { name: 'Inter', weight: 400 }
  ],
  // ...
});

Time saved: ~15 minutes per font family

Automatic Caching

// First render: Downloads fonts from Google (~500ms)
await renderer.renderToImage('blog-post', { title: 'Post 1' });

// Second render: Uses cached fonts (~50ms) - 10x faster! ⚡
await renderer.renderToImage('blog-post', { title: 'Post 2' });

// All subsequent renders: Lightning fast
await renderer.renderToImage('blog-post', { title: 'Post 3' });

Performance: 10x faster after first render, no configuration needed

Dynamic Emoji Loading

// ✅ Emojis just work - loaded dynamically from CDN
renderer: ({ params }) => `
  <div>
    <h1>${params.title}</h1>
    <div>👋 😄 🎉 🚀</div>  <!-- Automatically rendered -->
  </div>
`

Time saved: No emoji sprite sheets, no asset management, no build step

📚 Advanced Usage

Custom Fonts

Load fonts from Google Fonts, custom URLs, or embedded data:

const template = defineTemplate({
  id: 'custom-fonts',
  name: 'Custom Fonts Template',
  description: 'Template with custom fonts',
  fonts: [
    // Google Fonts (automatic)
    { name: 'Roboto', weight: 400 },
    
    // Custom URL
    { name: 'MyFont', url: 'https://example.com/font.woff2', weight: 700 },
    
    // Embedded data
    { name: 'EmbeddedFont', data: fontBuffer, weight: 400 }
  ],
  renderer: ({ params }) => `<div>${params.title}</div>`
});

Emoji Support

Choose from multiple emoji providers:

const template = defineTemplate({
  id: 'emoji-template',
  name: 'Emoji Template',
  description: 'Template with emoji support',
  fonts: [{ name: 'Inter', weight: 400 }],
  emojiProvider: 'twemoji', // or 'fluent', 'noto', 'openmoji', etc.
  renderer: ({ params }) => `
    <div>
      <h1>${params.title}</h1>
      <div>👋 😄 🎉</div>
    </div>
  `
});

Lifecycle Hooks

Add custom logic before and after rendering:

const renderer = createTemplateRenderer({
  templates: [blogTemplate],
  beforeRender: async (templateId, params) => {
    console.log(`Rendering ${templateId}`, params);
    // Log analytics, validate params, etc.
  },
  afterRender: async (templateId, params, imageBuffer) => {
    console.log(`Rendered ${templateId} successfully`);
    // Cache image, send notifications, etc.
  }
});

Platform-Specific Dimensions

Generate images for different platforms:

// Facebook/LinkedIn (1200x630)
const facebookImage = await renderer.renderToImage('blog-post', params);

// Twitter (1200x675)
const twitterImage = await renderer.renderToImage('blog-post', params, {
  width: 1200,
  height: 675
});

🎨 Template Features

Supported CSS Properties

Templates support a subset of CSS properties via Satori:

  • Layout: display: flex, flexDirection, alignItems, justifyContent
  • Spacing: padding, margin, gap
  • Typography: fontSize, fontWeight, color, lineHeight, textAlign
  • Background: backgroundColor, backgroundImage
  • Border: border, borderRadius
  • Size: width, height, maxWidth, maxHeight

Tailwind-like Utilities

You can use Tailwind-like class names:

renderer: ({ params }) => `
  <div class="flex flex-col items-center justify-center w-full h-full bg-white p-4">
    <h1 class="text-[60px] font-bold text-black">${params.title}</h1>
    <p class="text-[30px] text-gray-600">${params.description}</p>
  </div>
`

📖 API Reference

defineTemplate(config)

Defines a new OG template.

Parameters:

  • id (string): Unique identifier
  • name (string): Human-readable name
  • description (string): Template description
  • renderer (function): Function that returns HTML string
  • fonts (array): Array of font configurations
  • emojiProvider (optional): Emoji provider to use

Returns: OgTemplate

createTemplateRenderer(config)

Creates a new template renderer instance.

Parameters:

  • templates (array): Array of template definitions
  • defaultParams (optional): Default parameters for all templates
  • beforeRender (optional): Hook called before rendering
  • afterRender (optional): Hook called after rendering

Returns: TemplateRenderer

renderer.renderToImage(templateId, params, options?)

Renders a template to a PNG buffer.

Parameters:

  • templateId (string): ID of the template to render
  • params (object): Parameters to pass to the template
  • options (optional): Rendering options
    • width (number): Image width (default: 1200)
    • height (number): Image height (default: 630)

Returns: Promise<Buffer>

renderer.getTemplate(id)

Retrieves a template by ID.

Returns: OgTemplate | undefined

renderer.getTemplateIds()

Gets all registered template IDs.

Returns: string[]

⚡ Performance & Production

Automatic Caching (Zero Config)

OGify automatically caches fonts and emojis in memory - no configuration required:

// First render: Downloads fonts from Google Fonts (~500ms)
await renderer.renderToImage('blog-post', { title: 'Post 1' });

// Second render: Uses cached fonts (~50ms) - 10x faster! ⚡
await renderer.renderToImage('blog-post', { title: 'Post 2' });

// Third+ renders: Lightning fast from cache
await renderer.renderToImage('blog-post', { title: 'Post 3' });

📋 Changelog

See CHANGELOG.md for a complete history of changes and releases.

🤝 Contributing

We welcome contributions! Please see our contributing guidelines.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Credits

Built on top of: