VoodMedia plugin screenshot
Dark mode ready
No multilingual support
Supports v5.x

VoodMedia

Community

Media vault and galleries for Laravel + Filament — reusable assets, galleries, and form pickers. MIT by Voodflow.

Tags: Developer Tool Form Field Spatie Integration
Supported versions:
5.x
Voodflow avatar Author: Voodflow

Package health

Beta

Automated checks of this plugin's Composer package

100 / 100
Security 100
Maintenance 100
Ecosystem 100
15 checks
  • Skipped: GitHub Actions pinned to SHA
  • Skipped: GitLab CI includes pinned to SHA
  • Passed: Open security advisories
  • Passed: Dependabot PR responsiveness — No open Dependabot PRs.
  • Skipped: Renovate MR responsiveness
  • Passed: Dependabot or Renovate configured
  • Passed: Dependency update cooldown configured
  • Passed: Provides a security policy
  • Passed: Abandoned or archived — No consulted source marks the package abandoned (packagist, github).
  • Passed: Commit and release recency — Active: last commit 0 days ago; last release 0 days ago.
  • Passed: composer.lock not committed by library — composer.lock is absent from the released dist archive.
  • Passed: Dist archive is lean
  • Passed: Current Laravel version supported — Package dependencies resolve together with current Laravel 13.0.
  • Passed: Current PHP version supported — Constraint ^8.4 supports current PHP 8.5.
  • Skipped: Current Symfony version supported
Third-party plugin. This is built by the community, not the Filament team. Filament does not review, endorse, or vet the security of plugins outside the filament/ namespace. Review the source and install at your own risk. Found malware or an unresolved security issue the author won't address? Report it .
Powered by Plumb Last scanned 2 days ago

Documentation

VoodMedia — Filament Media Vault by VoodFlow

Media Vault for Laravel + Filament: upload once, reuse everywhere. One vault storage copy, many gallery memberships, morph attachments for your domain models.

Works standalone in any Filament app. Optional integrations with VoodBuilder (Asset Manager), Voodflow (e.g. Approval Page heroes), and any third-party package that registers its own vault root.

Built on Filament 5 and Spatie Media Library.

#Screenshots

#Media library

Central library: preview, galleries, usage counts, type, size, and upload time. Upload media or Import ZIP from the header.

VoodMedia media library

#Galleries (folders & albums)

Organize vault media with a hierarchy: Folder = container (year, product, plugin…); Album = holds photos/files. Mark a default gallery and toggle public albums.

VoodMedia galleries list

#Album editor

Edit album metadata (parent, slug, public/default), manage images (browse library, upload, ZIP import, drag reorder), and assign album tags.

VoodMedia album edit

#Picker (VmediaPicker)

Modal for forms and builders: upload into the selected folder/album, filter by parent/gallery, search, grid/list view, multi-select → Use selection.

VoodMedia choose from media library

#Requirements

Requirement Notes
PHP 8.4+
Laravel 12 or 13
Filament 5
Spatie Media Library 11
PHP gd extension Must be built with JPEG (and preferably WebP + FreeType). Spatie generates thumb conversions on upload; without JPEG support you get imagecreatefromstring(): No JPEG support in this PHP build.

Verify in the app container:

php -r 'var_export(gd_info()["JPEG Support"] ?? false);'
# expect: true

Docker / php:*-fpm example:

RUN apt-get update && apt-get install -y \
    libpng-dev libjpeg-dev libwebp-dev libfreetype6-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
    && docker-php-ext-install gd

#Quick start (5 minutes)

composer require voodflow/vmedia
php artisan vmedia:install

Register on the Filament panel:

->plugins([
    \Voodflow\Vmedia\VmediaPlugin::make(),
])

Attach media to a model:

use Voodflow\Vmedia\Concerns\HasAttachedMedia;

class Booth extends Model
{
    use HasAttachedMedia;
}

Upload in a Filament form:

use Voodflow\Vmedia\Filament\Forms\Components\VmediaFileUpload;

VmediaFileUpload::make('logo')
    ->collection('logo')
    ->image();

Pick existing vault media:

use Voodflow\Vmedia\Filament\Forms\Components\VmediaPicker;

VmediaPicker::make('gallery')
    ->collection('gallery')
    ->images()
    ->multiple();

#Plugin vault roots (for packages & host apps)

VoodMedia does not hardcode product folders. Each package (or the host app) registers a top-level folder + default Library album, then uses it for uploads/pickers.

#1. Register + ensure on boot

In your package ServiceProvider (or AppServiceProvider):

use Voodflow\Vmedia\Support\Integration\RegistersPluginVault;

public function boot(): void
{
    if (! class_exists(RegistersPluginVault::class)) {
        return;
    }

    // source = stable id (integration_source), slug = folder slug in the UI
    RegistersPluginVault::register(
        source: 'acme',
        slug: 'acme',
        name: 'Acme', // or fn (): string => __('acme::nav.media_root')
        // integrationKey: 'root:acme', // optional; default root:{slug}
    );
    RegistersPluginVault::ensureOnBoot($this->app, 'acme');
}

Equivalent low-level API:

use Voodflow\Vmedia\Vmedia;

Vmedia::registerPluginVault('acme', 'acme', 'Acme');
Vmedia::ensurePluginVault('acme'); // or RegistersPluginVault::ensureOnBoot(...)

After boot you get a folder Acme with a child Library album (upload target when browsing that folder).

Sync all registered roots (after companions have booted):

php artisan vmedia:ensure-plugin-roots

#2. Use the vault in code

use Voodflow\Vmedia\Support\Integration\PluginVaultRootGroup;
use Voodflow\Vmedia\Support\Integration\PluginVaultLibraryGallery;
use Voodflow\Vmedia\Support\MediaLibrary;
use Voodflow\Vmedia\Filament\Forms\Components\VmediaPicker;

