
A comprehensive Progressive Web App (PWA) plugin for Filament v3 and v4 admin panels. Transform your Filament admin panel into a fully-featured PWA with offline functionality, installation prompts, automatic icon generation, and comprehensive internationalization support.
Install the package via Composer:
composer require alareqi/filament-pwa
Note: This package supports both Filament v3 and v4. The installation process is identical for both versions.
Publish the configuration file and assets:
# Publish configuration file
php artisan vendor:publish --tag="filament-pwa-config"
# Publish views (for customization)
php artisan vendor:publish --tag="filament-pwa-views"
# Publish public assets
php artisan vendor:publish --tag="filament-pwa-assets"
Generate all required PWA icons from your logo:
# From SVG (recommended for best quality)
php artisan filament-pwa:setup --generate-icons --source=public/logo.svg
# From PNG/JPG
php artisan filament-pwa:setup --generate-icons --source=public/logo.png
Validate your PWA configuration:
php artisan filament-pwa:setup --validate
Register the plugin in your Panel provider with fluent configuration:
use Alareqi\FilamentPwa\FilamentPwaPlugin;
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
FilamentPwaPlugin::make()
->name('My Admin Panel')
->shortName('Admin')
->description('Powerful admin panel for managing your application')
->themeColor('#3B82F6')
->backgroundColor('#ffffff')
->standalone()
->language('en')
->ltr()
->enableInstallation(2000) // Show prompt after 2 seconds
->addShortcut('Dashboard', '/admin', 'Main dashboard')
->addShortcut('Users', '/admin/users', 'Manage users')
->icons('images/icons', [72, 96, 128, 144, 152, 192, 384, 512])
->serviceWorker('my-app-v1.0.0', '/offline'),
]);
}
Alternatively, register the plugin and configure via config file:
use Alareqi\FilamentPwa\FilamentPwaPlugin;
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
FilamentPwaPlugin::make(),
]);
}
Then configure in config/filament-pwa.php:
return [
'name' => 'My Admin Panel',
'short_name' => 'Admin',
'description' => 'Powerful admin panel for managing your application',
'theme_color' => '#3B82F6',
'background_color' => '#ffffff',
'display' => 'standalone',
'installation' => [
'enabled' => true,
'prompt_delay' => 2000,
'ios_instructions_delay' => 5000,
'show_banner_in_debug' => true,
],
'shortcuts' => [
[
'name' => 'Dashboard',
'url' => '/admin',
'description' => 'Main dashboard',
],
],
];
For advanced use cases, use closures for dynamic configuration:
FilamentPwaPlugin::make()
->name(fn() => auth()->user()?->company_name ?? 'Admin Panel')
->themeColor(fn() => auth()->user()?->theme_color ?? '#3B82F6')
->language(fn() => auth()->user()?->language ?? app()->getLocale())
->direction(fn() => auth()->user()?->text_direction ?? 'ltr')
->addShortcut(fn() => [
'name' => 'My Dashboard',
'url' => '/admin/dashboard/' . auth()->id(),
'description' => 'Personal dashboard',
])
The plugin offers extensive configuration options through multiple approaches:
| Option | Type | Default | Description |
|---|---|---|---|
name |
string|Closure |
config('app.name') . ' Admin' |
PWA application name |
short_name |
string|Closure |
'Admin' |
Short name for home screen |
description |
string|Closure |
'Admin panel for ' . config('app.name') |
App description |
start_url |
string|Closure |
'/admin' |
Starting URL when app opens |
display |
string |
'standalone' |
Display mode (standalone, fullscreen, minimal-ui, browser) |
theme_color |
string|Closure |
Auto-detected from Filament | Theme color for browser UI |
background_color |
string|Closure |
'#ffffff' |
Background color during loading |
orientation |
string |
'portrait-primary' |
Screen orientation preference |
scope |
string |
'/admin' |
Navigation scope |
lang |
string|Closure |
Auto-detected from Laravel | Language code |
dir |
string|Closure |
Auto-detected from language | Text direction (ltr, rtl) |
'installation' => [
'enabled' => true, // Enable installation prompts
'prompt_delay' => 2000, // Delay before showing prompt (ms)
'ios_instructions_delay' => 5000, // Delay for iOS instructions (ms)
'show_banner_in_debug' => true, // Always show banner in debug mode
],
'icons' => [
'path' => 'images/icons', // Output directory for icons
'sizes' => [72, 96, 128, 144, 152, 192, 384, 512], // Icon sizes to generate
'maskable_sizes' => [192, 512], // Maskable icon sizes
],
'service_worker' => [
'cache_name' => 'filament-admin-v1.0.0', // Cache name for versioning
'offline_url' => '/offline', // Offline fallback page
'cache_urls' => [ // URLs to cache immediately
'/admin',
'/admin/login',
'/manifest.json',
],
'cache_patterns' => [ // Regex patterns for caching
'filament_assets' => '/\/css\/filament\/|\/js\/filament\//',
'images' => '/\.(png|jpg|jpeg|svg|gif|webp|ico)$/',
'fonts' => '/\.(woff|woff2|ttf|eot)$/',
],
],
The plugin includes comprehensive internationalization support with built-in translations for 10+ languages and full RTL/LTR support.
| Language | Code | Direction | Status |
|---|---|---|---|
| English | en |
LTR | ✅ Complete |
| Arabic | ar |
RTL | ✅ Complete |
| Spanish | es |
LTR | ✅ Complete |
| French | fr |
LTR | ✅ Complete |
| German | de |
LTR | ✅ Complete |
| Portuguese | pt |
LTR | ✅ Complete |
| Italian | it |
LTR | ✅ Complete |
| Russian | ru |
LTR | ✅ Complete |
| Japanese | ja |
LTR | ✅ Complete |
| Chinese (Simplified) | zh-CN |
LTR | ✅ Complete |
| Dutch | nl |
LTR | ✅ Complete |
The plugin automatically detects language and text direction from Laravel's configuration:
// The plugin will automatically use Laravel's app locale
// and detect RTL languages (Arabic, Hebrew, Persian, etc.)
FilamentPwaPlugin::make()
// Language and direction are auto-detected
FilamentPwaPlugin::make()
->language('ar') // Set specific language
->rtl() // Set RTL direction
// Or use LTR
->language('en')
->ltr()
FilamentPwaPlugin::make()
->language(fn() => auth()->user()?->language ?? app()->getLocale())
->direction(fn() => auth()->user()?->text_direction ?? 'ltr')
For RTL languages like Arabic, the plugin automatically:
dir="rtl" in the PWA manifest// Automatic RTL detection for Arabic
app()->setLocale('ar');
FilamentPwaPlugin::make()
// Automatically detects Arabic and sets RTL direction
To add custom translations or modify existing ones:
Publish the language files:
php artisan vendor:publish --tag="filament-pwa-lang"
Modify translations in resources/lang/{locale}/pwa.php:
// resources/lang/ar/pwa.php
return [
'install_title' => 'تثبيت التطبيق',
'install_description' => 'احصل على تجربة أفضل مع التطبيق المثبت',
// ... more translations
];
Add new language support:
# Copy existing translation file
cp resources/lang/en/pwa.php resources/lang/your-locale/pwa.php
# Translate the content
The plugin uses the following translation keys:
// Installation prompts
'install_title', 'install_description', 'install_button', 'dismiss_button'
// iOS installation
'ios_install_title', 'ios_install_description', 'ios_step_1', 'ios_step_2', 'ios_step_3', 'got_it'
// Updates
'update_available', 'update_description', 'update_now', 'update_later'
// Offline functionality
'offline_title', 'offline_subtitle', 'offline_status', 'online_status'
// Features and actions
'available_features', 'retry_connection', 'go_home'
// Validation messages
'validation.manifest_missing', 'validation.service_worker_missing'
// Setup command messages
'setup.starting', 'setup.completed', 'setup.validation_passed'
The plugin automatically generates all required PWA icons from a single source image with high-quality output and maskable icon support.
# Generate from SVG (best quality)
php artisan filament-pwa:setup --generate-icons --source=public/logo.svg
# Generate from PNG
php artisan filament-pwa:setup --generate-icons --source=public/logo.png
# Generate from different path
php artisan filament-pwa:setup --generate-icons --source=/path/to/your/logo.svg
The plugin generates icons in the following sizes by default:
Maskable icons ensure your app icon looks great on all devices by providing a safe area:
// Configure maskable icon sizes
'icons' => [
'maskable_sizes' => [192, 512], // Sizes for maskable icons
],
Maskable icons are automatically generated with:
// In your panel provider
FilamentPwaPlugin::make()
->icons(
path: 'images/icons', // Output directory
sizes: [72, 96, 128, 144, 152, 192, 384, 512], // Standard sizes
maskableSizes: [192, 512] // Maskable sizes
)
// Or in config file
'icons' => [
'path' => 'images/icons',
'sizes' => [72, 96, 128, 144, 152, 192, 384, 512],
'maskable_sizes' => [192, 512],
],
The plugin uses different image processing libraries based on availability:
Install Imagick for best results:
# Ubuntu/Debian
sudo apt-get install php-imagick
# macOS with Homebrew
brew install imagemagick
brew install php-imagick
# Windows
# Download from https://windows.php.net/downloads/pecl/releases/imagick/
Source image not found:
# Ensure the source path is correct
php artisan filament-pwa:setup --generate-icons --source=public/your-logo.svg
Poor quality icons:
Permission errors:
# Ensure the icons directory is writable
chmod 755 public/images/icons
If you prefer to create icons manually, place them in the configured icons directory:
public/images/icons/
├── icon-72x72.png
├── icon-96x96.png
├── icon-128x128.png
├── icon-144x144.png
├── icon-152x152.png
├── icon-192x192.png
├── icon-192x192-maskable.png
├── icon-384x384.png
├── icon-512x512.png
└── icon-512x512-maskable.png
Enable debug mode to always show installation prompts during development:
FilamentPwaPlugin::make()
->enableDebugBanner() // Always show installation banner in debug mode
// Or in config
'installation' => [
'show_banner_in_debug' => true,
],
Extend the service worker functionality:
// Configure caching strategies
FilamentPwaPlugin::make()
->serviceWorker(
cacheName: 'my-app-v2.0.0',
offlineUrl: '/custom-offline',
cacheUrls: ['/admin', '/admin/dashboard', '/api/user']
)
Add shortcuts that appear when users long-press your app icon:
FilamentPwaPlugin::make()
->addShortcut('Dashboard', '/admin', 'Main dashboard')
->addShortcut('Users', '/admin/users', 'Manage users')
->addShortcut('Settings', '/admin/settings', 'App settings')
// Dynamic shortcuts
->addShortcut(fn() => [
'name' => 'My Profile',
'url' => '/admin/profile/' . auth()->id(),
'description' => 'View my profile',
'icons' => [['src' => '/images/profile-icon.png', 'sizes' => '96x96']],
])
PWAs require HTTPS in production. The plugin validates this automatically:
// Validation will check for HTTPS in production
php artisan filament-pwa:setup --validate
For development, you can use:
php artisan serve with --host=localhost (localhost is exempt from HTTPS requirement)The plugin includes several performance optimizations:
// Efficient caching strategies
'service_worker' => [
'cache_patterns' => [
'filament_assets' => '/\/css\/filament\/|\/js\/filament\//', // Cache Filament assets
'images' => '/\.(png|jpg|jpeg|svg|gif|webp|ico)$/', // Cache images
'fonts' => '/\.(woff|woff2|ttf|eot)$/', // Cache fonts
],
],
The plugin automatically detects and uses your Filament panel's primary color for the PWA installation banner and other UI elements. The color detection system works with both Filament v3 and v4:
#6366f1 (Tailwind Indigo 500)The system handles various color formats used by Filament:
// Hex colors
'primary' => '#3B82F6'
// RGB format
'primary' => 'rgb(59, 130, 246)'
// Comma-separated RGB
'primary' => '59, 130, 246'
// Filament Color arrays (v3/v4)
'primary' => [
600 => '59, 130, 246',
500 => '#3B82F6',
// ... other shades
]
// Filament Color objects (v4)
'primary' => Color::Blue
You can override the automatic detection:
// In config/filament-pwa.php
'theme_color' => '#FF6B35', // Your custom color
// Or via environment
PWA_THEME_COLOR=#FF6B35
// Or via plugin configuration
FilamentPwaPlugin::make()->themeColor('#FF6B35')
Installation prompt not showing:
// Enable debug mode to always show prompts
FilamentPwaPlugin::make()->enableDebugBanner()
// Check browser console for errors
// Ensure HTTPS is enabled in production
Icons not loading:
# Regenerate icons
php artisan filament-pwa:setup --generate-icons --source=public/logo.svg
# Check file permissions
chmod 755 public/images/icons
Service worker not updating:
// Update cache name to force refresh
'service_worker' => [
'cache_name' => 'my-app-v1.0.1', // Increment version
],
PWA banner styling broken in Filament v4:
# Filament v4 uses Tailwind CSS v4 which has breaking changes
# The plugin has been updated to be compatible with both Tailwind v3 and v4
# Make sure you're using the latest version of the plugin
# Clear any cached views
php artisan view:clear
php artisan config:clear
Validation shows "Manifest file not found" or "Service worker not found":
# This is usually a false positive from older versions
# The plugin serves these files dynamically through routes, not as physical files
# Make sure the plugin is properly registered in your service provider
# Check if routes are registered
php artisan route:list | grep manifest
php artisan route:list | grep sw.js
PWA not installable:
# Validate PWA requirements
php artisan filament-pwa:setup --validate
# Check browser developer tools > Application > Manifest
Use the validation command to check your PWA setup:
php artisan filament-pwa:setup --validate
This checks for:
Note: The plugin serves manifest.json and sw.js dynamically through routes, not as physical files. The validation has been updated to check route registration instead of file existence.
Get detailed debug information about color detection and configuration:
use Alareqi\FilamentPwa\Services\PwaService;
// In a controller or command
$debug = PwaService::debugColorDetection();
dd($debug);
The debug output includes:
Use browser developer tools to debug PWA issues:
->name(string|Closure $name) // Set app name
->shortName(string|Closure $shortName) // Set short name
->description(string|Closure $description) // Set description
->startUrl(string|Closure $startUrl) // Set start URL
->themeColor(string|Closure $themeColor) // Set theme color
->backgroundColor(string|Closure $backgroundColor) // Set background color
->displayMode(string $mode) // Set display mode
->standalone() // Set standalone mode
->fullscreen() // Set fullscreen mode
->orientation(string $orientation) // Set orientation
->portrait() // Set portrait orientation
->landscape() // Set landscape orientation
->scope(string $scope) // Set navigation scope
->language(string|Closure $language) // Set language
->direction(string|Closure $direction) // Set text direction
->ltr() // Set left-to-right
->rtl() // Set right-to-left
->installation(bool $enabled, int $delay, int $iosDelay, bool $debugBanner) // Configure installation
->enableInstallation(int $delay = 2000) // Enable installation prompts
->disableInstallation() // Disable installation prompts
->enableDebugBanner(bool $enabled = true) // Enable debug banner
->categories(array $categories) // Set app categories
->shortcuts(array $shortcuts) // Set shortcuts
->addShortcut(string|Closure $name, string $url, string $description, array $icons) // Add shortcut
->icons(string $path, array $sizes, array $maskableSizes) // Configure icons
->serviceWorker(string $cacheName, string $offlineUrl, array $cacheUrls) // Configure service worker
PwaService::getMetaTags(array $config = []) // Get PWA meta tags
PwaService::getInstallationScript(array $config = []) // Get installation script
PwaService::isPWARequest() // Check if request is from PWA
PwaService::getConfig(array $overrides = []) // Get merged configuration
PwaService::validatePWAAssets() // Validate PWA assets
PwaService::debugColorDetection() // Debug color detection
composer test
We welcome contributions! Please see CONTRIBUTING for details on:
To add support for a new language:
Copy the English translation file:
cp resources/lang/en/pwa.php resources/lang/{locale}/pwa.php
Translate all strings while preserving:
:attribute)Test the translations in your application
Submit a pull request with your translation
Please review our security policy on how to report security vulnerabilities.
Please see CHANGELOG for more information on what has changed recently.
The MIT License (MIT). Please see License File for more information.
Made with ❤️ for the Filament community
How can I help you explore Laravel packages today?