April 30, 2024
This post is based on my own experience at the time it was written. If you see anything that needs to be corrected or added, please let me know.
The idea for Alert Hero came from a need I’ve often felt when developing web services: I want to send push notifications to my devices to alert myself to important events. I also wanted to see what’s currently possible with Progressive Web Apps and web push notifications. Are PWAs a viable alternative to native apps?
With the release of iOS 16.4 and macOS 13.3 in March 2023, it finally became possible to install Progressive Web Apps and receive web push notifications on iOS and macOS devices. It had been a long wait for users of Apple devices since the initial rollout of PWAs in Chrome on Android in 2015, and this marked a welcome change. However, Apple’s implementation of the related web APIs is currently incomplete, resulting in impediments to the adoption of PWAs on iOS and macOS devices.
In Chrome you can intercept the beforeinstallprompt
event and show the user the browser’s prompt to install the PWA at an appropriate time—in response to the user clicking an “Install” button, for example. This API is not available in Safari, and Safari has no browser prompt to install the PWA, which means that you need to detect the user’s browser and platform and provide specific instructions for Safari users. In Safari on iOS, the user must tap the share button in the browser and select “Add to Home Screen”. In Safari on macOS, the user must select “Add to Dock…” from the File menu. The fact that this functionality is hidden away in menus likely significantly reduces the install rate for PWAs in Safari.
The appinstalled
event allows you to react when the PWA has been installed, but is not available in Safari.
You also might want to detect if the PWA is already installed on the device and direct the user to use the installed PWA instead of the browser. The getInstalledRelatedApps
method allows you to do this, but it is not available in Safari, and it returns an empty array in Chrome on desktop devices, even when the PWA has been installed with Chrome.
You can detect whether a page is running in a browser or in a standalone PWA by checking navigator?.standalone
and window.matchMedia('(display-mode: standalone)').matches
. Check both of these to cover all platforms.
If you do manage to get the user to install your PWA on an iOS device, they will only be able to enable and receive web push notifications in the PWA, since the Notification
API is not available in Safari on iOS. This API is available in Safari on macOS, however, so users can receive notifications in the browser and/or in an installed PWA.
It’s important to present every notification to the user immediately in the service worker (background notifications are not allowed), or else the device’s endpoint may stop working.
When an endpoint is no longer in use (perhaps because the user unsubscribed from notifications), the response code from notifications sent to Chrome endpoints is 410 or 404, which allows you to stop trying to send notifications to that endpoint. In my experience, the response from inactive Apple endpoints is no different from a successful delivery, which means that you’ll need to use other heuristics to detect inactive endpoints and stop sending notifications to them. For example, you could send a delivery confirmation from the service worker to your server and track deliveries to each endpoint over time.
There are differences in how PWAs work in different browsers and on different platforms, which can result in usability issues that need to be taken into account. For example, Chrome shares local data (such as cookies with authentication tokens, data in localStorage
, etc.) between the website running in the browser and an installed PWA. Safari copies this data to the PWA on installation, but after that the PWA and the website running in Safari maintain separate local data.
Deep linking to a PWA works on Android, but not on Apple devices. This means that on Apple devices, verification links sent to email won’t open the PWA. This is problematic if you’re using email verification links to log users in, because the PWA doesn’t have access to authentication tokens stored in Safari after installation. I’m currently working around this by prompting the user to paste the verification link from the email into a text input field that is only shown in the PWA, but this solution is far from ideal.
There can also be some glitchy behavior. On macOS, dismissing a PWA’s notification from the Notification Center opens the installed PWA, which is not the expected behavior, and sometimes notifications cause the PWA to launch, even when there is no user interaction.
Different browsers crop the PWA’s icon in different shapes and to different degrees, so the result will not look uniform on all devices.
Different browsers also present notifications differently: Chrome shows notifications only when the Chrome browser is running, but notifications from Safari-installed PWAs are generally shown even when the PWA or Safari are not running. When launching Chrome or a Chrome-installed PWA, the user may be presented with a batch of previously undelivered notifications all at once.
If your PWA includes dynamic content loaded from the server, you’ll need to configure offline fallbacks for each dynamic route in the service worker to make the app usable when the network is unavailable. This is currently not well supported in many web frameworks.
In Firefox, PWAs are not supported at all.
In order for PWAs to offer functionality on par with native apps, they need access to a wide range of capabilities through the relevant web APIs, not all of which have been finalized or widely implemented.
It’s not currently possible to submit an unmodified PWA to the Apple or Google app stores. To upload your PWA to these app stores, you’ll need to package it with something like Capacitor, Bubblewrap, or PWABuilder. You’ll also need to comply with the app stores’ rules, which generally means using their payment systems.
The process of installing, detecting, and using PWAs generally works well in Chrome. Apple’s introduction of support for PWAs is a step in the right direction, but until Apple fully implements the relevant web APIs, significant hurdles to the adoption of PWAs on iOS and macOS devices remain.