jolicode/media-bundle
JoliCode MediaBundle is a Symfony bundle for handling images, videos, and audio. It offers a provider system, on-the-fly filters like resize and crop, responsive image helpers, and local or cloud storage integration, making media consistent and easy to reuse across your application.
Architecture fit — unchanged: weak for a Laravel estate, strong only for Symfony. jolicode/media-bundle remains a Symfony bundle, not a framework-agnostic PHP library. It integrates through the Symfony kernel: a Bundle class, DI extension/config tree, tagged services, Twig helpers, and admin integrations built on Symfony Form types. None of that is loadable in a Laravel application. v0.10.0 does not change this — if anything it deepens the coupling by moving conversion into core and requiring imagine/imagine by default, which ties the media pipeline contract to Symfony service wiring rather than a standalone library API. For a Laravel target this remains a domain-reference artifact, not a dependency.
What v0.10.0 actually changes. This is a substantive release (~19 PRs, 3 new contributors), not a maintenance bump, and it materially answers several of our open questions:
trash_path so trash directory cannot be deleted" (#158). Worth flagging to any reviewer: this is a destructive-operation guard, and its presence implies the prior behavior could delete outside the intended trash scope.Integration feasibility — still high friction, but the spike is now cheaper and better targeted. The persistence question is still the first hard blocker: if media are Doctrine entities, the model layer is incompatible with Eloquent regardless of container differences. New first-order checks introduced by this release: (1) does the new internal uploader expose any non-browser contract, or is it purely a Symfony Form/asset-bundle integration; (2) does the temporary-URL feature support the storage drivers we actually use, or only S3; (3) what does the default imagine/imagine requirement do to an existing composer.lock that already pins an imaging library.
Technical risk — low code risk, high fit risk, adoption signal now mixed rather than poor. MIT, maintained by JoliCode, provenance solid. The 0-dependents signal from the prior assessment has not been re-supplied and must be re-verified, but the directional indicators have improved: three first-time contributors in one release, CI coverage extended to a real cloud storage backend, and a coherent architectural consolidation (convert into core, srcset into a resolver) rather than scattered patches. Set against that: this is still a 0.x package, and v0.10.0 is a minor bump that carries behavior changes — a new hard dependency, an uploader replacement, a trash-path normalization, a convert-service relocation. Under 0.x semver we must treat minor releases as potentially breaking. The earlier concern about the registry's freshness signal (a 2026-10-05 last-release date) remains unresolved: verify commit history and the Symfony support matrix directly rather than trusting metadata.
Key questions for the maintainer / spike (revised):
Verdict (revised): Unchanged for a Laravel target — do not adopt; the Laravel-native path still wins decisively. But the reference value of this package went up: v0.10.0 is now a materially better design reference for the media bounded context (signed delivery, server-side srcset resolution, tested object-storage behavior, guarded deletion semantics) than it was at v0.9.0. Read those five areas specifically in the 1–2 day spike, then map to the native stack. If a Symfony service enters the estate, this release moves the package from "risky bet" to "credible, with a pinned-version plan."
Stack fit — unchanged. For a Laravel codebase the correct equivalent remains Spatie Media Library (media model, conversions, multi-collection, Flysystem disk abstraction) plus Intervention Image or Glide for transforms plus a queue-backed conversion pipeline. That covers 90%+ of what this bundle offers, with a Laravel-native container, Eloquent integration, and a large answer base. Note that v0.10.0's "Imagine in core" decision is a point in favor of the native path: the bundle has now chosen an engine rather than delegating, so the only thing we would gain from it is admin glue we cannot use.
Migration path — concept migration, now with a better shopping list. Extract from v0.10.0 specifically:
Storage::temporaryUrl() and is the single most portable idea in the release.Re-express these as our own interfaces (a MediaDeliverer for signed URLs, a SrcsetResolver, a ConversionPipeline) so the domain model stays portable.
Compatibility — one new hard constraint. If a Symfony component exists in the estate, v0.10.0 introduces a mandatory imagine/imagine dependency. Before anything else, run a composer constraint audit against that app's composer.lock: an existing Imagine/Glide/LiipImagine pin is now a likely conflict, and that conflict is the usual dealbreaker. Also verify the Symfony major matrix and the transitive Doctrine ORM/DBAL and Flysystem constraints. Pin exactly (0.10.0, not ^0.10) and treat every 0.x minor as a potential breaking change until 1.0 — this release alone carries an uploader swap, a service relocation, a config normalization, and a new required dependency.
Sequencing (if pursued for a Symfony service):
imagine/imagine requirement against the existing lock first; do not proceed past a conflict.Maintenance. Single-agency stewardship (JoliCode) with a small but now visibly growing contributor base — three first-time contributors in v0.10.0 is a genuinely positive signal after a 0-dependent history. But there is still no LTS, no commercial support tier, and no declared deprecation policy. The added hard dependency on imagine/imagine also means Imagine's release cadence and security posture are now part of our maintenance surface. Budget an explicit "if upstream goes quiet, we fork or replace" contingency; the temporary-URL and delivery code is the part most likely to be worth carrying forward in a fork.
Support. GitHub issues only. Expect to be near the front of the queue for edge cases in the newer features — temporary URLs and the internal uploader are one release old and have the least field exposure. S3 CI coverage (#182) reduces the risk of the most common production divergence, which is a real improvement over the prior state, but it is a test suite, not a support contract. Acceptable for a low-blast-radius admin feature; not acceptable for anything customer-facing at scale.
Scaling. The bundle still exposes scaling problems rather than solving them. Image transformation is CPU- and memory-bound and must run on asynchronous workers with concurrency limits and per-asset size caps — "convert moved to core" changes where the code lives, not where it should execute. Two v0.10.0-specific additions to the scaling model: temporary URLs put signed-delivery generation in the request path, so cache signed URLs at the edge where expiry windows allow, and be deliberate about expiry length versus CDN TTL; server-side srcset resolution (#173) is a per-render cost that must be memoized/cached, or it becomes a cheap way to regress response times on media-heavy pages. Storage growth remains unbounded by default — retention policy and a derived-asset regeneration story are still required when transform parameters change.
Failure modes to design against:
trash_path normalization fix (#158) shows deletion scope was previously under-guarded. Any admin user with delete rights is a potential blast radius; verify the guard holds under our config and add a test that asserts nothing outside the trash directory can be removed.fa icon-class change (#170) is a small example of cosmetic drift surfacing to content editors. Requires visual smoke tests.Ramp-up. Unchanged for a Laravel team: Symfony bundle conventions, DI tagging, config-tree semantics, Twig, and Doctrine metadata are unfamiliar territory, and the payoff is a single feature area — 3–5 engineer-days to first productive contribution versus under a day with the Laravel-native equivalent. The v0.10.0 breakage surface (uploader swap, convert relocation, new required dependency, trash-path behavior) adds half a day of diff review even for a Symfony-fluent team, so the comfortable sub-day ramp now assumes reading the v0.9→v0.10 diff first. Still the only scenario where the dependency math works.
Bottom line for the roadmap: the prior low opportunity score (26.11) remains directionally correct — mature substitutes exist on both frameworks, and the Symfony-only surface caps strategic value. But v0.10.0 is the strongest signal this project has emitted: tested S3, signed delivery, a real architectural consolidation, and three new contributors. Recommendation holds — do not adopt for the Laravel estate; mine it as a reference implementation, with emphasis on temporary URLs, the srcset Resolver, and the trash/deletion guard. For any future Symfony service, treat v0.10.0 as the pin, budget the composer conflict audit up front, and re-evaluate the dependents/adoption metric before committing — that number was not included in this release data and should be re-verified rather than assumed improved.
How can I help you explore Laravel packages today?