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

Media Manager Laravel Package

ctf0/media-manager

ctf0/media-manager is a Laravel media and file manager with an intuitive interface for uploading, browsing, organizing, and editing files. It supports image cropping and resizing, drag-and-drop uploads, and straightforward integration into Laravel applications.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a self-contained file browser (Vue 2 front-end + Laravel back-end) that ships its own route, assets, and config. There is no database layer — everything is driven by a Flysystem disk — so setup is three steps, not the usual five.

composer require ctf0/media-manager
php artisan vendor:publish --provider="ctf0\MediaManager\MediaManagerServiceProvider"
php artisan storage:link

Then open config/media-manager.php and check, in this order:

  1. disk — which filesystem the manager operates on (public by default). The UI browses the root of that disk, so scope it deliberately (see below).
  2. route / prefix — the URL it mounts at (default media).
  3. middleware — defaults to web only. Add auth before you do anything else; otherwise you have just published an unauthenticated file-delete endpoint.
  4. allowed_mimes, folder_max_size — your upload guardrails.

Confirm what actually got registered before debugging anything else:

php artisan route:list | grep media

v4.0.0 is a Laravel-version bump and nothing more — the entire release note is "update laravel version." Before you assume that means "Laravel 11/12 ready," verify the facts yourself:

composer show ctf0/media-manager          # installed version
composer show ctf0/media-manager --all    # available versions + constraints

Read the composer.json inside vendor/ctf0/media-manager for the actual illuminate/*, php, and intervention/image constraints. That file — not the release note — tells you which Laravel minors you can realistically run.

First use case: visit /media as an authenticated admin and treat it as an internal asset browser — upload logos, hero images, PDFs into per-page folders. That remains the dominant use. Everything else (programmatic access, custom UI, editors) is built on top of that one route.

The package's real integration surface is its JSON API rather than the Vue bundle, so read the controller routes from route:list early — that is where the leverage is.

Implementation Patterns

Standalone admin route. The simplest and most durable pattern: register the package route inside your existing admin middleware group and link to it from your nav. No coupling to your app's views, easy to rip out later.

// config/media-manager.php
'middleware' => ['web', 'auth', 'can:manage-media'],
'disk'       => 'public',
'route'      => 'admin/media',

Per-user sandboxing via disk roots. Rather than fighting the package's permission model, point it at a per-tenant directory. Swap the disk at runtime in a service provider or a small middleware:

config(['filesystems.disks.tenant' => [
    'driver' => 'local',
    'root'   => storage_path('app/tenants/'.auth()->id()),
    'url'    => '/storage/tenants/'.auth()->id(),
]]);
config(['media-manager.disk' => 'tenant']);

This gives you hard isolation for free — the UI cannot traverse above the disk root.

Embedding for pickers. The common day-to-day need is "pick an image for this record." Two workable approaches:

  • Iframe modal — load the media route in an iframe, have your host page listen for a postMessage you inject via a tiny custom Blade view that extends the package view. Brittle but zero build tooling.
  • Direct API — call the JSON endpoints (upload, list, rename, delete) from your own Vue/Alpine component. More work up front, but survives package upgrades and lets you drop the bundled Vue 2 assets entirely.

Using the bundled facade for server-side work. For seeding, imports, or scheduled cleanup, reach for the filesystem directly (Storage::disk('public')) rather than the package facade — the facade is thin and the disk API is what you actually want. Reserve the package for human-driven operations.

S3 / remote disk. Set disk to an s3 disk and be aware the UI will issue per-request round trips for listing and thumbnailing; on large buckets this is noticeably slow. Budget for it or keep the manager on local disk and sync.

Editor integration. The classic pairing is with a WYSIWYG (TinyMCE/CKEditor) file-picker button that opens the media route in a popup and calls back with the selected URL. Treat the manager as an external tool speaking a small URL contract, not as a component in your SPA.

Upgrading from 3.x to 4.x. Treat it as a real major bump even though the changelog is one line: re-publish and diff the config and views (vendor:publish --force into a scratch dir first, then merge), re-run route:list, and smoke-test upload/crop/delete. Major bumps can carry constraint, asset, or namespace changes that never made it into a notes file. Do it on a branch with composer.lock committed so you can revert cleanly.

Gotchas and Tips

Release cadence is still the headline risk. The project sat dormant from July 2023 until v4.0.0, and v4.0.0 ships a one-line changelog with no migration guide, no testing notes, and a major version number. Read that as "one person bumped a constraint," not as "actively maintained." Pin versions, commit composer.lock, and assume you will be the maintainer. Budget for a fork rather than expecting upstream fixes.

Vue 2 is still almost certainly on board. A Laravel-version bump does not rewrite the front end. Unless you have verified otherwise in vendor/ctf0/media-manager/package.json, assume the bundled UI is Vue 2 (EOL), which matters for your build tooling, CSP, and any bundler audit you run. The direct-API pattern above is the escape hatch.

The default middleware is a security hole. ['web'] on a route that can delete files. Every install must add auth plus an authorization gate. Check this first if you inherit a project — and re-check it after any config re-publish during the 4.x upgrade, since publishing can overwrite your hardened file.

Uploads fail silently or 403 with no useful message. In order: PHP upload_max_filesize / post_max_size (Nginx client_max_body_size too), then the package's own folder_max_size and allowed_mimes config, then storage/ permissions and the storage:link symlink. Enable APP_DEBUG and watch the network tab — the API returns JSON errors, but the Vue layer sometimes swallows them.

Image manipulation requires a working GD or Imagick. intervention/image will throw on crop/resize/rotate if the extension is missing or the image driver config is wrong. Check php -m | grep -E 'gd|imagick' before blaming the package — and note that if 4.x moved to Intervention v3, the driver/config/image.php conventions differ from v2 docs you will find in older tutorials.

Config caching bites. After editing config/media-manager.php: php artisan config:clear. Routes: php artisan route:clear. After a version bump, also php artisan view:clear and php artisan optimize:clear — stale compiled views from 3.x are a plausible cause of a blank or broken UI post-upgrade.

Thumbnails are cached on disk. Regenerate after changing image dimensions by clearing the thumbnail directory (path is in config) — otherwise the UI keeps serving stale crops.

CSRF and the API. If you call the endpoints from your own SPA, you need the session cookie plus X-XSRF-TOKEN; the bundled UI handles this automatically because it runs inside the web group. Custom clients that omit it get 419s that look like auth failures.

Debugging checklist. composer show ctf0/media-manager → what you actually installed. route:list | grep media → confirm the route and middleware survived the upgrade. Browser network tab → the exact JSON error and status. storage/logs/laravel.log → Intervention/Flysystem exceptions. php artisan tinker → Storage::disk('public')->allFiles() to confirm the disk really contains what the UI claims.

Extension points are limited. The package publishes views and config but not a clean service/event layer. If you need to hook uploads (virus scan, image optimization, DB record creation), the pragmatic route is a middleware wrapping the upload endpoint or a filesystem event listener on the disk — not a package hook. Forking is often cheaper than fighting the abstraction, and after a one-line major release, forking is also a reasonable hedge against the next dormancy.

Don't mount it at a public path. Even with auth, the route name leaks and the UI is fingerprinted by scanners. Put it under an admin prefix and leave the "looks like WordPress" scanners guessing.

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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin