composer require erag/laravel-pwa
php artisan erag:install-pwa
resources/views/layouts/app.blade.php):
<head>
@PwaHead
<!-- Other head tags -->
</head>
<body>
<!-- Content -->
@RegisterServiceWorkerScript
</body>
config/pwa.php with your app’s name, icons, and theme colors.php artisan erag:update-manifest to generate manifest.json and sw.js in public/.Ctrl+Shift+I), and check the "Application" tab for PWA registration.Configuration-Driven Setup:
config/pwa.php (name, icons, theme colors, etc.).PWA::update()) to dynamically modify settings at runtime (e.g., for multi-tenancy).Frontend Integration:
@PwaHead: Injects <link rel="manifest">, theme colors, and meta tags.@RegisterServiceWorkerScript: Registers the service worker with fallback logic.'livewire-app' => true in config.Dynamic Updates:
PWA::update(['name' => 'New App Name']);
PWA::processLogo($request); // For file uploads
Offline Support:
resources/views/vendor/pwa/offline.blade.php for offline pages.public/sw.js).config/pwa.php).public/sw.js to add custom caching logic (e.g., for API routes):
// public/sw.js
self.addEventListener('fetch', (event) => {
if (event.request.url.includes('/api/')) {
event.respondWith(caches.match(event.request));
}
});
debug: true in config/pwa.php to log service worker events to the console.Service Worker Registration:
scope parameter in sw.js:
// public/sw.js
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js', { scope: '/' }).catch(err => {
console.error('Service Worker registration failed: ', err);
});
});
}
manifest.json:
{
"display": "standalone",
"scope": "/",
"start_url": "/"
}
Manifest Updates:
config/pwa.php don’t reflect in manifest.json until you run php artisan erag:update-manifest.Livewire Compatibility:
'livewire-app' => true in config/pwa.php and ensure Livewire’s Alpine.js doesn’t interfere with service worker registration.Offline Page:
offline.blade.php isn’t served when offline.fetch event handler:
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
Application > Service Workers), reload the page, and check the "Registered" status.navigator.serviceWorker.controller to inspect the active worker.manifest.json using Google’s PWA Checker.short_name, invalid icon sizes, or incorrect start_url.$request->validate([
'logo' => 'required|image|mimes:png|max:1024',
]);
Custom Service Worker:
public/sw.js to add logic like:
caches.open('api-cache').then((cache) => {
return fetch('/api/data')
.then((response) => cache.put('/api/data', response.clone()))
.then(() => response);
});
Dynamic Manifests:
PWA::update([
'name' => Auth::user()->company_name,
'theme_color' => Auth::user()->preferred_color,
]);
Push Notifications:
self.addEventListener('push', (event) => {
const data = event.data.json();
event.waitUntil(
self.registration.showNotification(data.title, {
body: data.body,
icon: '/logo.png',
})
);
});
Local Development:
laravel-valet with HTTPS or configure trusted-proxies in config/app.php for local PWA testing:
'trusted_proxies' => ['127.0.0.1', '::1'],
How can I help you explore Laravel packages today?