Weave Code
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 Image Laravel Package

spatie/laravel-og-image

Generate Open Graph images in Laravel from Blade-defined HTML. Automatically renders screenshots, serves them from a route, and caches files. Templates reuse your app’s CSS, fonts, and Vite assets—no external API required.

View on GitHub
Deep Wiki
Context7

title: Caching and storage weight: 5

Content-hashed URLs

Image URLs are based on an md5 hash of the HTML content. When you change the template content, the hash changes and a new URL is produced. Crawlers pick up the new image automatically. Old images remain on disk until you clear them.

Configuring the disk

By default, images are stored on the public disk at og-images/. You can change both via the OgImage facade:

use Spatie\OgImage\Facades\OgImage;

OgImage::disk('s3', 'og-images');

Serving with Cloudflare (recommended)

If your site is behind Cloudflare, no extra configuration is needed. When the first crawler requests an OG image:

  1. The request passes through Cloudflare to your server
  2. PHP generates (or reads) the image and responds with Cache-Control: public, max-age=86400
  3. Cloudflare caches the response

All subsequent requests for that image are served directly from Cloudflare's edge. PHP is never hit again (until the cache expires). Since image URLs are content-hashed, different content always produces a different URL, so stale cache is not a concern.

This duration is controlled by the redirect_cache_max_age config value, which sets the Cache-Control: max-age header on the image response. The default is 1 day. Since image URLs are content-hashed, you can safely increase this:

// config/og-image.php
'redirect_cache_max_age' => 60 * 60 * 24 * 7, // 7 days

Serving without a CDN

Without a CDN like Cloudflare, every request to /og-image/{hash}.jpeg hits PHP. This works, but each request occupies a PHP-FPM worker to serve a static file.

You can add an nginx rule that serves already-generated images directly from disk, bypassing PHP entirely:

location ~ ^/og-image/([a-f0-9]+\.(jpeg|jpg|png|webp))$ {
    try_files /storage/og-images/$1 /index.php?$query_string;
}

Place this before the location / block in your nginx site config.

This tells nginx to first check if the image exists at /storage/og-images/{hash}.{format}. If it does, nginx serves it directly. If not, the request falls through to PHP, which generates the image and saves it to disk. The next request for that image is served by nginx without PHP.

Forge

If you're using Laravel Forge, go to your site's settings and click the Nginx tab. Add the location block above to the "before" section so it is placed before the location / block.

Serving with S3 or other remote disks

When using S3 as your storage disk, the package detects that it is a remote disk and automatically issues a 301 redirect to the S3 URL instead of streaming the image through PHP. This means:

  1. The first request hits PHP, which issues a 301 redirect to https://your-bucket.s3.amazonaws.com/og-images/{hash}.jpeg
  2. The client fetches the image directly from S3
  3. CDNs cache the 301 redirect, so subsequent requests never hit PHP

This keeps PHP out of the image serving path entirely. If your S3 bucket is behind CloudFront, crawlers end up fetching the image from CloudFront's edge.

The nginx try_files optimization does not apply to S3, since the files are not on the local filesystem. The redirect approach is used automatically instead.

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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport