PHPackages                             void/og-image - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. void/og-image

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

void/og-image
=============

A minimal Open Graph Image generator library

v1.0.0(3mo ago)016↓90%MITPHPPHP &gt;=8.2CI passing

Since Mar 26Pushed 3mo agoCompare

[ Source](https://github.com/raphalogou/og-image)[ Packagist](https://packagist.org/packages/void/og-image)[ RSS](/packages/void-og-image/feed)WikiDiscussions 1.x Synced 3w ago

READMEChangelog (1)Dependencies (5)Versions (2)Used By (0)

OG Image
========

[](#og-image)

A standalone PHP library for generating dynamic Open Graph (OG) images, with optional Symfony bundle integration.

Overview
--------

[](#overview)

OG Image provides a flexible, extensible system to programmatically generate custom Open Graph images. Perfect for creating dynamic social media preview images with titles, descriptions, badges, and custom themes.

**Works standalone** or as a **Symfony bundle** - use it however you prefer!

Features
--------

[](#features)

- 🎨 **Customizable Themes** - Define colors, backgrounds, and fonts
- 📐 **Flexible Layout System** - Built-in layouts and easy to extend
- 🏷️ **Badge Support** - Add category/status badges to your images
- 🔄 **Multiple Formats** - Render to WebP (default) or PNG
- 🚀 **Simple API** - Intuitive, functional approach with immediate rendering
- 🔌 **Zero Dependencies** - Core library has no external dependencies (except Intervention Image)
- 🎯 **Standalone &amp; Bundle** - Use as a library or register as a Symfony bundle

Requirements
------------

[](#requirements)

- PHP 8.2+
- Intervention Image 3.11+
- **Image Driver**: One of:
    - **GD** (bundled with PHP, recommended)
    - **Imagick** (optional, for better performance)

**Optional (for Symfony integration):**

- Symfony 7.4 or 8.0+

At least one image driver must be available. GD is included with most PHP installations by default.

Installation
------------

[](#installation)

### Via Composer

[](#via-composer)

```
composer require void/og-image
```

Quick Start - Standalone
------------------------

[](#quick-start---standalone)

```
use Intervention\Image\ImageManager;
use Void\OgImage\Generator;
use Void\OgImage\Model\ImageContent;
use Void\OgImage\Layout\StandardLayout;
use Void\OgImage\Enum\Format;

// Initialize image manager with your driver
$imageManager = ImageManager::gd();  // or ImageManager::imagick()

// Create content
$content = new ImageContent(
    title: 'My Article Title',
    description: 'A brief description of the article'
);

// Generate image (uses default theme if not provided)
$generator = new Generator($imageManager);
$result = $generator->generate(
    data: $content,
    layout: new StandardLayout(),
    theme: null,  // optional - uses layout's default theme
    format: Format::Webp  // or Format::Png
);

// Use the result
$binary = $result->toString();        // Binary image data
$dataUri = $result->toBase64();       // Data URI for HTML
$stream = $result->toStream();        // Stream resource
$mimeType = $result->mimeType();      // 'image/webp' or 'image/png'
$width = $result->getWidth();         // Image width
$height = $result->getHeight();       // Image height
```

Quick Start - Symfony Bundle
----------------------------

[](#quick-start---symfony-bundle)

### Register the Bundle

[](#register-the-bundle)

```
// config/bundles.php
return [
    // ...
    Void\OgImage\Symfony\OgImageBundle::class => ['all' => true],
];
```

### Use in Your Application

[](#use-in-your-application)

```
use Void\OgImage\Generator;
use Void\OgImage\Model\ImageContent;
use Void\OgImage\Layout\StandardLayout;
use Void\OgImage\Enum\Format;

class ArticleService
{
    public function __construct(private Generator $generator) {}

    public function generateOgImage(string $title, string $description): string
    {
        $content = new ImageContent(
            title: $title,
            description: $description
        );

        $result = $this->generator->generate(
            data: $content,
            layout: new StandardLayout(),
            format: Format::Webp
        );

        // Save to filesystem or return binary
        return $result->toString();
    }
}
```

Core Concepts
-------------

[](#core-concepts)

### ImageContent

[](#imagecontent)

The data model for your OG image:

```
use Void\OgImage\Model\ImageContent;
use Void\OgImage\Model\Badge;

$content = new ImageContent(
    title: 'Article Title',                    // Required
    description: 'Article description',        // Optional
    badges: [                                  // Optional array of Badge objects
        new Badge('category', 'Technology'),
        new Badge('status', 'Published'),
    ],
    extras: []                                 // Optional - additional data for custom layouts
);
```

### Theme

[](#theme)

Customize the appearance of your images:

```
use Void\OgImage\Theme;
use Void\OgImage\Model\Background;
use Void\OgImage\Model\Font;

$theme = new Theme(
    primaryColor: '#6366f1',                          // Optional accent color
    background: new Background(
        color: '#0f172a',                             // Background color
        image: null,                                  // Optional background image path
        fit: Fit::Cover,                              // How to fit the image
        spacing: 20,                                  // Spacing for Repeat fit
        opacity: 0.8                                  // Opacity for image background
    ),
    textColor: '#ffffff',                             // Optional text color
    mutedColor: '#999999',                            // Optional muted/secondary text color
    titleFont: new Font(
        path: '/path/to/font.ttf',                    // Font file path
        size: 64,                                     // Font size in pixels
        color: '#000000'                              // Font color
    ),
    bodyFont: new Font(                               // For description text
        path: '/path/to/font.ttf',
        size: 32,
        color: '#333333'
    ),
    badgeFont: new Font(                              // For badge text
        path: '/path/to/font.ttf',
        size: 16,
        color: '#ffffff'
    ),
    padding: 40,                                      // Content padding
    logo: '/path/to/logo.png',                        // Optional logo/watermark
    logoScale: 0.5,                                   // Logo scale factor
    badges: null                                      // Optional default badge styles
);
```

### Background

[](#background)

Control how backgrounds are rendered:

```
use Void\OgImage\Model\Background;
use Void\OgImage\Enum\Fit;

$background = new Background(
    color: '#ffffff',                    // Fallback/primary color
    image: '/path/to/image.png',        // Optional background image
    fit: Fit::Cover,                    // Fit mode: Cover, Contain, Center, Repeat, Stretch
    spacing: 10,                        // Spacing for Repeat mode
    opacity: 1.0                        // Opacity (0-1) for image
);
```

### Layouts

[](#layouts)

Built-in layouts for common patterns:

#### StandardLayout

[](#standardlayout)

The default layout with title, description, and badges:

```
use Void\OgImage\Layout\StandardLayout;

$layout = new StandardLayout();
$result = $generator->generate($content, $layout);
```

### Image Formats

[](#image-formats)

Generate WebP or PNG images:

```
use Void\OgImage\Enum\Format;

// WebP (default, smaller file size, better compression)
$result = $generator->generate($content, $layout, $theme, Format::Webp);

// PNG (broader compatibility, larger file size)
$result = $generator->generate($content, $layout, $theme, Format::Png);
```

Extending
---------

[](#extending)

### Custom Layouts

[](#custom-layouts)

Create your own layout by extending `AbstractLayout`:

```
use Intervention\Image\Interfaces\ImageManagerInterface;
use Void\OgImage\Canvas;
use Void\OgImage\Layout\AbstractLayout;
use Void\OgImage\Model\ImageContent;
use Void\OgImage\Theme;

class CustomLayout extends AbstractLayout
{
    public function defaultTheme(): Theme
    {
        return new Theme(
            primaryColor: '#ff0000',
            // ... other default theme properties
        );
    }

    public function build(
        ImageManagerInterface $imageManager,
        ImageContent $data,
        ?Theme $theme = null
    ): Canvas {
        $canvas = new Canvas(1200, 630, $imageManager);

        // Set background
        $canvas->setBackground($theme->background ?? new Background(color: '#ffffff'));

        // Add your custom rendering logic here
        // Use $canvas->add($box, $position) to add elements

        return $canvas;
    }
}
```

### Custom Fonts

[](#custom-fonts)

Use different fonts for various text elements:

```
use Void\OgImage\Model\Font;

$theme = new Theme(
    titleFont: new Font('/path/to/bold-font.ttf', 64, '#000000'),
    bodyFont: new Font('/path/to/regular-font.ttf', 32, '#333333'),
    badgeFont: new Font('/path/to/small-font.ttf', 16, '#ffffff')
);
```

### Custom Badges

[](#custom-badges)

Add badges to your content:

```
use Void\OgImage\Model\Badge;
use Void\OgImage\Model\ImageContent;

$content = new ImageContent(
    title: 'Article Title',
    description: 'Description',
    badges: [
        new Badge('Technology', 'Python'),
        new Badge('Status', 'Published'),
        new Badge('Category', 'Tutorial'),
    ]
);
```

### Enums

[](#enums)

The library includes helpful enums for configuration:

**Format** - Image output format:

```
use Void\OgImage\Enum\Format;

Format::Webp  // Default
Format::Png
```

**Fit** - Background image fitting:

```
use Void\OgImage\Enum\Fit;

Fit::Cover      // Crop to fill
Fit::Contain    // Scale to fit
Fit::Center     // Center without scaling
Fit::Repeat     // Tile the image
Fit::Stretch    // Stretch to fill
```

**TextAlignment** - Text alignment within boxes:

```
use Void\OgImage\Enum\TextAlignment;

TextAlignment::Left
TextAlignment::Center
TextAlignment::Right
```

**Overflow** - Text overflow handling:

```
use Void\OgImage\Enum\Overflow;

Overflow::Visible
Overflow::Hidden
Overflow::Ellipsis
```

**Placement** - Element positioning:

```
use Void\OgImage\Enum\Placement;

Placement::TopLeft
Placement::Top
Placement::TopRight
Placement::Left
Placement::Center
Placement::Right
Placement::BottomLeft
Placement::Bottom
Placement::BottomRight
```

Complete Example
----------------

[](#complete-example)

```
use Intervention\Image\ImageManager;
use Void\OgImage\Generator;
use Void\OgImage\Model\ImageContent;
use Void\OgImage\Model\Badge;
use Void\OgImage\Model\Font;
use Void\OgImage\Model\Background;
use Void\OgImage\Layout\StandardLayout;
use Void\OgImage\Theme;
use Void\OgImage\Enum\Format;

// Setup
$imageManager = ImageManager::gd();
$generator = new Generator($imageManager);

// Create content with badges
$content = new ImageContent(
    title: 'Getting Started with PHP 8.2',
    description: 'Learn the new features in PHP 8.2 and how to use them',
    badges: [
        new Badge('category', 'PHP'),
        new Badge('level', 'Intermediate'),
    ]
);

// Create a custom theme
$theme = new Theme(
    primaryColor: '#6366f1',
    background: new Background(color: '#0f172a'),
    textColor: '#ffffff',
    mutedColor: '#a0aec0',
    titleFont: new Font('/fonts/bold.ttf', 64, '#ffffff'),
    bodyFont: new Font('/fonts/regular.ttf', 32, '#a0aec0'),
    badgeFont: new Font('/fonts/medium.ttf', 16, '#6366f1'),
    padding: 50,
    logo: '/images/logo.png',
    logoScale: 0.6
);

// Generate the image
$result = $generator->generate(
    data: $content,
    layout: new StandardLayout(),
    theme: $theme,
    format: Format::Webp
);

// Output
echo "Generated OG image: {$result->getWidth()}x{$result->getHeight()}";
echo "MIME Type: {$result->mimeType()}";

// Save to file
file_put_contents('og-image.webp', $result->toString());

// Or get as data URI for HTML img tag
echo '';
```

Testing
-------

[](#testing)

Run the test suite:

```
composer test
```

With coverage report:

```
composer test:coverage
```

License
-------

[](#license)

MIT License - see LICENSE file for details

Author
------

[](#author)

Raphael Alogou -

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance82

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

91d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c8700323ebed54bdf0a8f45cdf5801c042e4901c5ca2cb3d5886f11fcb45dc8b?d=identicon)[raphalogou](/maintainers/raphalogou)

---

Top Contributors

[![adeys](https://avatars.githubusercontent.com/u/45217162?v=4)](https://github.com/adeys "adeys (20 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/void-og-image/health.svg)

```
[![Health](https://phpackages.com/badges/void-og-image/health.svg)](https://phpackages.com/packages/void-og-image)
```

###  Alternatives

[laravolt/avatar

Turn name, email, and any other string into initial-based avatar or gravatar.

2.0k5.6M38](/packages/laravolt-avatar)[unopim/unopim

UnoPim Laravel PIM

10.3k2.2k](/packages/unopim-unopim)[inovector/mixpost

Self-hosted social media management software.

3.3k5.7k2](/packages/inovector-mixpost)[fisharebest/webtrees

webtrees online genealogy

77416.0k20](/packages/fisharebest-webtrees)[symfony/ux-cropperjs

Cropper.js integration for Symfony

19322.9k3](/packages/symfony-ux-cropperjs)[beyondcode/laravel-favicon

Create dynamic favicons based on your environment settings.

37448.1k](/packages/beyondcode-laravel-favicon)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
