kit icon indicating copy to clipboard operation
kit copied to clipboard

beforeinstallprompt doesnt get fired in +layout.svelte

Open teemingc opened this issue 1 year ago • 5 comments

Discussed in https://github.com/sveltejs/kit/discussions/11550

Originally posted by rheanV January 9, 2024 I have an installable PWA (for sveltekit app). I want to add a custom button for installing the app. I placed my window.addEventListener('beforeinstallprompt', (event) => { event.preventDefault(); //logic }); in the onMount of the +layout.svelte file. I have all other configurations correct, meets all installation criteria, and can be installed via the browser download option in the URL bar. However, my "beforeinstallprompt" does not get fired in the +layout.svelte. If I place it in app.html then it is fired but not in +layout.svelte. How should I fix this? What am I missing in my sveltekit app setup?

teemingc avatar Feb 20 '24 16:02 teemingc

Same issue here - no clue if the use of this event in app.html can be a workaround? Please help

EDIT: A good workaround is

<script nonce="%sveltekit.nonce%">
			window.addEventListener('beforeinstallprompt', event => {
				event.preventDefault()
				window.deferredInstallPrompt = event
			})
</script>

and then where it's needed:

	const showInstallPrompt = async () => {
		if (window.deferredInstallPrompt) {
			await window.deferredInstallPrompt.prompt()
			window.deferredInstallPrompt = null
			canInstallApp = false
		}
	}

where canInstallApp is for displaying a button

laszlo1337 avatar Mar 03 '24 13:03 laszlo1337

Same issue here. Not only is the window.addEventListener for beforeinstallprompt not working, but also the event in the svelte:window tag is not fired too.

Feuerhamster avatar Sep 11 '24 13:09 Feuerhamster

It triggers very intermittently when adding the event listener to <svelte:window> so it's a timing issue. I wonder if we should try to somehow replay this event or wait for it to stablise across browsers. https://developer.mozilla.org/en-US/docs/Web/API/BeforeInstallPromptEvent

There's no guaranteed time this event is fired, but it usually happens on page load.

  • https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeinstallprompt_event
<svelte:window
  onbeforeinstallprompt={() => {
    console.log("beforeinstallprompt");
  }}
/>

teemingc avatar Dec 11 '24 03:12 teemingc

EDIT: A good workaround is

<script nonce="%sveltekit.nonce%">
			window.addEventListener('beforeinstallprompt', event => {
				event.preventDefault()
				window.deferredInstallPrompt = event
			})
</script>

This is great, and super helpful, however it does mean that pre-rendering is no longer an option (due to the included nonce)... but removing the nonce means that CSP wouldn't be able to be used in any secure fashion. 🙃

Rican7 avatar Mar 20 '25 22:03 Rican7

I can even put it into a component that gets loaded in the root +layout.svelte.

<script module lang="ts">
	let installPrompt: Event;
</script>

<svelte:window
	onbeforeinstallprompt={(e) => {
		installPrompt = e;
	}}
/>

It is worth mentioning that it only fires in production mode via https.

maxfriedmann avatar May 21 '25 07:05 maxfriedmann