Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Og Images Laravel Package

abordage/laravel-og-images

A Laravel package for generating Open Graph images for social sharing. Define templates, render dynamic titles and metadata, and serve cached OG images for pages, posts, and products with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

The package wraps Browsershot/Puppeteer so you can turn a Blade view into a PNG/JPEG/WebP — typically a 1200×630 Open Graph card — without hand-rolling Chrome invocation.

Minimal setup:

  1. composer require abordage/laravel-og-images
  2. php artisan vendor:publish --tag="og-images-config" (and the views tag if you want a starting template to copy).
  3. Make sure the host has Node + a Chromium/Chrome binary available — this is a Browsershot-backed package, so PHP alone is not enough. Set the binary paths in config/og-images.php (node/npm/chrome) or the matching env vars if your binaries live outside PATH.
  4. Point the config at a disk/path and, if you want on-the-fly rendering, at the route prefix.

First use case to try: render a title/subtitle card from a controller and dump it to disk.

use Abordage\OgImages\Facades\OgImage;

OgImage::view('og-images.post')
    ->data(['title' => $post->title, 'author' => $post->author->name])
    ->save("og/{$post->slug}.png");

Then reference the absolute URL in your layout:

<meta property="og:image" content="{{ asset("og/{$post->slug}.png") }}">

Where to look first: the published config (binary paths, disk, route settings), the published Blade template (that's the whole design surface), and the OgImage facade for the fluent builder (view(), data(), save(), toResponse(), toHtml()).

Implementation Patterns

Generate on write, not on read. The most common production shape is an observer or model event that dispatches a queued job after save. Rendering takes hundreds of milliseconds to a few seconds (Chrome cold start), which is too slow for a page request but trivial in a queue.

class PostObserver
{
    public function saved(Post $post): void
    {
        GenerateOgImage::dispatch($post)->onQueue('images');
    }
}

Store the resulting path (or a hash of the inputs) in a column so you can render the meta tag without touching the filesystem, and so you know when to regenerate.

Cache-bust with content hashes, not timestamps. Social platforms cache aggressively. Filenames like og/{slug}-{sha1($title.$subtitle)}.png mean a title edit produces a new URL and the crawler picks it up; a stable filename means you're stuck with the old card for days.

On-the-fly route + HTTP caching. If you enable the package route, the pattern is: signed or slug-addressed URL → render → cache the response with a long Cache-Control and an ETag. This is convenient for large sites where storing thousands of PNGs is annoying, but you must put a cache in front of it or every crawler hit spawns a Chrome process.

Template as a first-class artifact. Keep the OG Blade template dumb: inline CSS or a single compiled stylesheet, web-safe/system fonts or self-hosted fonts referenced by absolute path, no JS, no external network calls. Anything that depends on the request lifecycle (auth, session, locale) should be passed in explicitly via data().

Testing. Don't shell out to Chrome in CI unless you already have a Chrome-enabled runner. Assert on toHtml() for template correctness and use Bus::fake() to assert the job is dispatched. Cover the job itself with a single integration test tagged/skipped when the binary is missing.

Fallbacks matter. Always ship a static default OG image. If generation fails (missing font, OOM, Chrome crash), the meta tag should point at something valid rather than 404 — crawlers will happily cache the 404.

Gotchas and Tips

  • Version 1.1.1 dropped Laravel 11 from the test matrix. If you're still on Laravel 11, pin ^1.1.0 and don't expect regressions to be caught for you. On Laravel 12+ this release is a no-op.
  • Docker/Chromium sandboxing. Running as root inside a container requires --no-sandbox; Browsershot exposes this via its Chrome arguments. Symptoms are silent timeouts or "Failed to launch the browser process" — check the process stderr, not the Laravel log.
  • Fonts are the #1 cause of ugly output. A minimal container ships without the fonts your template asks for; Cyrillic, CJK, or even a specific weight will silently fall back to tofu boxes or a default serif. Install font packages in the image and verify with a non-Latin sample.
  • Cold start is real. First render after a deploy can take seconds while Chrome spins up. Warm it once during deploy if the first user-visible card matters, or accept the latency on the queue.
  • Size mismatch. Set both the Browsershot viewport and the template's CSS dimensions to 1200×630; a viewport smaller than the page gives you a cropped screenshot, not a scaled one.
  • Absolute URLs only. og:image must be fully qualified. Use asset()/url() and set APP_URL correctly in every environment — a http://localhost OG image is the classic staging-leak bug.
  • Debugging path: call toHtml() on the builder and inspect the markup before blaming Chrome. If the HTML is right, the problem is binary paths, fonts, or sandbox flags — in that order.
  • Extension points: published views are meant to be edited (put your brand template in resources/views/og-images/), the config lets you swap disk/path/route prefix without touching code, and data() is the seam for injecting anything the template needs. Keep the template free of queries so it stays cacheable and testable.
  • Disk and cleanup. Generated files accumulate. Pair the generator with a scheduled prune for orphaned hashes, or write to a s3/object-store disk and let lifecycle rules handle it.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast