feat: Improve PWA standalone experience and redirect to dashboard (#90)

## 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
This commit is contained in:
Víctor Falcón 2026-01-31 19:46:57 +01:00 committed by Víctor Falcón
parent dfd8bf8092
commit b4897ef425
4 changed files with 52 additions and 2 deletions

View File

@ -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",

23
public/sw.js Normal file
View File

@ -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).
});

View File

@ -2,7 +2,7 @@
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" @class(['dark' => ($appearance ?? 'system') == 'dark'])>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#383838" media="(prefers-color-scheme: dark)">
@ -62,5 +62,11 @@
event-uuid="696e6c66-33e0-482c-aa4a-a21410ec38c8"
src="https://tracker.metricswave.com/js/visits.js"
></script>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js', { scope: '/' });
}
</script>
</body>
</html>

21
tests/Feature/PwaTest.php Normal file
View File

@ -0,0 +1,21 @@
<?php
test('service worker exists', function () {
expect(file_exists(public_path('sw.js')))->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);
});