itiden/laravel-image
A Laravel package for handling images with a fluent, expressive API. Generate, resize, and cache image variations, then serve optimized, responsive assets through Laravel's filesystem and storage layers with minimal configuration.
itiden/laravel-opixlig wraps League Glide so you can serve transformed images (resize, crop, focal point, format conversion) from Laravel storage without hand-rolling a Glide server. v1.0.0 is the first stable cut and is the release to target — everything below assumes it.
league/glide constraint must allow ^3.0):
composer require itiden/laravel-opixlig
php artisan vendor:publish
Look for config/opixlig.php. In v1.0.0 the transformation defaults live under a nested defaults key (previously the flat default_keys), and a new presets key holds named transformation sets.AGENTS.md and Boost guidelines first. v1.0.0 shipped AGENTS.md and Laravel Boost integration, so php artisan boost:install (or the Boost MCP tools in your editor) can surface the package's own usage guidance and keep AI-assisted edits from inventing an API that doesn't exist.opixlig.php; the defaults assume a local public disk, so S3/GCS users must change them explicitly.card → width 600, height 400, fit=crop, fm=webp), then render an image through that preset in a Blade view instead of hand-writing query strings. Verify by hitting a page and checking that the derived file appears on the cache disk with the expected dimensions and format.The fastest sanity check is: upload one image, render it through one preset, and confirm the derived URL responds 200 with Content-Type: image/webp.
Presets are the primary abstraction — use them, not ad-hoc parameters. Define the transformations your design system actually needs (thumb, card, hero, og) once in config/opixlig.php under presets, then reference them by name from Blade/components. This keeps sizes consistent across the app and gives you a single place to change formats or quality later.
Pass one-off manipulations only for genuine exceptions. v1.0.0 expanded the supported manipulation set. Where a preset doesn't fit, pass manipulations per call, but treat that as a code smell that a preset is missing — and never let manipulation keys come straight from request input.
Default merges with per-call options. The defaults array is the baseline applied to every transformation; presets and per-call options layer on top. Establish your house defaults (format, quality, fit) in defaults so individual presets stay short and readable.
Cache busting on image update. v1.0.0 clears the browser cache when a source image changes — the derived URL changes so CDN/browser caches don't serve a stale crop after a re-upload. This matters most for user-editable images (avatars, product photos, CMS media). Wire your model's update path so a replaced file triggers this; if you also front the app with a CDN or reverse proxy, remember that this only handles client-side caches.
Responsive images. Generate a srcset by looping presets (or width variants) and emitting one URL per entry, with the largest preset as src. Because presets are named, your Blade component stays declarative rather than embedding Glide syntax in templates.
Keep the Glide server behind the package. Resist the urge to register your own /img/{path} route and call Glide directly. Routing through the package gets you its signing/validation, cache layout, and the browser-cache invalidation behaviour for free — and means the Glide 3 upgrade in this release didn't require changes in your app code.
AI-assisted work. With AGENTS.md and Boost integration in place, point your agent at the published config and the guidelines before asking it to add a preset; otherwise it tends to generate flat default_keys-era code or raw Glide query strings.
default_keys key; v1.0.0 uses nested defaults. Any published config/opixlig.php and any code reading config('opixlig.default_keys') must be updated. Re-publish the config and diff it rather than editing the old file by hand.league/glide ^2.x, Composer will block the upgrade. Resolve that before attempting the v1.0.0 bump; don't force it with --ignore-platform-reqs. If you extended Glide classes directly, expect API differences between v2 and v3.200 on the source file is almost always a cache-disk path or writability problem, not a transformation problem. Check the cache disk first when debugging.Storage::fake() in tests doesn't give you Glide. Tests can assert the generated URL and the preset/manipulation arguments, but the actual image write won't happen against a fake disk. Keep transformation assertions at the URL level and cover real rendering with a single feature test against a real temp disk.defaults, a preset that only sets w inherits your default fit/h and may crop unexpectedly. Be explicit in presets and don't rely on inheritance for geometry.How can I help you explore Laravel packages today?