Add PWA support with service worker, manifest, and offline page

This commit is contained in:
dhanabalan
2025-11-04 09:44:37 +05:30
parent f47f5182a2
commit aed8c36089
5 changed files with 223 additions and 0 deletions

72
config/pwa.php Normal file
View File

@@ -0,0 +1,72 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Would you like the install button to appear on all pages?
Set true/false
|--------------------------------------------------------------------------
*/
'install-button' => true,
/*
|--------------------------------------------------------------------------
| PWA Manifest Configuration
|--------------------------------------------------------------------------
| php artisan erag:update-manifest
*/
// 'manifest' => [
// 'name' => 'Digital Manufacturing',
// 'short_name' => 'LPT',
// 'background_color' => '#6777ef',
// 'display' => 'standalone',
// 'description' => 'A Progressive Web Application setup for Laravel projects.',
// 'theme_color' => '#6777ef',
// 'icons' => [
// [
// 'src' => 'logo.png',
// 'sizes' => '512x512',
// 'type' => 'image/png',
// ],
// ],
// ],
'manifest' => [
'name' => 'Digital Manufacturing',
'short_name' => 'PWA',
'start_url' => '/',
'background_color' => '#6777ef',
'display' => 'fullscreen',
'description' => 'A Progressive Web Application setup for Laravel projects.',
'theme_color' => '#6777ef',
'icons' => [
[
'src' => 'logo.png',
'sizes' => '512x512',
'type' => 'image/png',
],
],
],
/*
|--------------------------------------------------------------------------
| Debug Configuration
|--------------------------------------------------------------------------
| Toggles the application's debug mode based on the environment variable
*/
'debug' => env('APP_DEBUG', false),
/*
|--------------------------------------------------------------------------
| Livewire Integration
|--------------------------------------------------------------------------
| Set to true if you're using Livewire in your application to enable
| Livewire-specific PWA optimizations or features.
*/
'livewire-app' => false,
];

16
public/manifest.json Normal file
View File

@@ -0,0 +1,16 @@
{
"name": "Laravel PWA",
"short_name": "LPT",
"background_color": "#6777ef",
"display": "standalone",
"description": "A Progressive Web Application setup for Laravel projects.",
"theme_color": "#6777ef",
"start_url": "/",
"icons": [
{
"src": "logo.png",
"sizes": "512x512",
"type": "image/png"
}
]
}

21
public/offline.html Normal file
View File

@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Check your internet connection</title>
<style> body {margin: 0;background: linear-gradient(172deg, #181722 20%, #ff2d20 100%, #8d7171 100%);display: flex;justify-content: center;align-items: center;height: 100vh;font-family: "Lato", sans-serif;}.container {text-align: center;}.text {color: #fff;font-weight: 300;font-size: 45px;margin-bottom: 40px;animation: fade-in-out 2.5s infinite;}.box {width: 240px;height: 150px;position: relative;margin: 0 auto;}.comp, .server {border: 3px solid #fff;}.comp {width: 80px;height: 55px;border-radius: 5px;position: absolute;top: 0;}.comp:after {content: "";position: absolute;top: 19px;left: 5px;width: 65px;height: 10px;border-radius: 360px;border: 3px solid #fff;}.loader {position: absolute;top: 26px;left: 12px;width: 8px;height: 7px;background: #fff;border-radius: 8%;animation: loader 5s infinite linear 0.5s;}.con {position: absolute;top: 28px;left: 85px;width: 100px;height: 3px;background: #fff;}.byte {position: absolute;top: 25px;left: 80px;width: 9px;height: 9px;background: #fff;border-radius: 50%;opacity: 0;animation: byte_animate 5s infinite linear 0.5s;z-index: 6;}.server {width: 35px;height: 65px;border-radius: 360px;background: #eaecf4;transform: rotateX(58deg);position: absolute;top: 6px;left: 185px;z-index: 1;}.server:before {content: "";position: absolute;top: -47px;left: -3px;width: 35px;height: 35px;background: #d3bbba;border-radius: 50%;border: 3px solid #fff;z-index: 20;}.server:after {content: "";position: absolute;top: -26px;left: -3px;width: 35px;height: 40px;background: #fff;border-left: 3px solid #fff;border-right: 3px solid #fff;z-index: 17;}@keyframes byte_animate {0% {opacity: 0;left: 80px }4% {opacity: 1 }46% {opacity: 1 }50% {opacity: 0;left: 185px }54% {opacity: 1 }96% {opacity: 1 }100% {opacity: 0;left: 80px }}@keyframes loader {0% {width: 8px }100% {width: 63px }}@keyframes fade-in-out {0%, 100% {opacity: 1 }50% {opacity: 0 }}</style>
</head>
<body>
<div class="container">
<div class="text">CONNECTING</div>
<div class="box">
<div class="comp"></div>
<div class="loader"></div>
<div class="con"></div>
<div class="byte"></div>
<div class="server"></div>
</div>
</div>
</body>
</html>

47
public/sw.js Normal file
View File

@@ -0,0 +1,47 @@
"use strict";
const CACHE_NAME = "offline-cache-v1";
const OFFLINE_URL = '/offline.html';
const filesToCache = [
OFFLINE_URL
];
self.addEventListener("install", (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => cache.addAll(filesToCache))
);
});
self.addEventListener("fetch", (event) => {
if (event.request.mode === 'navigate') {
event.respondWith(
fetch(event.request)
.catch(() => {
return caches.match(OFFLINE_URL);
})
);
} else {
event.respondWith(
caches.match(event.request)
.then((response) => {
return response || fetch(event.request);
})
);
}
});
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => {
if (cacheName !== CACHE_NAME) {
return caches.delete(cacheName);
}
})
);
})
);
});

View File

@@ -0,0 +1,67 @@
{{-- <link rel="manifest" href="{{ asset('manifest.json') }}">
<meta name="theme-color" content="#007bff">
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(function(registration) {
console.log('Service Worker registered with scope:', registration.scope);
}).catch(function(err) {
console.log('Service Worker registration failed:', err);
});
}
</script> --}}
{{-- <!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- PWA manifest and theme color -->
<link rel="manifest" href="{{ asset('manifest.json') }}">
<meta name="theme-color" content="#007bff">
<!-- Styles -->
<link href="{{ mix('css/app.css') }}" rel="stylesheet">
<!-- Service Worker -->
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(function(registration) {
console.log('Service Worker registered with scope:', registration.scope);
}).catch(function(err) {
console.log('Service Worker registration failed:', err);
});
}
</script>
</head>
<body>
@yield('content')
</body>
</html> --}}
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>@yield('title', 'Weight Scale Validation')</title>
<!-- Laravel PWA manifest and meta tags -->
@PwaHead
<link href="{{ mix('css/app.css') }}" rel="stylesheet">
</head>
<body>
@yield('content')
<script src="{{ mix('js/app.js') }}"></script>
@RegisterServiceWorkerScript
</body>
</html>