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

Statamic Picturesque Laravel Package

visuellverstehen/statamic-picturesque

Statamic addon that generates responsive, optimized picture elements from your assets. It handles srcset, multiple formats like WebP and AVIF, and lazy loading out of the box, so you can drop flexible, performance-friendly images into your Antlers templates with a single tag.

View on GitHub
Deep Wiki
Context7

Getting Started

Picturesque turns a Statamic asset (or a set of them) into responsive <picture>/<img> markup with Glide-generated derivatives — srcsets, per-breakpoint widths, and modern formats — without hand-writing {{ glide:generate }} chains.

  1. Install into an existing Statamic project (v3.4+/4/5) that has at least one asset container with Glide enabled:
    composer require visuellverstehen/statamic-picturesque
    php artisan vendor:publish --tag=picturesque-config
    
  2. Open config/picturesque.php first — this is the file you will spend 90% of your time in. It defines the named sources (breakpoints + width/height/format rules), the default source set, the default formats, and cache behaviour. Treat it as your design-system ↔ image pipeline contract.
  3. Replace your first {{ glide }} / raw <img> with the tag:
    {{ picturesque :src="hero_image" sizes="100vw" }}
    
  4. Then narrow it to the sources that actually match your layout:
    {{ picturesque :src="hero_image" sources="sm,md,lg" sizes="(min-width: 1024px) 50vw, 100vw" }}
    
    Comma-separated sources is restored in 2.2.0 — before that you were forced into YAML-array syntax in the template, which most people found noisy.

First real use case: a hero/banner partial that takes an asset field and renders a <picture> with AVIF/WebP + JPEG fallback and a srcset driven by your config breakpoints.

Implementation Patterns

Named sources as your design tokens. Define the breakpoints once in config/picturesque.php (sm, md, lg, xl, each with a width and optional height/ratio), then reference them by name everywhere. This keeps templates readable and lets you change a width in one place instead of grepping through Antlers files.

Comma-separated source lists (2.2.0). The pragmatic default for templates:

{{ picturesque :src="image" sources="sm,md,lg,xl" sizes="100vw" }}

Use the array/binding form (:sources="['sm','md']") only when the list is computed — e.g. from a Bard set, a fieldset toggle, or a layout partial's parameter. Both forms should be interchangeable, so pick one convention per project and lint for it.

Wrap it in a partial/component. The tag has a lot of optional surface area (alt, class, sizes, formats, placeholder, loading, fetchpriority). Create resources/views/components/picturesque.antlers.html that takes src, sources, sizes, class, alt, priority and forwards them. This is the single biggest maintainability win and makes swapping the package later survivable.

Format strategy. Enable webp (and avif if your Glide/imagemagick build supports it) in the config rather than per-call, and let the tag emit <source type="..."> before the fallback <img>. Keep the fallback format as jpg/png — animated GIFs and SVGs should bypass the tag entirely.

Layout-driven sizes. Always pass sizes that mirrors the actual CSS. A missing sizes makes browsers assume 100vw, so a 400px-wide card downloads the 1920px derivative. Pair each breakpoint source with the media query that matches it, and put the mapping in a comment above the partial.

Art-directed and per-context images. For Bard/replicator sets, drive sources from the set config (e.g. sources="{set:image_size}" where the value is sm,md or lg,xl). This is exactly the pattern the restored comma syntax makes pleasant — a field value can be passed straight through as a string.

Focal points and Glide parity. Picturesque sits on top of Glide, so use Statamic's focal point field and pass through your normal Glide params (:glide="true") when you need cropping (fit, crop, brightness). Keep custom params in a config array rather than inline so caches stay consistent.

Static/edge caching. Generate derivatives at deploy (or via a warm-up command hitting your top N pages) rather than on first anonymous request. If you use the static cache, remember the generated markup is frozen — clear both Picturesque's derivative cache and the static cache when breakpoints change.

Gotchas and Tips

  • Comma syntax is whitespace-sensitive. sources="sm, md, lg" may not trim as you expect (and "sm,,lg" definitely won't). Write it without spaces, sources="sm,md,lg", and prefer the binding form if the list is dynamic.
  • String vs array ambiguity. Because sources accepts both a comma string and an array, a value like "1" or a single name behaves identically — but a mistyped array (e.g. sources="[sm,md]" in a non-:, non-YAML context) silently degrades to one weird source name. If the output has no srcset, dump the resolved sources before touching anything else.
  • Unknown source names fail quietly. Referencing a source that isn't in config/picturesque.php usually just yields fewer <source> entries — no exception. Keep the config and template names in sync, and add a test/smoke check that asserts the expected number of srcset candidates.
  • Cache invalidation is the main footgun. Derivative URLs are keyed on source name + Glide params, not on file contents. Replacing an asset in place can leave a stale derivative; re-upload (new filename) or run the cache clear command. After editing breakpoints in config, always clear derivatives and any static/response cache.
  • sizes is not optional in practice. Omit it and you ship oversized images to every phone. If you can't compute sizes, at least pass a conservative single value — it's better than nothing.
  • Extension points. The source/format resolution is the place to hook if you need custom srcset logic; for anything more exotic (CDN-specific URL signing, per-tenant breakpoints), wrap the tag in your own Antlers tag or partial rather than forking the config.
  • Don't run it through SVG/GIF. Non-raster assets should branch out before the tag; Glide will either error or produce a useless derivative.
  • Local debugging. Disable the derivative cache locally so you can iterate on the config without repeated clears, but re-enable it (or warm it) before load testing — the first uncached render of a grid of images is dramatically slower than cached.
  • Upgrading: 2.2.0 is additive (restores a previously supported syntax), so existing array/YAML-style sources continue to work. No migration required, but it is worth normalising templates to the comma form or the array form so the codebase doesn't drift into both.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console