From b4897ef4250fc467d01f57e7dc08ecf21faeb183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Falc=C3=B3n?= Date: Sat, 31 Jan 2026 19:46:57 +0100 Subject: [PATCH] feat: Improve PWA standalone experience and redirect to dashboard (#90) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Add service worker registration and `viewport-fit=cover` for proper iOS standalone mode (no Safari chrome) - Change manifest `start_url` to `/dashboard` so PWA users skip the landing page - Add tests for PWA configuration ## Test plan - [x] Deploy and re-add PWA to iOS home screen — should open as standalone (no address bar) - [x] PWA launch should go to `/dashboard` instead of the landing page - [x] Non-authenticated PWA users should be redirected to login Closes #71 --- public/favicon/site.webmanifest | 2 +- public/sw.js | 23 +++++++++++++++++++++++ resources/views/app.blade.php | 8 +++++++- tests/Feature/PwaTest.php | 21 +++++++++++++++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 public/sw.js create mode 100644 tests/Feature/PwaTest.php diff --git a/public/favicon/site.webmanifest b/public/favicon/site.webmanifest index 4ba73977..ae6b41c0 100644 --- a/public/favicon/site.webmanifest +++ b/public/favicon/site.webmanifest @@ -2,7 +2,7 @@ "name": "Whisper Money", "short_name": "Whisper Money", "description": "Track your finances privately and securely", - "start_url": "/", + "start_url": "/dashboard", "scope": "/", "id": "/", "display": "standalone", diff --git a/public/sw.js b/public/sw.js new file mode 100644 index 00000000..1ed5cb09 --- /dev/null +++ b/public/sw.js @@ -0,0 +1,23 @@ +const CACHE_NAME = 'whisper-money-v1'; + +self.addEventListener('install', (event) => { + self.skipWaiting(); +}); + +self.addEventListener('activate', (event) => { + event.waitUntil( + caches.keys().then((cacheNames) => + Promise.all( + cacheNames + .filter((name) => name !== CACHE_NAME) + .map((name) => caches.delete(name)), + ), + ), + ); + self.clients.claim(); +}); + +self.addEventListener('fetch', (event) => { + // Let all requests pass through to the network. + // The app handles offline state via IndexedDB (Dexie). +}); diff --git a/resources/views/app.blade.php b/resources/views/app.blade.php index 5482fe90..6066f90f 100644 --- a/resources/views/app.blade.php +++ b/resources/views/app.blade.php @@ -2,7 +2,7 @@ ($appearance ?? 'system') == 'dark'])> - + @@ -62,5 +62,11 @@ event-uuid="696e6c66-33e0-482c-aa4a-a21410ec38c8" src="https://tracker.metricswave.com/js/visits.js" > + + diff --git a/tests/Feature/PwaTest.php b/tests/Feature/PwaTest.php new file mode 100644 index 00000000..74dc2a20 --- /dev/null +++ b/tests/Feature/PwaTest.php @@ -0,0 +1,21 @@ +toBeTrue(); +}); + +test('web manifest starts at dashboard with standalone display', function () { + $manifest = json_decode(file_get_contents(public_path('favicon/site.webmanifest')), true); + + expect($manifest['start_url'])->toBe('/dashboard') + ->and($manifest['display'])->toBe('standalone'); +}); + +test('app template includes pwa meta tags and service worker registration', function () { + $response = $this->get('/'); + + $response->assertStatus(200) + ->assertSee('apple-mobile-web-app-capable', false) + ->assertSee('serviceWorker', false) + ->assertSee('viewport-fit=cover', false); +});