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

Responsive Image Laravel Package

tempest/responsive-image

Generate responsive images in PHP and render the correct HTML. Define your source and public paths, create a factory, then output an img tag with a ready-made srcset of scaled sizes. Early work in progress, so expect changes.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. tempest/responsive-image is a thin, opinionated layer that does two things: (1) generates downscaled derivatives from a source image at a configurable set of widths, and (2) renders an <img> tag with a srcset/sizes pair. Architecturally it is a rendering-time convenience, not an image pipeline: it expects a source directory (srcPath), a public output directory (publicPath), and produces files named by dimensions (parrot-1920-1280.jpg). That is a good fit for a statically deployed, low-traffic PHP app where images are curated assets committed to the repo or uploaded via an admin panel. It is a poor fit for user-generated content at scale, multi-tenant asset storage on object stores, or anything requiring signed URLs, on-the-fly transformation, or CDN edge negotiation. Note the packaging reality: this is a Tempest package, not a Laravel one. The quickstart instantiates ResponsiveImageFactory and ResponsiveImageConfig directly, which is the most promising integration surface — but we must verify the factory does not reach into Tempest's container, discovery, or config bootstrapping, because if it does we cannot use it inside a Laravel service container without a shim.

Integration feasibility. Two viable integration shapes exist. Shape A (preferred): treat the two classes as a plain-PHP library, bind ResponsiveImageConfig as a Laravel singleton from config/images.php, inject ResponsiveImageFactory into a Blade directive or a @responsiveImage($path) helper, and wrap generation in an artisan command so it runs at deploy time rather than per-request. This is achievable in a day or two of spike work. Shape B: install the full Tempest framework alongside Laravel — do not do this. Composer-wise the package is tempest/responsive-image and will pull Tempest support packages as transitive dependencies; the spike's first deliverable is a composer why on the dependency tree to confirm what actually gets dragged in. If the transitive footprint is only small utility packages (path helpers, string helpers), Shape A is safe. If it requires tempest/framework, the integration cost triples and the evaluation should end there.

Technical risk. Risks, in descending order of severity:

  1. Framework coupling / abandonment. 1 star, 0 dependents, "work in progress," and a single-maintainer ecosystem. This is not a dependency you can put on a critical rendering path without a fork-and-own plan. Assume you will vendor or fork it.
  2. Synchronous generation on the request path. The README's example calls create() and echoes html — if derivative generation happens inline, the first request for each image blocks on GD/Imagick work, and concurrent first-hits will stampede. This must be pre-generated at build/deploy time or lazily behind a queue.
  3. Storage and cache invalidation. Derivatives are written to publicPath with dimension-encoded filenames. There is no visible cache-busting hash, no manifest, and no deletion story. Changing the source image at the same path will serve stale derivatives forever; changing the configured widths orphans files on disk with no GC.
  4. Format strategy. The example emits JPEG only. No WebP/AVIF, no <picture>/type negotiation, no loading="lazy", no decoding, no explicit dimensions (CLS risk), no fetchpriority. For a modern Core Web Vitals budget this is table stakes; we would need to extend the renderer regardless.
  5. Determinism of the width ladder. Widths appear to derive from the source aspect ratio. That is fine but must be stable across environments and image drivers (GD vs Imagick produce different resample output), otherwise golden-file checks and CDN purges get noisy.
  6. License/governance. MIT is fine and removes legal friction; the risk is stewardship, not licensing.

Key questions for the maintainer / spike.

  • Does ResponsiveImageFactory require the Tempest container, or is it constructible with only ResponsiveImageConfig in a bare PHP process?
  • What is the exact transitive Composer footprint, and does it include tempest/framework?
  • Which backend is used — GD, Imagick, or vips — and is it configurable?
  • Is there a queued/CLI generation path, or is it request-time only?
  • Are derivatives content-hashed or otherwise cache-busted when the source changes? Is there a prune/GC command?
  • Is WebP/AVIF or <picture> support on the roadmap, or is JPEG-only the intended scope?
  • What happens on a missing source file, an unreadable file, or an unsupported format — exception, silent fallback, or broken <img>?
  • Is there any test suite, and does CI exercise multiple PHP versions and image drivers?

Integration Approach

Stack fit. The package fits a Laravel monolith whose images are a bounded, curated set — marketing pages, editorial content, a product catalogue measured in thousands rather than millions — served from local disk or a single bucket mounted into publicPath. It does not fit a multi-tenant SaaS where tenants upload arbitrary images, nor a headless/API-only backend fronted by a SPA (though the generated srcset string is still useful there). Before committing, benchmark it against the incumbent options on the same page: spatie/laravel-medialibrary + intervention/image (more capable, far healthier, heavier), and a managed transform CDN such as Cloudflare Images, Imgix, or Cloudinary (zero maintenance, per-image cost). The honest framing for stakeholders: this package saves perhaps 150–300 lines of glue code over hand-rolling srcset generation around intervention/image, and in exchange you accept single-maintainer risk. The buy case is thin; the build case is also thin; the CDN case is usually the strongest at any real scale.

