# Livewire FilePond
Livewire FilePond is a Laravel package that provides seamless integration between FilePond (a powerful JavaScript file upload library) and Livewire components. It enables developers to implement modern drag-and-drop file uploads with minimal configuration, wrapping FilePond's rich feature set into a simple Livewire-compatible component. The package handles the complexity of bridging client-side file uploads with server-side Livewire state management, providing automatic validation, temporary file handling, and event-driven workflows.
Built by Spatie and used in production in their Mailcoach product, this package supports Laravel 10.x/11.x/12.x and Livewire 3.5+. It includes 40+ language translations, multiple FilePond plugins for image processing (preview, crop, resize, transform), and comprehensive file validation capabilities. The package offers both dynamic asset serving through Laravel routes and optional static asset publishing for CDN deployment.
## Basic File Upload Component
Simple file upload with drag-and-drop interface
```php
// app/Livewire/DocumentUpload.php
document is a TemporaryUploadedFile instance
$path = $this->document->store('documents', 'public');
// Store to database or process further
auth()->user()->documents()->create([
'path' => $path,
'filename' => $this->document->getClientOriginalName(),
]);
$this->resetFilePond('document');
session()->flash('message', 'Document uploaded successfully!');
}
public function render()
{
return view('livewire.document-upload');
}
}
```
```blade
{{-- resources/views/livewire/document-upload.blade.php --}}
@if (session()->has('message'))
{{ session('message') }}
@endif
```
```blade
{{-- resources/views/layouts/app.blade.php --}}
My App
@filepondScripts
@livewire('document-upload')
```
## Multiple File Upload
Upload multiple files simultaneously with array handling
```php
// app/Livewire/GalleryUpload.php
photos is an array of TemporaryUploadedFile instances
foreach ($this->photos as $photo) {
$path = $photo->store('gallery', 'public');
auth()->user()->photos()->create([
'path' => $path,
'filename' => $photo->getClientOriginalName(),
'size' => $photo->getSize(),
]);
}
$this->resetFilePond('photos');
session()->flash('message', count($this->photos) . ' photos uploaded!');
}
public function render()
{
return view('livewire.gallery-upload');
}
}
```
```blade
{{-- resources/views/livewire/gallery-upload.blade.php --}}
@if (count($photos) > 0)
{{ count($photos) }} file(s) selected
@endif
```
## Server-Side Validation on Upload
Validate files immediately upon upload with custom rules
```php
// app/Livewire/AvatarUpload.php
'required|image|mimetypes:image/jpg,image/jpeg,image/png|max:3000',
];
}
public function messages(): array
{
return [
'avatar.required' => 'Please upload an avatar image.',
'avatar.image' => 'The file must be an image.',
'avatar.mimetypes' => 'Only JPG, JPEG, and PNG images are allowed.',
'avatar.max' => 'The image must not exceed 3MB.',
];
}
public function validateUploadedFile(): bool
{
// This is called automatically after each file upload
// If validation fails, the upload is rejected immediately
$this->validate();
return true;
}
public function save()
{
$this->validate();
// Delete old avatar if exists
if (auth()->user()->avatar) {
Storage::disk('public')->delete(auth()->user()->avatar);
}
// Store new avatar
$path = $this->avatar->store('avatars', 'public');
auth()->user()->update(['avatar' => $path]);
$this->resetFilePond('avatar');
session()->flash('message', 'Avatar updated successfully!');
}
public function render()
{
return view('livewire.avatar-upload');
}
}
```
```blade
{{-- resources/views/livewire/avatar-upload.blade.php --}}
@error('avatar')
{{ $message }}
@enderror
@if ($avatar)
@endif
```
## Pre-loading Existing Files
Display previously uploaded files in FilePond component
```php
// app/Livewire/DocumentEditor.php
document = $document;
// Pre-populate with existing file URL
// The component will automatically load and display it
$this->file = asset('storage/' . $document->path);
}
public function update()
{
// Only update if a new file was uploaded
if ($this->file instanceof \Livewire\Features\SupportFileUploads\TemporaryUploadedFile) {
// Delete old file
Storage::disk('public')->delete($this->document->path);
// Store new file
$path = $this->file->store('documents', 'public');
$this->document->update([
'path' => $path,
'filename' => $this->file->getClientOriginalName(),
]);
}
session()->flash('message', 'Document updated successfully!');
}
public function render()
{
return view('livewire.document-editor');
}
}
```
```blade
{{-- resources/views/livewire/document-editor.blade.php --}}
Edit Document: {{ $document->filename }}
```
## Event Handling with Alpine.js
Listen to upload events and trigger custom actions
```blade
{{-- resources/views/livewire/file-upload-with-events.blade.php --}}
Uploading files... Please wait.
All {{ uploadedCount }} file(s) uploaded successfully!
```
```php
// app/Livewire/FileUploadWithEvents.php
```
```php
// app/Livewire/ProductImageUpload.php
'image|mimetypes:image/png,image/jpeg,image/webp|max:5120',
];
}
public function validateUploadedFile(): bool
{
$this->validate();
return true;
}
public function save()
{
$this->validate();
foreach ($this->productImages as $image) {
$path = $image->store('products/' . $this->product->id, 'public');
$this->product->images()->create([
'path' => $path,
'filename' => $image->getClientOriginalName(),
'order' => $this->product->images()->count(),
]);
}
$this->resetFilePond('productImages');
session()->flash('message', 'Product images uploaded!');
}
public function render()
{
return view('livewire.product-image-upload');
}
}
```
## Manual FilePond Reset
Programmatically clear FilePond component
```php
// app/Livewire/BatchUpload.php
documents as $document) {
$path = $document->store('batch-uploads', 'public');
auth()->user()->documents()->create([
'path' => $path,
'filename' => $document->getClientOriginalName(),
]);
$this->uploadedCount++;
}
// Clear the FilePond component and reset the property
$this->resetFilePond('documents');
session()->flash('message', 'Batch upload completed!');
}
public function clearAll()
{
// Manually reset FilePond without saving
$this->resetFilePond('documents');
session()->flash('message', 'Upload cancelled.');
}
public function render()
{
return view('livewire.batch-upload');
}
}
```
```blade
{{-- resources/views/livewire/batch-upload.blade.php --}}
Total uploaded in this session: {{ $uploadedCount }}
@if (count($documents) > 0)
@endif
```
## WithFilePond Trait Methods
Core trait providing file handling functionality
```php
// Trait usage example
validate([
'files.*' => 'required|file|max:10240',
]);
return true;
}
/**
* Remove a file from the property and delete from storage
* Called when user clicks remove button in FilePond
*
* @param string $property The Livewire property name
* @param string $filename The filename to remove
*/
public function customRemove($property, $filename)
{
// The trait's remove() method handles this automatically
// You typically don't need to call this manually
$this->remove($property, $filename);
}
/**
* Revert an uploaded file (undo upload)
* Called when user clicks undo button in FilePond
*
* @param string $property The Livewire property name
* @param string $filename The filename to revert
*/
public function customRevert($property, $filename)
{
// The trait's revert() method handles this automatically
// It deletes the TemporaryUploadedFile and updates the property
$this->revert($property, $filename);
}
/**
* Reset FilePond component and clear files
* Call this after processing uploads or to cancel
*
* @param string $property The Livewire property name to reset
*/
public function clearUploads()
{
$this->resetFilePond('files');
// This method:
// 1. Resets the Livewire property to null/empty array
// 2. Dispatches 'filepond-reset-{property}' event to clear UI
}
public function render()
{
return view('livewire.file-manager');
}
}
```
## Localization
Configure FilePond in different languages
```bash
# Publish translation files
php artisan vendor:publish --tag="livewire-filepond-translations"
```
```env
# .env - Set application locale
APP_LOCALE=id
```
```php
// config/app.php or in a middleware
use Illuminate\Support\Facades\App;
// Set locale programmatically
App::setLocale('id'); // Indonesian
App::setLocale('es'); // Spanish
App::setLocale('fr'); // French
App::setLocale('de'); // German
```
```php
// resources/lang/id/filepond.php (after publishing)
'Seret & Lepas file Anda atau Telusuri ',
'labelFileLoading' => 'Memuat',
'labelFileProcessing' => 'Mengunggah',
'labelFileProcessingComplete' => 'Upload selesai',
'labelFileProcessingAborted' => 'Upload dibatalkan',
'labelTapToCancel' => 'ketuk untuk membatalkan',
'labelTapToRetry' => 'ketuk untuk mencoba lagi',
'labelTapToUndo' => 'ketuk untuk membatalkan',
'labelButtonRemoveItem' => 'Hapus',
'labelButtonAbortItemLoad' => 'Batalkan',
'labelButtonRetryItemLoad' => 'Coba lagi',
'labelButtonAbortItemProcessing' => 'Batalkan',
'labelButtonUndoItemProcessing' => 'Urungkan',
'labelButtonRetryItemProcessing' => 'Coba lagi',
'labelButtonProcessItem' => 'Upload',
];
```
```php
// app/Livewire/LocalizedUpload.php
dispatch('$refresh');
}
public function render()
{
return view('livewire.localized-upload');
}
}
```
## Static Asset Publishing
Serve FilePond assets from your public directory
```bash
# Publish static assets to public/vendor/livewire-filepond
php artisan vendor:publish --tag=livewire-filepond-assets --force
```
```json
// composer.json - Auto-publish assets after updates
{
"scripts": {
"post-update-cmd": [
"@php artisan vendor:publish --tag=livewire-filepond-assets --force"
]
}
}
```
```blade
{{-- After publishing, assets are served from: --}}
{{-- public/vendor/livewire-filepond/filepond.js --}}
{{-- public/vendor/livewire-filepond/filepond.css --}}
{{-- The @filepondScripts directive automatically detects published assets --}}
@filepondScripts
```
## Installation and Setup
Complete installation guide
```bash
# Install via Composer
composer require spatie/livewire-filepond
# Optional: Publish views for customization
php artisan vendor:publish --tag="livewire-filepond-views"
# Optional: Publish translations for customization
php artisan vendor:publish --tag="livewire-filepond-translations"
# Optional: Publish assets for static serving
php artisan vendor:publish --tag="livewire-filepond-assets" --force
```
```php
// The service provider is auto-discovered via Laravel's package discovery
// No manual registration needed
// Verify installation in config/app.php (auto-added):
'providers' => [
// ...
Spatie\LivewireFilepond\LivewireFilepondServiceProvider::class,
],
```
```blade
{{-- resources/views/layouts/app.blade.php --}}
My Application
{{-- Required: Add FilePond scripts and styles --}}
@filepondScripts
@livewireStyles
{{ $slot }}
@livewireScripts
```
## Summary
Livewire FilePond simplifies file upload implementation in Laravel applications by providing a drop-in Livewire component that wraps FilePond's rich JavaScript library. The package excels at handling common upload scenarios including single and multiple file uploads, image processing with crop/resize/transform capabilities, real-time validation, and pre-loading existing files. With support for 40+ languages and comprehensive event handling through Alpine.js, developers can create sophisticated file upload interfaces with minimal custom code. The `WithFilePond` trait extends Livewire's native file upload functionality with methods for reverting uploads, removing files, and resetting the component state, while the `validateUploadedFile()` hook enables immediate server-side validation as files are uploaded.
The package's flexible architecture supports both dynamic asset serving through Laravel routes and static asset publishing for CDN deployment, making it suitable for various hosting environments. Integration requires only three steps: adding the `@filepondScripts` directive to your layout, including the `WithFilePond` trait in your Livewire component, and placing the `` component in your view with a `wire:model` binding. FilePond's extensive configuration options are accessible via kebab-case attributes on the Blade component, allowing fine-grained control over file constraints, image processing, and UI behavior. Whether building a simple document upload form or a complex multi-file image gallery with validation and processing, Livewire FilePond provides the tools needed for modern file upload experiences in Laravel applications.