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.
Installation:
composer require spatie/laravel-og-image
Ensure you have Node.js and Chrome/Chromium installed (required for spatie/laravel-screenshot).
Publish Config (optional):
php artisan vendor:publish --tag="og-image-config"
First Use Case: Add the Blade component to your view:
<x-og-image>
<div class="w-full h-full bg-blue-900 text-white flex items-center justify-center">
<h1 class="text-6xl font-bold">{{ $post->title }}</h1>
</div>
</x-og-image>
This generates a hidden <template> tag and meta tags pointing to /og-image/{hash}.jpeg.
Define OG Image:
Use <x-og-image> in Blade views to define the HTML structure for the OG image. The component inherits your page's CSS, fonts, and Vite assets automatically.
Lazy Generation:
The package generates images on-demand when a crawler requests /og-image/{hash}.jpeg. The first request triggers a screenshot via spatie/laravel-screenshot, which caches the image on disk.
Previewing:
Test OG images locally by appending ?ogimage to the page URL (e.g., https://yourapp.com/post?ogimage).
Pre-Generating Images:
Use the Artisan command or generateForUrl() to pre-generate images for new content:
php artisan og-image:generate https://yourapp.com/page1
Or programmatically:
OgImage::generateForUrl('https://yourapp.com/blog/my-post');
Ideal for queued jobs after publishing content:
dispatch(function () use ($post) {
OgImage::generateForUrl($post->url);
});
Fallback Images:
Register a fallback for pages without <x-og-image> in AppServiceProvider:
OgImage::fallbackUsing(function (Request $request) {
return view('og-image.fallback', ['title' => $request->route('post')->title]);
});
The fallback view should mirror the structure of <x-og-image> (no layout or scripts).
Customizing Screenshots: Override defaults (size, format, disk) globally or per component:
OgImage::format('webp')->size(1200, 630)->disk('s3', 'og-images');
Or in Blade:
<x-og-image :width="800" :height="400">
<div>Custom size</div>
</x-og-image>
CDN Optimization:
Cache-Control: public, max-age=86400.location block to serve static images directly:
location ~ ^/og-image/([a-f0-9]+\.(jpeg|jpg|png|webp))$ {
try_files /storage/og-images/$1 /index.php?$query_string;
}
Concurrent Screenshot Load: Lazy generation can spike server load if many crawlers hit new pages simultaneously. Mitigate by pre-generating images or using a queue.
Content Hashing:
Changing <x-og-image> HTML or dimensions invalidates the cache. Old images remain on disk until cleared or manually deleted.
Fallback Overrides:
Fallbacks apply only to pages without <x-og-image>. Ensure logic in the fallback closure doesn’t unintentionally override intended behavior.
Remote Disk Redirects: When using S3 or remote disks, the package issues 301 redirects to the S3 URL. Ensure your CDN (e.g., CloudFront) caches these redirects to avoid PHP overhead.
Missing Images:
<x-og-image> component is present in the Blade view.og:image meta tag in the page source (should point to /og-image/{hash}.jpeg).public disk (or configured disk) has write permissions.Stale Images: Clear cached images with:
php artisan og-image:clear
Or manually delete files from storage/app/public/og-images/.
Screenshot Failures:
spatie/laravel-screenshot logs for errors (e.g., missing dependencies like puppeteer).Custom Screenshot Driver: Replace the default Browsershot driver with Cloudflare’s Browser Rendering:
OgImage::useCloudflare(
env('CLOUDFLARE_ACCOUNT_ID'),
env('CLOUDFLARE_API_TOKEN')
);
Dynamic Fallbacks: Use route parameters or model bindings in the fallback closure to dynamically generate OG images for specific routes:
OgImage::fallbackUsing(function (Request $request) {
if ($request->routeIs('posts.show')) {
return view('og-image.post-fallback', ['post' => $request->route('post')]);
}
return null;
});
Custom Storage Paths:
Override the default og-images directory or disk:
OgImage::disk('s3')->path('custom-og-images');
Cache Control:
Adjust redirect_cache_max_age in config/og-image.php to extend CDN caching (e.g., 7 days for static assets):
'redirect_cache_max_age' => 60 * 60 * 24 * 7,
How can I help you explore Laravel packages today?