Migration path. Treat this as an additive, strangler-style rollout, never a big-bang.

  1. Spike (1 week). Install in a throwaway branch against the current Laravel version. Confirm bare-PHP constructibility, transitive deps, driver, and behavior on a representative sample of 20 real images. Decision gate: proceed only if no framework coupling.
  2. Wrap, don't scatter. Introduce a single first-party ImageRenderer service (and a @responsiveImage Blade directive) that delegates to the package. Every template calls our wrapper, never ResponsiveImageFactory directly. This is the seam that makes swapping to a CDN or a fork a one-file change.
  3. Pre-generate at deploy. Add an images:generate artisan command invoked in the deploy pipeline (or a container build step), writing into a gitignored public/images/generated path. Requests never trigger generation. Emit a manifest (path → hashed filenames) so templates can cache-bust.
  4. Pilot one surface. Roll out to a single high-visibility template (e.g. article hero images) behind a feature flag, measure LCP, CLS, and byte weight against the current baseline for two weeks.
  5. Broaden, then retire. Migrate remaining templates surface by surface; decommission the old helper once the manifest covers all referenced images.

Compatibility. Pin the version exactly ("tempest/responsive-image": "0.x.y" — no caret) given WIP status; a 0.x minor bump is a de facto breaking change. Verify PHP version and Laravel support matrix explicitly; confirm the image driver is present in every environment (GD is near-universal, Imagick often absent from slim containers, vips almost never pre-installed). Ensure local, CI, and production share the same driver and PHP version so derivative output is byte-identical — otherwise deploy-time generation and local development diverge. Confirm the package honours Laravel's public_path() and filesystem abstraction; if it writes to a raw absolute path, wrap it so a move to S3 later does not require touching call sites.

Sequencing. Spike and decision gate → wrapper + config binding + artisan command → CI step asserting generation is deterministic and idempotent → single-surface pilot → measurements → broad rollout → fork-or-replace decision reviewed at the six-month mark. Do not begin until the wrapper exists; the wrapper is the entire risk-mitigation strategy.

Operational Impact

Maintenance. This is a fork-and-own dependency, and the operating assumption must be that upstream goes quiet. Budget roughly 10–15% of one engineer's time ongoing: tracking the upstream repo, rebasing a small internal patch set (WebP/AVIF output, loading/decoding/width/height attributes, content-hashed filenames, prune command), and re-verifying on Laravel and PHP upgrades. Assign a named owner. If nobody will own it, do not adopt it — that is the whole decision.

Support. No vendor, no SLA, no security response process. MIT gives you the legal right to fork, which is the only real support guarantee. Security exposure is modest (image decoding is the main attack surface, and that risk is inherited from GD/Imagick, not this package), but a malicious upload path must be validated upstream of this library regardless of which option you choose.

Scaling. Generation cost is CPU-bound and linear in (number of images × widths in the ladder). That is entirely acceptable at deploy time and entirely unacceptable per-request. Storage is source count × ladder size, typically 4–6× the original bytes — trivial for thousands of images, a real line item for millions. Serving scales fine because the output is static files behind a CDN; the package is not in the hot path once generation is pre-baked. The scaling ceiling is reached when image count makes full re-generation at deploy too slow, at which point you need incremental generation driven by a manifest diff — a feature the package does not appear to have, so it becomes internal work. Beyond that ceiling, migrate to a transform CDN; the wrapper seam makes that a contained change.

Failure modes. Enumerate and instrument each:

  • Missing or corrupt source — decide explicitly between 500, placeholder image, or omitted tag; the package's default must not be a broken <img> in production.
  • Derivative generation failure at deploy — should fail the deploy loudly, not ship a half-populated manifest.
  • Stale derivatives — source replaced, hash unchanged, old file served indefinitely. Mitigated by content-hashed filenames.
  • Disk exhaustion — orphaned derivatives from changed width ladders with no GC. Mitigated by a prune command in the deploy pipeline plus a disk-usage alert.
  • Driver drift — CI (GD) and production (Imagick) produce different bytes; manifests mismatch across environments. Mitigated by pinning the driver everywhere.
  • Concurrency stampede — if any code path generates at request time, concurrent first-hits will thrash CPU. Mitigated by pre-generation plus a lock or a "generate on miss into a queue, serve original" fallback.
  • Silent layout shift — no width/height emitted; CLS regressions go unnoticed unless measured. Add attribute injection in the wrapper and assert in the pilot.

Ramp-up. Low for a mid-level Laravel engineer — the API is two classes and a config object, and a competent developer is productive in under a day. The real ramp-up is operational: whoever owns deploys must understand the generate-prune-manifest cycle, and whoever owns templates must use the wrapper rather than the raw factory. Write a two-page runbook covering the deploy step, the prune command, the driver-pinning rule, and the escalation path for a broken image. Total onboarding cost, including the spike, is on the order of one engineer-week — which is the correct yardstick against the alternative of a CDN integration (also roughly one week, but with recurring cost and near-zero ongoing engineering). For a small, curated image set on a modest Laravel app with an engineer willing to own a fork, this package is a defensible, cheap choice; for anything larger or less well-staffed, budget the week toward a managed transform CDN 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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log