Featured image & gallery
The bundled Post owns three media-library-for-laravel buckets through the HasPostMedia concern:
| Bucket | Config key | Shape | Accepts |
|---|---|---|---|
featured | media.featured_bucket | single file — a new attach replaces the previous one; optional fallback URL | image/jpeg, image/png, image/webp, image/gif, image/avif |
gallery | media.gallery_bucket | multiple files, order preserved | image/jpeg, image/png, image/webp, image/gif, image/avif |
content | media.content_bucket | multiple files — owns the inline [media:UUID] media | any type |
Each bucket uses posts.media.disk when set and posts.media.responsive_widths (a list of positive integers — any other entry throws InvalidConfigurationException; [] declares no variants); null means the media-library defaults. Responsive widths become variants named responsive-{width}.
Featured image and gallery
// Featured image (single-file — a new attach replaces the previous one)
$post->addMedia($request->file('cover'))->toMediaBucket($post->featuredBucket());
$post->featuredImage(); // ?Media
$post->featuredImageUrl(); // string ('' or the configured fallback when empty)
$post->featuredImageUrl('responsive-640'); // the variant once generated, else the original
// Gallery (multi-file, order preserved)
$post->addMedia($request->file('photo'))->toMediaBucket($post->galleryBucket());
$post->galleryImages(); // Collection<int, Media>
$post->galleryImageUrls(); // list<string>
$post->galleryImageUrls('responsive-320'); // list<string> — each variant once generated, else the original
// The configured bucket names
$post->featuredBucket(); // 'featured'
$post->galleryBucket(); // 'gallery'
$post->contentBucket(); // 'content'Variants are generated on a queue, so featuredImageUrl($variant) and galleryImageUrls($variant) return the variant’s URL once it exists and the original’s until then — or for an unknown name — instead of failing the page.
Every other media-library method — getMedia(), getFirstMediaUrl(), hasMedia(), clearMediaBucket(), addMediaFromUrl() and the rest — is available on the post through InteractsWithMedia.
Media options
'media' => [
'disk' => env('POSTS_MEDIA_DISK'), // null = media-library default
'featured_fallback_url' => env('POSTS_MEDIA_FEATURED_FALLBACK'),
'responsive_widths' => [480, 960, 1440], // positive ints; null = media-library default, [] = no variants
'seo_og_image' => true,
'og_variant' => '', // '' = the original, or a variant such as 'responsive-960'
'warm_on_publish' => true,
],Featured image as og:image
When a post has no explicit og:image, seo()->ogImage and the JSON-LD image fall back to the featured image URL — the posts.media.og_variant variant once it is generated, the original until then or when it is ''. Turn it off with posts.media.seo_og_image.
Warm variants on publish
On PostPublished, the queued WarmPostMediaVariants listener dispatches media-library’s GenerateVariantsJob for every media in the featured, gallery and content buckets, so responsive derivatives are ready when the post goes live. It does nothing when posts.media.warm_on_publish is false, the post no longer exists, or it has no media.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.