// Top-level folder (KIND_GROUP)
$root = PluginVaultRootGroup::for('acme');

// Default Library album under that folder (KIND_ALBUM) — prefer this for uploads
$library = PluginVaultLibraryGallery::album('acme');

MediaLibrary::store($uploadedFile, $library);

// Lock a Filament picker to your plugin library
VmediaPicker::make('hero')
    ->images()
    ->attachToRecord(false)
    ->vaultGallery(fn (): int => (int) PluginVaultLibraryGallery::album('acme')->getKey());

Optional: nest under a configured parent (settings / multi-tenant layout):

PluginVaultRootGroup::for('acme', $optionalOuterRootId);

#3. Conventions

Concept Rule
source Stable string stored as integration_source (e.g. acme, voodflow)
slug URL/path segment for the folder
Library album Auto-created under the root; use it as default upload target
Isolation Your package owns only its source; do not hardcode other products in VoodMedia

Shared Logos folder is provided by VoodMedia itself (PluginVaultRootGroup::logos()).

#Model

  • Vault — singleton Spatie owner of every file on disk (one storage copy)
  • Galleries — many-to-many membership (a photo/video/file can sit in several galleries)
  • Folders vs albums — folders nest structure; albums hold media
  • Default gallery — fallback target for uploads when no gallery is selected; Choose can browse any gallery
  • Attachments — HasAttachedMedia morph pivot (domain models never own Spatie collections)

#Features

Area What you get
Admin Library + galleries hierarchy, metadata (alt, caption, credits; video poster on videos), soft delete / trash
Picker VmediaPicker + VmediaFileUpload for other plugins
Files Photos, videos, and documents (PDF/Office/ZIP…)
Thumbs Configurable Spatie conversion ladder (thumb + sm/md/lg/xl WebP by default); API exposes display / srcset / sizes
Usage Attachment counts; delete protected when media is in use
Tags Media tags + album tags; bulk assign
Duplicates SHA-256 reuse (optional)
ZIP import Bulk extract into the vault
Events MediaStored, MediaAttached, MediaDetached, MediaDeleted, MediaRestored
Stats Dashboard widget + php artisan vmedia:stats
Orphans php artisan vmedia:prune-orphans --force
Public GET /galleries/{slug} Blade gallery for is_public galleries

#HTTP API (package-owned)

Method Path Role
GET /vmedia/media/galleries Gallery list + counts
GET /vmedia/media?page=&per_page=&gallery_id=&type=&q= Paginated assets (type: image|video|file)
POST /vmedia/media/upload Upload; optional gallery_id (folder/album — folders resolve to library album)
DELETE /vmedia/media/{media} Soft-delete (?force=1 force-deletes)

All routes require authentication (and optional Gate ability VMEDIA_ABILITY).

#Config highlights

VMEDIA_ENABLED=true
VMEDIA_DISK=public
VMEDIA_CONVERSIONS=true
VMEDIA_DETECT_DUPLICATES=true
VMEDIA_PROTECT_DELETE=true
VMEDIA_PUBLIC_GALLERIES=true

#Storage disk (local / S3 / …)

VMEDIA_DISK is any disk from Laravel’s config/filesystems.php. Spatie stores vault files on that disk (MediaVault → useDisk(...)).

Local (default):

VMEDIA_DISK=public

S3 (or compatible): define the disk as usual, then point VoodMedia at it:

FILESYSTEM_DISK=s3
AWS_ACCESS_KEY_ID=…
AWS_SECRET_ACCESS_KEY=…
AWS_DEFAULT_REGION=eu-west-1
AWS_BUCKET=your-bucket
AWS_URL=https://your-bucket.s3.eu-west-1.amazonaws.com
# optional: AWS_ENDPOINT=…  AWS_USE_PATH_STYLE_ENDPOINT=true  (MinIO, R2, …)

VMEDIA_DISK=s3

config/filesystems.php (stock Laravel s3 disk is enough):

's3' => [
    'driver' => 's3',
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION'),
    'bucket' => env('AWS_BUCKET'),
    'url' => env('AWS_URL'),
    'endpoint' => env('AWS_ENDPOINT'),
    'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
],

Require the Flysystem S3 adapter if the host app does not already:

composer require league/flysystem-aws-s3-v3 "^3.0"

No VoodMedia-specific S3 code path: Filament uploads and Spatie conversions use the configured disk. Keep Livewire temporary uploads on a local disk if you prefer (LIVEWIRE_TEMPORARY_FILE_UPLOAD_DISK=local); only the final vault objects need VMEDIA_DISK=s3.

Public URLs come from Storage::disk(...)->url(...) (local → /storage/..., S3 → bucket/CloudFront URL). Use a public bucket (or CDN AWS_URL) so thumbs and embeds resolve without signed URLs.

#Docs

Public documentation: docs.voodflow.com

#License

MIT — see LICENSE.

The author

Voodflow avatar Author: Voodflow

We are a development team focused on building modern, efficient management applications using FilamentPHP. We’ve been working with FilamentPHP since version 3 for several years, leveraging its flexibility to create solid, scalable, and productivity-oriented admin interfaces.

Over time, we developed an internal management system for one of our businesses, tackling real-world challenges and delivering practical, field-tested solutions. From that experience, we also built a range of plugins designed to extend Filament’s capabilities in a focused and meaningful way.

This natural evolution led to the creation of Voodflow: not just a plugin, but a full workflow engine that lives inside FilamentPHP. Voodflow is designed to orchestrate complex processes in an intuitive way, while preserving the consistency and elegance of the Filament ecosystem—while pushing it beyond its traditional limits.

Plugins
5
Stars
5

From the same author