<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://web.dev/</id>
  <title>Alexey Rodionov on web.dev</title>
  <updated>2026-04-15T23:21:06Z</updated>
  <author>
    <name>Alexey Rodionov</name>
  </author>
  <link href="https://web.dev/authors/alexeyrodionov/feed.xml" rel="self"/>
  <link href="https://web.dev/"/>
  <icon>https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/n6mW0LtLb2NtYAoQSCx7.png?auto=format</icon>
  <logo>https://web.dev/images/shared/rss-banner.png</logo>
  <subtitle>PWA developer. UX/DX engineer. Web platform advocate. Google Developer Expert (GDE) in Web Technologies. PWA, Web Components, GraphQL evangelist. PWA Russian-speaking community organizer. Chromium contributor. Lead front-end developer at Mercury Development.</subtitle>
  
  
  <entry>
    <title>PWAs on Oculus Quest 2</title>
    <link href="https://web.dev/pwas-on-oculus-2/"/>
    <updated>2022-01-10T00:00:00Z</updated>
    <id>https://web.dev/pwas-on-oculus-2/</id>
    <content type="html" mode="escaped">&lt;h2 id=&quot;the-oculus-quest-2&quot;&gt;The Oculus Quest 2 &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#the-oculus-quest-2&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.oculus.com/quest-2/&quot; rel=&quot;noopener&quot;&gt;Oculus Quest 2&lt;/a&gt; is a virtual reality (VR) headset created
by Oculus, a division of Meta. It is the successor to the company&#39;s previous headset, the Oculus
Quest. The device is capable of running as both a standalone headset with an internal, Android-based
operating system, and with Oculus-compatible VR software running on a desktop computer when
connected over USB or Wi-Fi. It uses the Qualcomm
&lt;a href=&quot;https://www.qualcomm.com/news/onq/2020/10/29/oculus-quest-2-how-snapdragon-xr2-powers-next-generation-vr&quot; rel=&quot;noopener&quot;&gt;Snapdragon XR2&lt;/a&gt;
system on a chip with 6 GB of RAM. The Quest 2&#39;s display is a singular fast-switch LCD
panel with 1,832 × 1,920 pixels per eye resolution that runs at a refresh rate of up to
120 Hz.&lt;/p&gt;
&lt;img alt=&quot;Oculus Quest 2 device with controllers.&quot; decoding=&quot;async&quot; height=&quot;304&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/g0IQmlLaOiLWqwQuvnhQ.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h2 id=&quot;the-oculus-browser&quot;&gt;The Oculus Browser &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#the-oculus-browser&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Currently there are three browsers available for the Oculus Quest 2:
&lt;a href=&quot;https://www.oculus.com/experiences/quest/4812663595466206/&quot; rel=&quot;noopener&quot;&gt;Wolvic&lt;/a&gt;, a successor to
&lt;a href=&quot;https://www.oculus.com/experiences/quest/2180252408763702/&quot; rel=&quot;noopener&quot;&gt;Firefox Reality&lt;/a&gt;, and the built-in
&lt;a href=&quot;https://www.oculus.com/experiences/quest/1916519981771802&quot; rel=&quot;noopener&quot;&gt;Oculus Browser&lt;/a&gt;. This article focuses on
the latter. The Oculus website
&lt;a href=&quot;https://developer.oculus.com/documentation/web/browser-intro/&quot; rel=&quot;noopener&quot;&gt;introduces&lt;/a&gt; the Oculus Browser as
follows.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;quot;Oculus Browser provides support for the latest web standards and other technologies to help you
create VR experiences on the web. Today&#39;s 2D web sites work great in Oculus Browser because it&#39;s
powered by the Chromium rendering engine. It&#39;s further optimized for Oculus headsets to get the best
performance and to enable web developers take advantage of the full potential of VR with new APIs,
like WebXR. Through WebXR, we&#39;re opening the doors to the next frontier of the web.&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;img alt=&quot;Oculus Browser with three browser windows open.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/R4SwrV05Pqap583Rzr4L.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h3 id=&quot;user-agent&quot;&gt;User agent &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#user-agent&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The browser&#39;s user agent string at the time of writing is as follows.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;Mozilla/5.0 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;X11&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; Linux x86_64&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; Quest &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;AppleWebKit/537.36 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;KHTML, like Gecko&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;OculusBrowser/18.1.0.2.46.337441587&lt;br /&gt;SamsungBrowser/4.0&lt;br /&gt;Chrome/95.0.4638.74&lt;br /&gt;VR&lt;br /&gt;Safari/537.36&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;As you can see, the current version &lt;code&gt;18.1.0.2.46.337441587&lt;/code&gt; of the Oculus Browser is based on Chrome
&lt;code&gt;95.0.4638.74&lt;/code&gt;, that is only one version behind the current stable version of Chrome, which is
&lt;code&gt;96.0.4664.110&lt;/code&gt;. If the user switches to mobile mode, &lt;code&gt;VR&lt;/code&gt; changes to &lt;code&gt;Mobile VR&lt;/code&gt;.&lt;/p&gt;
&lt;img alt=&quot;Oculus Browser About page.&quot; decoding=&quot;async&quot; height=&quot;449&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/E3929PxcGa7GCxKoTffh.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h3 id=&quot;user-interface&quot;&gt;User interface &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#user-interface&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The browser&#39;s user interface (shown above) has the following features (top row from left to right):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Back button&lt;/li&gt;
&lt;li&gt;Reload button&lt;/li&gt;
&lt;li&gt;Site information&lt;/li&gt;
&lt;li&gt;URL bar&lt;/li&gt;
&lt;li&gt;Create bookmark button&lt;/li&gt;
&lt;li&gt;Resize button with narrow, medium, and wide options as well as a zoom feature&lt;/li&gt;
&lt;li&gt;Request mobile website button&lt;/li&gt;
&lt;li&gt;Menu button with the following options:
&lt;ul&gt;
&lt;li&gt;Enter private mode&lt;/li&gt;
&lt;li&gt;Close all tabs&lt;/li&gt;
&lt;li&gt;Settings&lt;/li&gt;
&lt;li&gt;Bookmarks&lt;/li&gt;
&lt;li&gt;Downloads&lt;/li&gt;
&lt;li&gt;History&lt;/li&gt;
&lt;li&gt;Clear browsing data&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The bottom row includes the following features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Close button&lt;/li&gt;
&lt;li&gt;Minimize button&lt;/li&gt;
&lt;li&gt;Three dots button with back, forward, and reload options&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;refresh-rate-and-device-pixel-ratio&quot;&gt;Refresh rate and device pixel ratio &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#refresh-rate-and-device-pixel-ratio&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For Oculus Quest 2, Oculus Browser renders both 2D web page content and WebXR at a
90 Hz refresh rate. When watching fullscreen media, Oculus Browser optimizes the device refresh
rate based on the frame rate of the video, for example, 24 fps. The Oculus Quest 2 has a
device pixel ratio of 1.5 for crisp text.&lt;/p&gt;
&lt;h2 id=&quot;pwas-in-oculus-browser-and-the-oculus-store&quot;&gt;PWAs in Oculus Browser and the Oculus Store &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#pwas-in-oculus-browser-and-the-oculus-store&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;On October 28, 2021, &lt;a href=&quot;https://twitter.com/jacobrossi&quot; rel=&quot;noopener&quot;&gt;Jacob Rossi&lt;/a&gt;, Product Management Lead at
Meta (Oculus), &lt;a href=&quot;https://twitter.com/jacobrossi/status/1453776349299019778&quot; rel=&quot;noopener&quot;&gt;shared&lt;/a&gt; that
&lt;a href=&quot;https://developer.oculus.com/pwa/&quot; rel=&quot;noopener&quot;&gt;PWAs were coming&lt;/a&gt; to Oculus Quest and Oculus Quest 2. In
the following, I describe the PWA experience on Oculus and explain how to build, sideload, and test
your PWA on the Oculus Quest 2.&lt;/p&gt;
&lt;h3 id=&quot;state-sharing&quot;&gt;State sharing &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#state-sharing&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Login state is shared between Oculus Browser and PWAs, allowing users to seamlessly switch between
the two. Naturally, &lt;a href=&quot;https://developers.facebook.com/docs/facebook-login/overview/&quot; rel=&quot;noopener&quot;&gt;Facebook Login&lt;/a&gt;
is supported out of the box. The Oculus Browser includes a password manager that allows users to
store and share their passwords securely between the browser and installed app experiences.&lt;/p&gt;
&lt;h3 id=&quot;pwa-window-sizes&quot;&gt;PWA window sizes &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#pwa-window-sizes&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Browser windows and windows of installed PWAs can be freely resized by the user. The height can vary
between 625 px and 1,200 px. The width can be set between 400 px and 2,000 px.
The default dimensions are 1,000 × 625 px.&lt;/p&gt;
&lt;h3 id=&quot;interacting-with-pwas&quot;&gt;Interacting with PWAs &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#interacting-with-pwas&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;PWAs can be controlled with the Oculus left and right controllers, Bluetooth mice and keyboards, and
via hand tracking. Scrolling works via the thumb sticks on the Oculus controllers, or by pinching
the thumb and the index finger and moving in the desired direction. To select something, the user
can point and pinch.&lt;/p&gt;
&lt;p&gt;&lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/8WbTDNrhLsU0El80frMBGE4eMCD3/20e7SXFMLC22gqW8HzRa.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;&lt;/p&gt;
&lt;h3 id=&quot;permissions-for-pwas&quot;&gt;Permissions for PWAs &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#permissions-for-pwas&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Permissions in Oculus Browser work pretty much the same way as in Chrome. The state is shared
between apps running in the browser and installed PWAs, so users can switch between the two
experiences without having to grant the same permissions again.&lt;/p&gt;
&lt;p&gt;Albeit many permissions are implemented, not all features are supported. For example, while
requesting the geolocation permission succeeds, the device never actually gets a location.
Similarly, the various hardware APIs like &lt;a href=&quot;https://web.dev/hid/&quot;&gt;WebHID&lt;/a&gt;, &lt;a href=&quot;https://web.dev/bluetooth/&quot;&gt;Web Bluetooth&lt;/a&gt;, etc. all
pass feature detection, but don&#39;t actually show a picker that would let the user pair the Oculus
with a hardware device. I suppose feature detectability of APIs will be refined once the browser
matures.&lt;/p&gt;
&lt;img alt=&quot;Permissions in Oculus Browser.&quot; decoding=&quot;async&quot; height=&quot;575&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fTX92hn8bIMpWVMoBUjE.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h3 id=&quot;debugging-pwas-via-chrome-devtools&quot;&gt;Debugging PWAs via Chrome DevTools &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#debugging-pwas-via-chrome-devtools&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After
&lt;a href=&quot;https://developer.oculus.com/documentation/native/android/mobile-device-setup/#enable-developer-mode&quot; rel=&quot;noopener&quot;&gt;enabling Developer Mode&lt;/a&gt;,
debugging PWAs on Oculus Quest 2 works exactly as described in
&lt;a href=&quot;https://developer.chrome.com/docs/devtools/remote-debugging/&quot; rel=&quot;noopener&quot;&gt;Remote debug Android devices&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;On the Oculus device, browse to the desired site in Oculus Browser.&lt;/li&gt;
&lt;li&gt;Launch Google Chrome on your computer and navigate to &lt;code&gt;chrome://inspect/#devices&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Find the Oculus device in question, which will be followed by a set of Oculus Browser tabs
currently open on the device.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;inspect&lt;/strong&gt; on the desired Oculus Browser tab.&lt;/li&gt;
&lt;/ol&gt;
&lt;img alt=&quot;Inspecting an app running on the Oculus Quest 2 with Chrome DevTools.&quot; decoding=&quot;async&quot; height=&quot;476&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/GiTjoiMuU2FoJOXLMEk2.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h3 id=&quot;app-discovery&quot;&gt;App discovery &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#app-discovery&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;People can use the browser itself or the &lt;a href=&quot;https://www.oculus.com/experiences/quest/&quot; rel=&quot;noopener&quot;&gt;Oculus Store&lt;/a&gt;
to discover PWAs. Just like with any other browser, installed PWAs also work in Oculus Browser as
websites running in a tab. When a user visits a site, the Oculus Browser will help them discover the
app if (and only if) it is available in the Oculus Store. For users that already have the app
installed, Oculus Browser will help them easily switch to the app if they desire.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Currently the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/BeforeInstallPromptEvent&quot;&gt;&lt;code&gt;BeforeInstallPrompt&lt;/code&gt; event&lt;/a&gt; will &lt;em&gt;not&lt;/em&gt; fire in Oculus Browser, despite feature detection reporting it to be supported. &lt;/div&gt;&lt;/aside&gt;
&lt;img alt=&quot;Oculus Browser inviting the user in a prompt to install the MyEmail app.&quot; decoding=&quot;async&quot; height=&quot;343&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 512px) 512px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/YNM3CfMKqnLuCJLw3I0U.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/YNM3CfMKqnLuCJLw3I0U.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/YNM3CfMKqnLuCJLw3I0U.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/YNM3CfMKqnLuCJLw3I0U.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/YNM3CfMKqnLuCJLw3I0U.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/YNM3CfMKqnLuCJLw3I0U.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/YNM3CfMKqnLuCJLw3I0U.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/YNM3CfMKqnLuCJLw3I0U.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/YNM3CfMKqnLuCJLw3I0U.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/YNM3CfMKqnLuCJLw3I0U.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/YNM3CfMKqnLuCJLw3I0U.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/YNM3CfMKqnLuCJLw3I0U.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/YNM3CfMKqnLuCJLw3I0U.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/YNM3CfMKqnLuCJLw3I0U.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/YNM3CfMKqnLuCJLw3I0U.png?auto=format&amp;w=1024 1024w&quot; width=&quot;512&quot; /&gt;
&lt;h2 id=&quot;exemplary-pwas-on-the-oculus-quest-2&quot;&gt;Exemplary PWAs on the Oculus Quest 2 &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#exemplary-pwas-on-the-oculus-quest-2&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;pwas-by-meta&quot;&gt;PWAs by Meta &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#pwas-by-meta&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Multiple Meta divisions have created PWAs for the Oculus Quest 2, for example
&lt;a href=&quot;https://www.oculus.com/experiences/quest/6102857836422862&quot; rel=&quot;noopener&quot;&gt;Instagram&lt;/a&gt; and
&lt;a href=&quot;https://www.oculus.com/experiences/quest/6126469507395223&quot; rel=&quot;noopener&quot;&gt;Facebook&lt;/a&gt;. These PWAs run in standalone
app windows that don&#39;t have a URL bar and that can be freely resized.&lt;/p&gt;
&lt;img alt=&quot;Facebook Oculus Quest 2 app.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/m5NoDaB7hyFOvrxHF9oS.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;img alt=&quot;Instagram Oculus Quest 2 app&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/gxYCh0Z9R3vXRU0MWsIB.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h3 id=&quot;pwas-by-other-developers&quot;&gt;PWAs by other developers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#pwas-by-other-developers&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;At the time of this writing, there is a small but growing number of PWAs for the Oculus Quest 2
on the Oculus Store. &lt;a href=&quot;https://www.oculus.com/experiences/quest/4949538568409451&quot; rel=&quot;noopener&quot;&gt;Spike&lt;/a&gt; lets users
experience all the essential work tools like email, chat, calls, notes, tasks, and to-dos from their
inbox in a virtual environment hub right in the Spike app.&lt;/p&gt;
&lt;img alt=&quot;Spike Oculus Quest 2 app.&quot; decoding=&quot;async&quot; height=&quot;450&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/yATTFGQRz75I2JrIAUSz.jpeg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;Another example is &lt;a href=&quot;https://www.oculus.com/experiences/quest/4636949963023496&quot; rel=&quot;noopener&quot;&gt;Smartsheet&lt;/a&gt;, a
dynamic workspace that provides project management, automated workflows, and rapid building of new
solutions.&lt;/p&gt;
&lt;p&gt;More PWAs like Slack, Dropbox, or Canva are coming, as teased in a
&lt;a href=&quot;https://www.facebook.com/watch/?v=4637130066326723&quot; rel=&quot;noopener&quot;&gt;video&lt;/a&gt; featuring Jacob Rossi that was released
in the context of Facebook&#39;s Connect conference in 2021.&lt;/p&gt;
&lt;h2 id=&quot;creating-pwas-for-oculus&quot;&gt;Creating PWAs for Oculus &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#creating-pwas-for-oculus&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Meta outlined the required steps in their
&lt;a href=&quot;https://developer.oculus.com/documentation/web/pwa-gs/&quot; rel=&quot;noopener&quot;&gt;documentation&lt;/a&gt;. In general, PWAs that are
installable in Chrome should oftentimes work out of the box on Oculus.&lt;/p&gt;
&lt;h3 id=&quot;web-app-manifest-requirements&quot;&gt;Web App Manifest requirements &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#web-app-manifest-requirements&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There are some important differences compared to
&lt;a href=&quot;https://web.dev/install-criteria/#criteria&quot;&gt;Chrome&#39;s installability criteria&lt;/a&gt; and the
&lt;a href=&quot;https://w3c.github.io/manifest/&quot; rel=&quot;noopener&quot;&gt;Web App Manifest spec&lt;/a&gt;. For example, Oculus only supports
left-to-right languages at the moment, whereas the Web App Manifest spec enforces no such
constraints. Another example is &lt;code&gt;start_url&lt;/code&gt;, which Chrome strictly requires for an app to be
installable, but which on Oculus is optional. Oculus offers a
&lt;a href=&quot;https://developer.oculus.com/documentation/web/pwa-packaging/&quot; rel=&quot;noopener&quot;&gt;command line tool&lt;/a&gt; that lets
developers create PWAs for the Oculus Quest 2, which allows them to pass the missing (or
override the existing) parameters in the Web App Manifest.&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(Required) The name of the PWA. Currently Oculus only supports left-to-right languages for the name.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;display&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(Required) Either &lt;code&gt;&quot;standalone&quot;&lt;/code&gt; or &lt;code&gt;&quot;minimal-ui&quot;&lt;/code&gt;. Oculus currently doesn&#39;t support any other values.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;short_name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(Required) A shorter version of the app name, if needed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scope&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(Optional) The URL or paths that should be considered as part of the app.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;start_url&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(Optional) The URL to show at app launch.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Oculus has a number of optional &lt;strong&gt;proprietary&lt;/strong&gt; Web App Manifest fields that can be used to
customize the PWA experience.&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ovr_package_name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(Optional) Sets the package name of the APK generated for the PWA. This must be in reverse domain name notation, e.g., &lt;code&gt;&quot;com.company.app.pwa&quot;&lt;/code&gt;. If not set, developers must provide a package name to the command line tool with the (then required) parameter &lt;code&gt;--package-name&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ovr_multi_tab_enabled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(Optional) If &lt;code&gt;true&lt;/code&gt;, this boolean field will give the PWA a tab bar similar to Oculus Browser. In multi-tab PWAs, internal links that target a new tab (&lt;code&gt;target=&quot;_new&quot;&lt;/code&gt; or &lt;code&gt;target=&quot;_blank&quot;&lt;/code&gt;) will open in new tabs within the PWA window. This differs from single-tab PWAs where such links would open to a Oculus Browser window. &lt;strong&gt;This feature is currently being standardized as &lt;a href=&quot;https://github.com/w3c/manifest/issues/737&quot; rel=&quot;noopener&quot;&gt;Tabbed Application Mode&lt;/a&gt;.&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ovr_scope_extensions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(Optional) Allows a PWA to include more web pages within the scope of the web application. It consists of a JSON dictionary containing extension URLs or wildcard patterns. &lt;strong&gt;This feature is currently being standardized as &lt;a href=&quot;https://github.com/WICG/manifest-incubations/blob/gh-pages/scope_extensions-explainer.md&quot; rel=&quot;noopener&quot;&gt;Scope Extensions for Web Apps&lt;/a&gt;.&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h3 id=&quot;packaging-pwas-with-bubblewrap-cli&quot;&gt;Packaging PWAs with Bubblewrap CLI &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#packaging-pwas-with-bubblewrap-cli&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/GoogleChromeLabs/bubblewrap&quot; rel=&quot;noopener&quot;&gt;Bubblewrap&lt;/a&gt; is an open source set of libraries and
a command line tool (CLI) for Node.js. Bubblewrap is developed by the Google Chrome team, to help
developers generate, build, and sign an Android project that launches your PWA as a
&lt;a href=&quot;https://developer.chrome.com/docs/android/trusted-web-activity/&quot; rel=&quot;noopener&quot;&gt;Trusted Web Activity&lt;/a&gt; (TWA).&lt;/p&gt;
&lt;p&gt;Meta Quest Browser currently doesn&#39;t fully support TWA, but starting from version 1.18.0,
Bubblewrap &lt;a href=&quot;https://github.com/GoogleChromeLabs/bubblewrap/releases/tag/v1.18.0&quot; rel=&quot;noopener&quot;&gt;supports&lt;/a&gt;
packaging PWAs for Meta Quest devices.&lt;/p&gt;
&lt;p&gt;It can generate &lt;em&gt;universal&lt;/em&gt; APK files that open a TWA on regular Android devices and the Meta Quest
Browser on Meta Quest devices.&lt;/p&gt;
&lt;p&gt;Assuming you have &lt;a href=&quot;https://nodejs.org/&quot; rel=&quot;noopener&quot;&gt;Node.js&lt;/a&gt; installed, Bubblewrap CLI can be installed with the
following command:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i -g @bubblewrap/cli&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;When running Bubblewrap for the first time, it will offer to automatically download and install the
required external dependencies—Java Development Kit (JDK) and Android SDK Build Tools.&lt;/p&gt;
&lt;p&gt;To generate a Meta Quest compatible Android project that wraps your PWA, run the &lt;code&gt;init&lt;/code&gt; command
with the &lt;code&gt;--metaquest&lt;/code&gt; flag and follow the wizard:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;bubblewrap init --manifest&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://your.web.app/manifest.json&quot;&lt;/span&gt; --metaquest&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Once the project has been generated, build and sign it by running:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;bubblewrap build&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This will output a file called &lt;code&gt;app-release-signed.apk&lt;/code&gt;. This file can be installed on the device
or published to the Meta Quest Store, Google Play Store or any of the other Android app distribution
platforms.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Pro tip: you can also use the &lt;code&gt;--chromeosonly&lt;/code&gt; flag in addition to the &lt;code&gt;--metaquest&lt;/code&gt; flag to make APK files compatible not only with Meta Quest and regular Android devices, but also with &lt;a href=&quot;https://chromeos.dev/&quot;&gt;ChromeOS&lt;/a&gt; devices. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;packaging-pwas-with-oculus-platform-utility&quot;&gt;Packaging PWAs with Oculus Platform Utility &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#packaging-pwas-with-oculus-platform-utility&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.oculus.com/documentation/web/pwa-packaging/#download-the-cli&quot; rel=&quot;noopener&quot;&gt;Oculus Platform Utility&lt;/a&gt;
is the official command line tool developed by Meta for publishing apps for Oculus Rift and Meta
Quest devices.&lt;/p&gt;
&lt;p&gt;It also allows to package PWAs for Meta Quest devices with the &lt;code&gt;create-pwa&lt;/code&gt; command and publish
them to the Meta Quest Store and App Lab.&lt;/p&gt;
&lt;p&gt;Set the output file name via the &lt;code&gt;-o&lt;/code&gt; parameter and the path to Android SDK via the &lt;code&gt;--android-sdk&lt;/code&gt;
parameter.&lt;/p&gt;
&lt;p&gt;Point the tool at the live URL of the web app manifest via the &lt;code&gt;--web-manifest-url&lt;/code&gt; parameter.&lt;/p&gt;
&lt;p&gt;If you don&#39;t have a manifest on your live PWA or wish to override the live manifest, you can still
generate an APK for your PWA using a local manifest file and the &lt;code&gt;--manifest-content-file&lt;/code&gt;
parameter.&lt;/p&gt;
&lt;p&gt;To leave the manifest as pure as possible, use the &lt;code&gt;--package-name&lt;/code&gt; parameter with a value in
reverse domain name notation (for example, &lt;code&gt;com.company.app.pwa&lt;/code&gt;), rather than adding the
proprietary &lt;code&gt;ovr_package_name&lt;/code&gt; field to the manifest.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;ovr-platform-util create-pwa -o output.apk --android-sdk ~/bin/android-10 --manifest-content-file manifest.json --package-name com.company.app.pwa&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; APK files generated by Oculus Platform Utility are only compatible with Meta Quest devices and cannot be run on regular Android devices. Also they can only be published to the Meta Quest Store and App Lab. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;packaging-pwas-with-pwabuilder&quot;&gt;Packaging PWAs with PWABuilder &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#packaging-pwas-with-pwabuilder&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Using &lt;a href=&quot;https://pwabuilder.com/&quot; rel=&quot;noopener&quot;&gt;PWABuilder&lt;/a&gt; is in the authors&#39; view the easiest and therefore
recommended way to package PWAs for Meta Quest at the moment.&lt;/p&gt;
&lt;p&gt;PWABuilder is an &lt;a href=&quot;https://github.com/pwa-builder&quot; rel=&quot;noopener&quot;&gt;open source&lt;/a&gt; project developed by Microsoft,
that allows developers to package and sign their PWAs for publishing to various stores, including
Microsoft Store, Google Play Store, App Store, and Meta Quest Store.&lt;/p&gt;
&lt;p&gt;Packaging PWAs with PWABuilder is as easy as entering the URL of a PWA, entering/editing the
metadata for the app, and clicking the &lt;strong&gt;Generate&lt;/strong&gt; button.&lt;/p&gt;
&lt;p&gt;PWABuilder gives developers the choice of what tool under the hood to use for packaging PWAs for
Meta Quest devices.&lt;/p&gt;
&lt;p&gt;You can choose the &lt;strong&gt;Meta Quest&lt;/strong&gt; option to use the Oculus Platform Utility.&lt;/p&gt;
&lt;img alt=&quot;PWABuilder packaging options.&quot; decoding=&quot;async&quot; height=&quot;600&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/nmHjO4Tbr01psSEfaaOO.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Pro tip: PWABuilder uses a slightly modified version of Oculus Platform Utility that generates much smaller APK files by &lt;a href=&quot;https://github.com/pwa-builder/pwabuilder-oculus/pull/7&quot;&gt;removing unused code and resources&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;You can choose the &lt;strong&gt;Android&lt;/strong&gt; option to use the Bubblewrap and select the &lt;strong&gt;Meta Quest compatible&lt;/strong&gt;
checkbox.&lt;/p&gt;
&lt;img alt=&quot;Packaging PWAs with PWABuilder using Bubblewrap.&quot; decoding=&quot;async&quot; height=&quot;600&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/jLnuUwLBi73HGXiv3XUy.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Pro tip: since PWABuilder is a PWA itself that works everywhere there is a browser, you can open it in the Meta Quest Browser and perform all the steps right on your Meta Quest. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;installing-pwas-with-adb&quot;&gt;Installing PWAs with ADB &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#installing-pwas-with-adb&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Important&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; To enable Android Debug Bridge (ADB) on the Meta Quest device, you must &lt;a href=&quot;https://developer.oculus.com/documentation/native/android/mobile-device-setup/&quot;&gt;enable developer mode&lt;/a&gt; in the companion mobile app. Before you can put your device in developer mode, you must belong to (or have created) a developer organization in the Oculus Developer Center. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;After creating the APK file, you can sideload it to the Meta Quest device using the ADB via
USB or Wi-Fi:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;adb &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; app-release-signed.apk&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If you use the Bubblewrap CLI for packaging PWAs, it provides a convenient alias command to
sideload the APK file:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;bubblewrap &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Pro tip: you can use &lt;a href=&quot;https://yume-chan.github.io/ya-webadb/install&quot;&gt;Android Web Toolbox&lt;/a&gt; to sideload APK files. It&#39;s an &lt;a href=&quot;https://github.com/yume-chan/ya-webadb/&quot;&gt;open source&lt;/a&gt; web app that allows you to access all ADB functionality right from the browser even from another Android device. No installation or drivers are required thanks to the &lt;a href=&quot;https://web.dev/usb/&quot;&gt;Web USB API&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Sideloaded apps appear in an &lt;strong&gt;Unknown Sources&lt;/strong&gt; section in the app drawer.&lt;/p&gt;
&lt;h3 id=&quot;app-submission&quot;&gt;App submission &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#app-submission&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Important&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Submission and consideration for the Oculus Store is only available if you have been approved as an Meta Quest Store developer. Distribution of PWAs via &lt;a href=&quot;https://developer.oculus.com/blog/introducing-app-lab-a-new-way-to-distribute-oculus-quest-apps/&quot;&gt;App Lab&lt;/a&gt; is not currently available. The Meta team will share more on when and how you can submit a PWA to App Lab soon. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Uploading and submitting PWAs to the Oculus Store is
&lt;a href=&quot;https://developer.oculus.com/documentation/web/pwa-submit-app/&quot; rel=&quot;noopener&quot;&gt;covered&lt;/a&gt; in detail in the Oculus
Developer Center docs.&lt;/p&gt;
&lt;p&gt;Apart from submitting apps to the Oculus Store, developers can also distribute their apps via platforms
like &lt;a href=&quot;https://sidequestvr.com/&quot; rel=&quot;noopener&quot;&gt;SideQuest&lt;/a&gt; directly to consumers safely and securely, without requiring
store approval. This allows them to get an app directly to end users, even if it is early in development,
experimental, or aimed at a unique audience.&lt;/p&gt;
&lt;h2 id=&quot;testing-multi-tab-apps&quot;&gt;Testing multi-tab apps &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#testing-multi-tab-apps&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To test multi-tab apps, I created a little &lt;a href=&quot;https://tomayac.github.io/oculus-pwa-test/&quot; rel=&quot;noopener&quot;&gt;test PWA&lt;/a&gt;
that demonstrates the various link features: namely opening a new in-PWA tab, staying on the current
tab, opening a new browser window, and opening in a WebView staying on the current tab. Create a
locally installable copy of this app by running the commands below on your machine.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;ovr-platform-util create-pwa -o test.apk --android-skd ~/bin/android-10 --web-manifest-url https://tomayac.github.io/oculus-pwa-test/manifest.json --package-name com.example.pwa&lt;br /&gt;adb &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; test.apk&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Here&#39;s a screencast of the test app.&lt;/p&gt;
&lt;div class=&quot;youtube&quot;&gt;  &lt;lite-youtube videoid=&quot;3ZlxCjW9rtg&quot;&gt;  &lt;/lite-youtube&gt;&lt;/div&gt;
&lt;h2 id=&quot;an-oculus-version-of-svgcode&quot;&gt;An Oculus version of SVGcode &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#an-oculus-version-of-svgcode&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To take the instructions for a spin, I created an Oculus version of my most recent PWA,
&lt;a href=&quot;https://web.dev/svgcode/&quot;&gt;SVGcode&lt;/a&gt;. You can download the resulting APK file
&lt;a href=&quot;https://drive.google.com/file/d/1ieGjwIXGGWmh0j9WpBdWqP7Bns3McNr1/view?usp=sharing&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;output.apk&lt;/code&gt;&lt;/a&gt;
from my Google Drive. If you want to investigate the package further, I have a
&lt;a href=&quot;https://drive.google.com/drive/folders/1EFtXK9ApJiJitfysZS_Z7iIWWiKEglu-?usp=sharing&quot; rel=&quot;noopener&quot;&gt;decompiled version&lt;/a&gt;,
too. Find the build instructions in
&lt;a href=&quot;https://github.com/tomayac/SVGcode/blob/6b23adf63a0a3a1b3828866dbb7db0f10206397f/package.json#L16&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Using the app on Oculus works fine, including the ability to open and save files. The Oculus Browser
doesn&#39;t support the &lt;a href=&quot;https://web.dev/file-system-access/&quot;&gt;File System Access API&lt;/a&gt;, but the
&lt;a href=&quot;https://web.dev/browser-fs-access/#the-traditional-way-of-dealing-with-files&quot;&gt;fallback approach&lt;/a&gt; helps. The only
thing that didn&#39;t function is pinch-zooming. My expectation was for it to work by pressing the
trigger button on both controllers and then moving the controllers in opposed directions. Other than
that, everything else was performant and responsive, as you can see in the embedded screencast.&lt;/p&gt;
&lt;div class=&quot;youtube&quot;&gt;  &lt;lite-youtube videoid=&quot;Gjc0IR17kAk&quot;&gt;  &lt;/lite-youtube&gt;&lt;/div&gt;
&lt;h2 id=&quot;immersive-3d-webxr-pwas&quot;&gt;Immersive 3D WebXR PWAs &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#immersive-3d-webxr-pwas&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;PWA support on Oculus Quest is not limited to flat 2D apps. Developers can build immersive 3D
experiences for VR using the &lt;a href=&quot;https://web.dev/tags/webxr/&quot;&gt;WebXR API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Wondering how various prompts (PWA install, permission requests, notifications) are handled
from within VR, if at all?&lt;/p&gt;
&lt;p&gt;Here&#39;s a screencast of
&lt;a href=&quot;https://immersive-web.github.io/webxr-samples/tests/permission-request.html&quot; rel=&quot;noopener&quot;&gt;User Agent Prompts test&lt;/a&gt;
from the &lt;a href=&quot;https://immersive-web.github.io/&quot; rel=&quot;noopener&quot;&gt;Immersive Web Working Group&lt;/a&gt;&#39;s
&lt;a href=&quot;https://immersive-web.github.io/webxr-samples/tests/&quot; rel=&quot;noopener&quot;&gt;WebXR Tests&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; playsinline=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/8WbTDNrhLsU0El80frMBGE4eMCD3/4fvDWOo2XxF67M8r3W3O.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;&lt;/p&gt;
&lt;p&gt;As you can see, entering VR mode requires the user&#39;s permission. Permissions are asked once per origin.
Requesting permissions leaves the immersive mode. Notifications are currently not supported.&lt;/p&gt;
&lt;h3 id=&quot;hand-tracking&quot;&gt;Hand tracking &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#hand-tracking&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can use your hands to interact with PWAs in immersive mode thanks to the
&lt;a href=&quot;https://immersive-web.github.io/webxr-hand-input/&quot; rel=&quot;noopener&quot;&gt;WebXR Hand Input API&lt;/a&gt; and Meta&#39;s
&lt;a href=&quot;https://ai.facebook.com/blog/hand-tracking-deep-neural-networks/&quot; rel=&quot;noopener&quot;&gt;AI-based hand-tracking system&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here&#39;s a screencast of
&lt;a href=&quot;https://immersive-web.github.io/webxr-samples/immersive-hands.html&quot; rel=&quot;noopener&quot;&gt;Hand Tracking Sample&lt;/a&gt;
from the Immersive Web Working Group&#39;s &lt;a href=&quot;https://immersive-web.github.io/webxr-samples/&quot; rel=&quot;noopener&quot;&gt;WebXR Samples&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; playsinline=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/8WbTDNrhLsU0El80frMBGE4eMCD3/nDm0rY5DvtyTbDgUqFTS.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;&lt;/p&gt;
&lt;h3 id=&quot;augmentedmixed-reality-passthrough&quot;&gt;Augmented/Mixed Reality (Passthrough) &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#augmentedmixed-reality-passthrough&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As announced at Meta Connect 2022, Meta Quest Browser
&lt;a href=&quot;https://developer.oculus.com/documentation/web/webxr-mixed-reality/&quot; rel=&quot;noopener&quot;&gt;has added support&lt;/a&gt; for
&lt;a href=&quot;https://web.dev/web-ar/&quot;&gt;WebXR Augmented Reality (AR)&lt;/a&gt;, also known as Mixed Reality (MR), on Meta Quest 2 and Meta
Quest Pro devices.&lt;/p&gt;
&lt;p&gt;Let&#39;s check a slightly modified A-Frame
&lt;a href=&quot;https://aframe.io/docs/1.3.0/introduction/#getting-started&quot; rel=&quot;noopener&quot;&gt;starter example&lt;/a&gt; with scaled-down
models and hidden sky and plane for augmented reality.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://aframe.io/&quot; rel=&quot;noopener&quot;&gt;A-Frame&lt;/a&gt; is an open source web framework for building 3D/VR/AR experiences
entirely out of declarative, reusable &lt;a href=&quot;https://web.dev/custom-elements-v1/&quot;&gt;custom HTML elements&lt;/a&gt; that are easy to
read, understand, and copy-and-paste.&lt;/p&gt;
&lt;div class=&quot;glitch-embed-wrap&quot; style=&quot;height: 420px; width: 100%;&quot;&gt;
  &lt;iframe allow=&quot;camera; clipboard-read; clipboard-write; encrypted-media; geolocation; microphone; midi; xr-spatial-tracking; fullscreen&quot; loading=&quot;lazy&quot; src=&quot;https://glitch.com/embed/#!/embed/a-frame-hello-world-ar?attributionHidden=true&amp;sidebarCollapsed=true&amp;path=index.html&amp;previewSize=50&quot; style=&quot;height: 100%; width: 100%; border: 0;&quot; title=&quot;a-frame-hello-world-ar on Glitch&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;Here&#39;s a screencast of this demo on Meta Quest 2.&lt;/p&gt;
&lt;p&gt;&lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; playsinline=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/8WbTDNrhLsU0El80frMBGE4eMCD3/RmPUmnh57gDZ2bbGkOWR.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Meta Quest 2 has monochrome cameras, so the passthrough is in grayscale, while Meta Quest Pro has
color cameras.&lt;/p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#conclusions&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;PWAs on Oculus Quest 2 are a lot of fun and very promising. The endless virtual canvas that
lets users scale their screen to whatever fits the current task best has a lot of potential to
change the way we work in the future. While typing in VR with hand tracking is still in its infancy
and, at least for me, doesn&#39;t work very reliably yet, it works well enough for entering URLs or
typing short texts.&lt;/p&gt;
&lt;p&gt;What I like the most about PWAs on the Oculus Quest 2 is that they are just regular PWAs that
can be used unchanged in a browser tab or through a thin APK wrapper without any platform-specific
APIs. Targeting multiple platforms with the same code has never been easier. Here&#39;s to PWAs in VR
and AR on the web. The future is bright!&lt;/p&gt;
&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/pwas-on-oculus-2/#acknowledgements&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Oculus Quest 2 photo by &lt;a href=&quot;https://flickr.com/people/191783462@N03/&quot; rel=&quot;noopener&quot;&gt;Maximilian Prandstätter&lt;/a&gt; on
&lt;a href=&quot;https://flickr.com/photos/191783462@N03/50844634326&quot; rel=&quot;noopener&quot;&gt;Flickr&lt;/a&gt;. Oculus Store images of
&lt;a href=&quot;https://www.oculus.com/experiences/quest/6102857836422862&quot; rel=&quot;noopener&quot;&gt;Instagram&lt;/a&gt;,
&lt;a href=&quot;https://www.oculus.com/experiences/quest/6126469507395223&quot; rel=&quot;noopener&quot;&gt;Facebook&lt;/a&gt;,
&lt;a href=&quot;https://www.oculus.com/experiences/quest/1916519981771802&quot; rel=&quot;noopener&quot;&gt;Oculus Browser&lt;/a&gt;, and
&lt;a href=&quot;https://www.oculus.com/experiences/quest/4949538568409451&quot; rel=&quot;noopener&quot;&gt;Spike&lt;/a&gt; apps as well as
&lt;a href=&quot;https://developer.oculus.com/pwa/&quot; rel=&quot;noopener&quot;&gt;app discoverability&lt;/a&gt; illustration and
&lt;a href=&quot;https://support.oculus.com/articles/headsets-and-accessories/controllers-and-hand-tracking/hand-tracking-quest-2/&quot; rel=&quot;noopener&quot;&gt;hand tracking&lt;/a&gt;
animation courtesy of Meta. Hero image by Arnau Marín i Puig. This post was reviewed by
&lt;a href=&quot;https://github.com/jpmedley&quot; rel=&quot;noopener&quot;&gt;Joe Medley&lt;/a&gt;.&lt;/p&gt;
</content>
    <author>
      <name>Thomas Steiner</name>
    </author><author>
      <name>Alexey Rodionov</name>
    </author>
  </entry>
  
  <entry>
    <title>Displaying a Notification</title>
    <link href="https://web.dev/push-notifications-display-a-notification/"/>
    <updated>2016-06-30T00:00:00Z</updated>
    <id>https://web.dev/push-notifications-display-a-notification/</id>
    <content type="html" mode="escaped">&lt;p&gt;The notification options is split into two sections, one that deals with the visual aspects (this
section) and one that explains the behavioral aspects of notifications (the next section).&lt;/p&gt;
&lt;p&gt;You can play around with various notification options in various browsers on various platforms
using &lt;a href=&quot;https://twitter.com/beverloo&quot; rel=&quot;noopener&quot;&gt;Peter Beverloo&lt;/a&gt;&#39;s
&lt;a href=&quot;https://tests.peter.sh/notification-generator/&quot; rel=&quot;noopener&quot;&gt;Notification Generator&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;visual-options&quot;&gt;Visual Options &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-display-a-notification/#visual-options&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The API for showing a notification is simple:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ServiceWorkerRegistration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;.showNotification(&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Both arguments, &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;options&lt;/code&gt; are optional.&lt;/p&gt;
&lt;p&gt;The title is a string and options can be any of the following:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;//&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Visual Options&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;body&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;String&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;icon&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;URL String&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;image&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;URL String&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;badge&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;URL String&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;dir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;String of &#39;auto&#39; | &#39;ltr&#39; | &#39;rtl&#39;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;Long&gt;&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;//&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Both visual &amp;amp; behavioral options&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;actions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;Array of Strings&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;Anything&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;//&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Behavioral Options&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;tag&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;String&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;requireInteraction&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;boolean&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;renotify&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;Boolean&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;vibrate&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;Array of Integers&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;sound&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;URL String&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;silent&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;Boolean&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Let&#39;s look at the visual options:&lt;/p&gt;
&lt;img alt=&quot;Dissection of the UI of a Notification.&quot; decoding=&quot;async&quot; height=&quot;284&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ZVIQcUqIlNerdPiqOM9C.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h3 id=&quot;title-and-body-options&quot;&gt;Title and body options &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-display-a-notification/#title-and-body-options&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is what a notification looks like without the title and options in Chrome on Windows:&lt;/p&gt;
&lt;img alt=&quot;Notification without the title and options in Chrome on Windows.&quot; decoding=&quot;async&quot; height=&quot;312&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 780px) 780px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/oq8F8nrC9z8aY3CtC8pr.png?auto=format&amp;w=1560 1560w&quot; width=&quot;780&quot; /&gt;
&lt;p&gt;As you can see, the browser name is used as the title and the &amp;quot;New notification&amp;quot; placeholder is
used as the notification body.&lt;/p&gt;
&lt;p&gt;If a progressive web application is installed on the device, the web app name will be used instead
of the browser name:&lt;/p&gt;
&lt;img alt=&quot;Notification with the web app name instead of the browser name.&quot; decoding=&quot;async&quot; height=&quot;312&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 780px) 780px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/5TmavxZQDURHIHQnwScW.png?auto=format&amp;w=1560 1560w&quot; width=&quot;780&quot; /&gt;
&lt;p&gt;If we ran the following code:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Simple Title&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Simple piece of body text.\nSecond line of body text :)&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;we&#39;d get this notification in Chrome on Linux:&lt;/p&gt;
&lt;img alt=&quot;Notification with title and body text in Chrome on Linux.&quot; decoding=&quot;async&quot; height=&quot;117&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 380px) 380px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/BZnd4sFC3XMq8yPUkYVz.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/BZnd4sFC3XMq8yPUkYVz.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/BZnd4sFC3XMq8yPUkYVz.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/BZnd4sFC3XMq8yPUkYVz.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/BZnd4sFC3XMq8yPUkYVz.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/BZnd4sFC3XMq8yPUkYVz.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/BZnd4sFC3XMq8yPUkYVz.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/BZnd4sFC3XMq8yPUkYVz.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/BZnd4sFC3XMq8yPUkYVz.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/BZnd4sFC3XMq8yPUkYVz.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/BZnd4sFC3XMq8yPUkYVz.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/BZnd4sFC3XMq8yPUkYVz.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/BZnd4sFC3XMq8yPUkYVz.png?auto=format&amp;w=760 760w&quot; width=&quot;380&quot; /&gt;
&lt;p&gt;In Firefox on Linux it would look like this:&lt;/p&gt;
&lt;img alt=&quot;Notification with title and body text in Firefox on Linux.&quot; decoding=&quot;async&quot; height=&quot;74&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 521px) 521px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/53pAkj17dCQhnODMk2jq.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/53pAkj17dCQhnODMk2jq.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/53pAkj17dCQhnODMk2jq.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/53pAkj17dCQhnODMk2jq.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/53pAkj17dCQhnODMk2jq.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/53pAkj17dCQhnODMk2jq.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/53pAkj17dCQhnODMk2jq.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/53pAkj17dCQhnODMk2jq.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/53pAkj17dCQhnODMk2jq.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/53pAkj17dCQhnODMk2jq.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/53pAkj17dCQhnODMk2jq.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/53pAkj17dCQhnODMk2jq.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/53pAkj17dCQhnODMk2jq.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/53pAkj17dCQhnODMk2jq.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/53pAkj17dCQhnODMk2jq.png?auto=format&amp;w=1042 1042w&quot; width=&quot;521&quot; /&gt;
&lt;p&gt;This is what the notification with a lot of text in the title and body looks like in Chrome on
Linux:&lt;/p&gt;
&lt;img alt=&quot;Notification with long title and body text in Chrome on Linux.&quot; decoding=&quot;async&quot; height=&quot;156&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 380px) 380px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/MjZfnuD9h6MJLjv9enVi.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/MjZfnuD9h6MJLjv9enVi.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/MjZfnuD9h6MJLjv9enVi.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/MjZfnuD9h6MJLjv9enVi.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/MjZfnuD9h6MJLjv9enVi.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/MjZfnuD9h6MJLjv9enVi.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/MjZfnuD9h6MJLjv9enVi.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/MjZfnuD9h6MJLjv9enVi.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/MjZfnuD9h6MJLjv9enVi.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/MjZfnuD9h6MJLjv9enVi.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/MjZfnuD9h6MJLjv9enVi.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/MjZfnuD9h6MJLjv9enVi.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/MjZfnuD9h6MJLjv9enVi.png?auto=format&amp;w=760 760w&quot; width=&quot;380&quot; /&gt;
&lt;p&gt;Firefox on Linux collapses the body text until you hover the notification, causing
the notification to expand:&lt;/p&gt;
&lt;img alt=&quot;Notification with long title and body text in Firefox on Linux.&quot; decoding=&quot;async&quot; height=&quot;74&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 521px) 521px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/hyJWXo3xO7AlrlE3I61F.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/hyJWXo3xO7AlrlE3I61F.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/hyJWXo3xO7AlrlE3I61F.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/hyJWXo3xO7AlrlE3I61F.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/hyJWXo3xO7AlrlE3I61F.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/hyJWXo3xO7AlrlE3I61F.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/hyJWXo3xO7AlrlE3I61F.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/hyJWXo3xO7AlrlE3I61F.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/hyJWXo3xO7AlrlE3I61F.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/hyJWXo3xO7AlrlE3I61F.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/hyJWXo3xO7AlrlE3I61F.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/hyJWXo3xO7AlrlE3I61F.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/hyJWXo3xO7AlrlE3I61F.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/hyJWXo3xO7AlrlE3I61F.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/hyJWXo3xO7AlrlE3I61F.png?auto=format&amp;w=1042 1042w&quot; width=&quot;521&quot; /&gt;
&lt;img alt=&quot;Notification with long title and body text in Firefox on Linux while hovering over the notification with the mouse cursor.&quot; decoding=&quot;async&quot; height=&quot;159&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 521px) 521px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Huyo4xr85SwcmPN9zSly.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Huyo4xr85SwcmPN9zSly.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Huyo4xr85SwcmPN9zSly.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Huyo4xr85SwcmPN9zSly.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Huyo4xr85SwcmPN9zSly.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Huyo4xr85SwcmPN9zSly.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Huyo4xr85SwcmPN9zSly.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Huyo4xr85SwcmPN9zSly.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Huyo4xr85SwcmPN9zSly.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Huyo4xr85SwcmPN9zSly.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Huyo4xr85SwcmPN9zSly.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Huyo4xr85SwcmPN9zSly.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Huyo4xr85SwcmPN9zSly.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Huyo4xr85SwcmPN9zSly.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Huyo4xr85SwcmPN9zSly.png?auto=format&amp;w=1042 1042w&quot; width=&quot;521&quot; /&gt;
&lt;p&gt;The same notifications in Firefox on Windows look like this:&lt;/p&gt;
&lt;img alt=&quot;Notification with title and body text in Firefox on Windows.&quot; decoding=&quot;async&quot; height=&quot;232&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 562px) 562px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/l5Pi7IvjKtGnn6YK2NdS.png?auto=format&amp;w=1124 1124w&quot; width=&quot;562&quot; /&gt;
&lt;img alt=&quot;Notification with long title and body text in Firefox on Windows.&quot; decoding=&quot;async&quot; height=&quot;281&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 562px) 562px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/OQRchMO68ph6UV2Lovy0.png?auto=format&amp;w=1124 1124w&quot; width=&quot;562&quot; /&gt;
&lt;p&gt;As you can see, the same notification may look different in different browsers. It may also look
different in the same browser on different platforms.&lt;/p&gt;
&lt;p&gt;Chrome and Firefox use the system notifications and notification center on platforms where these
are available.&lt;/p&gt;
&lt;p&gt;For example, system notifications on macOS don&#39;t support images and actions (buttons and inline
replies).&lt;/p&gt;
&lt;p&gt;Chrome also has a custom notifications for all desktop platforms. You can enable it by setting the
&lt;code&gt;chrome://flags/#enable-system-notifications&lt;/code&gt; flag to the &lt;code&gt;Disabled&lt;/code&gt; state.&lt;/p&gt;
&lt;h3 id=&quot;icon&quot;&gt;Icon &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-display-a-notification/#icon&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;icon&lt;/code&gt; option is essentially a small image you can show next to the title and body text.&lt;/p&gt;
&lt;p&gt;In your code you need to provide a URL to the image you&#39;d like to load:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Icon Notification&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/icon-512x512.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;You get this notification in Chrome on Linux:&lt;/p&gt;
&lt;img alt=&quot;Notification with icon in Chrome on Linux.&quot; decoding=&quot;async&quot; height=&quot;100&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 380px) 380px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/RBQH1QGLIRT9HxJTDjkj.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/RBQH1QGLIRT9HxJTDjkj.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/RBQH1QGLIRT9HxJTDjkj.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/RBQH1QGLIRT9HxJTDjkj.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/RBQH1QGLIRT9HxJTDjkj.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/RBQH1QGLIRT9HxJTDjkj.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/RBQH1QGLIRT9HxJTDjkj.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/RBQH1QGLIRT9HxJTDjkj.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/RBQH1QGLIRT9HxJTDjkj.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/RBQH1QGLIRT9HxJTDjkj.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/RBQH1QGLIRT9HxJTDjkj.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/RBQH1QGLIRT9HxJTDjkj.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/RBQH1QGLIRT9HxJTDjkj.png?auto=format&amp;w=760 760w&quot; width=&quot;380&quot; /&gt;
&lt;p&gt;and in Firefox on Linux:&lt;/p&gt;
&lt;img alt=&quot;Notification with icon in Firefox on Linux.&quot; decoding=&quot;async&quot; height=&quot;75&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 522px) 522px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/EoS5ydulQRjq1nxTJxrA.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/EoS5ydulQRjq1nxTJxrA.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/EoS5ydulQRjq1nxTJxrA.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/EoS5ydulQRjq1nxTJxrA.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/EoS5ydulQRjq1nxTJxrA.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/EoS5ydulQRjq1nxTJxrA.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/EoS5ydulQRjq1nxTJxrA.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/EoS5ydulQRjq1nxTJxrA.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/EoS5ydulQRjq1nxTJxrA.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/EoS5ydulQRjq1nxTJxrA.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/EoS5ydulQRjq1nxTJxrA.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/EoS5ydulQRjq1nxTJxrA.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/EoS5ydulQRjq1nxTJxrA.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/EoS5ydulQRjq1nxTJxrA.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/EoS5ydulQRjq1nxTJxrA.png?auto=format&amp;w=1044 1044w&quot; width=&quot;522&quot; /&gt;
&lt;p&gt;Sadly there aren&#39;t any solid guidelines for what size image to use for an icon.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://stackoverflow.com/questions/7220738/honeycomb-notifications-how-to-set-largeicon-to-the-right-size&quot; rel=&quot;noopener&quot;&gt;Android seems to want a 64dp image&lt;/a&gt;
(which is 64px multiples by the device pixel ratio).&lt;/p&gt;
&lt;p&gt;Assuming the highest pixel ratio for a device is 3, an icon size of 192px or more is a
safe bet.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Some browsers may require the image be served over HTTPS. Be aware of this if you intend to use a third-party image. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;badge&quot;&gt;Badge &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-display-a-notification/#badge&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;badge&lt;/code&gt; is a small monochrome icon that is used to portray a little more information to the
user about where the notification is from:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Badge Notification&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;badge&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/badge-128x128.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;At the time of writing the badge is only used in Chrome on Android.&lt;/p&gt;
&lt;img alt=&quot;Notification with badge in Chrome on Android.&quot; decoding=&quot;async&quot; height=&quot;248&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/LaAYwycbWMn8SCro7fyo.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;On other browsers (or Chrome without the badge), you&#39;ll see an icon of the browser.&lt;/p&gt;
&lt;img alt=&quot;Notification with badge in Firefox on Android.&quot; decoding=&quot;async&quot; height=&quot;212&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/Xy0ewGrawZtPRQWM99iR.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;As with the &lt;code&gt;icon&lt;/code&gt; option, there are no real guidelines on what size to use.&lt;/p&gt;
&lt;p&gt;Digging through &lt;a href=&quot;https://developer.android.com/guide/practices/ui_guidelines/icon_design_status_bar.html&quot; rel=&quot;noopener&quot;&gt;Android guidelines&lt;/a&gt;
the recommended size is 24px multiplied by the device pixel ratio.&lt;/p&gt;
&lt;p&gt;Meaning an image of 72px or more should be good (assuming a max device pixel ratio of 3).&lt;/p&gt;
&lt;h3 id=&quot;image&quot;&gt;Image &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-display-a-notification/#image&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;image&lt;/code&gt; option can be used to display a larger image to the user. This is particularly
useful to display a preview image to the user.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Image Notification&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/unsplash-farzad-nazifi-1600x1100.jpg&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;In Chrome on Linux the notification will look like this:&lt;/p&gt;
&lt;img alt=&quot;Notification with image in Chrome on Linux.&quot; decoding=&quot;async&quot; height=&quot;340&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 380px) 380px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/xF6oPjieHKCqtvrsWfM7.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/xF6oPjieHKCqtvrsWfM7.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/xF6oPjieHKCqtvrsWfM7.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/xF6oPjieHKCqtvrsWfM7.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/xF6oPjieHKCqtvrsWfM7.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/xF6oPjieHKCqtvrsWfM7.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/xF6oPjieHKCqtvrsWfM7.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/xF6oPjieHKCqtvrsWfM7.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/xF6oPjieHKCqtvrsWfM7.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/xF6oPjieHKCqtvrsWfM7.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/xF6oPjieHKCqtvrsWfM7.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/xF6oPjieHKCqtvrsWfM7.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/xF6oPjieHKCqtvrsWfM7.png?auto=format&amp;w=760 760w&quot; width=&quot;380&quot; /&gt;
&lt;p&gt;In Chrome on Android the cropping and ratio are different:&lt;/p&gt;
&lt;img alt=&quot;Notification with image in Chrome on Android.&quot; decoding=&quot;async&quot; height=&quot;554&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/VF32ZZXDZj2xO7dJdR3W.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;Given the differences in ratio between desktop and mobile, it&#39;s extremely hard to suggest
guidelines.&lt;/p&gt;
&lt;p&gt;Since Chrome on desktop doesn&#39;t fill the available space and has a ratio of 4:3, perhaps the best
approach is to serve an image with this ratio and allow Android to crop the image. That being said,
the &lt;code&gt;image&lt;/code&gt; option may still change.&lt;/p&gt;
&lt;p&gt;On Android, the only &lt;a href=&quot;https://code.google.com/p/android/issues/detail?id=36744&quot; rel=&quot;noopener&quot;&gt;guideline&lt;/a&gt; is a
width of 450dp.&lt;/p&gt;
&lt;p&gt;Using this guideline, an image of width 1350px or more would be a good bet.&lt;/p&gt;
&lt;h3 id=&quot;actions-buttons&quot;&gt;Actions (Buttons) &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-display-a-notification/#actions-buttons&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can define &lt;code&gt;actions&lt;/code&gt; to display buttons with a notification:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Actions Notification&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;coffee-action&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;button&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Coffee&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/action-1-128x128.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;doughnut-action&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;button&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Doughnut&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/action-2-128x128.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;gramophone-action&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;button&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Gramophone&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/action-3-128x128.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;atom-action&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;button&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Atom&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/action-4-128x128.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;For each action you can define a &lt;code&gt;title&lt;/code&gt;, an &lt;code&gt;action&lt;/code&gt; (which is essentially an ID), an &lt;code&gt;icon&lt;/code&gt;, and
a &lt;code&gt;type&lt;/code&gt;. The title and icon is what you can see in the notification. The ID is used when detecting
that the action button had been clicked (more about this in the next section). The type
can be omitted because &lt;code&gt;&#39;button&#39;&lt;/code&gt; is the default value.&lt;/p&gt;
&lt;p&gt;At the time of writing only Chrome and Opera for Android support actions.&lt;/p&gt;
&lt;p&gt;In the example above there are four actions defined to illustrate that you can define more actions than
will be displayed. If you want to know the number of actions that will be displayed by the browser,
you can check &lt;code&gt;window.Notification?.maxActions&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maxVisibleActions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Notification&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;maxActions&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maxVisibleActions&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Up to &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;maxVisibleActions&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; notification actions can be displayed.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Notification actions are not supported.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;On desktop, the action button icons display their colors (see the pink doughnut):&lt;/p&gt;
&lt;img alt=&quot;Notification with action buttons on Chrome on Linux.&quot; decoding=&quot;async&quot; height=&quot;178&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 380px) 380px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/REyUtJ7icGvOoepXgpLQ.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/REyUtJ7icGvOoepXgpLQ.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/REyUtJ7icGvOoepXgpLQ.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/REyUtJ7icGvOoepXgpLQ.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/REyUtJ7icGvOoepXgpLQ.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/REyUtJ7icGvOoepXgpLQ.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/REyUtJ7icGvOoepXgpLQ.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/REyUtJ7icGvOoepXgpLQ.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/REyUtJ7icGvOoepXgpLQ.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/REyUtJ7icGvOoepXgpLQ.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/REyUtJ7icGvOoepXgpLQ.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/REyUtJ7icGvOoepXgpLQ.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/REyUtJ7icGvOoepXgpLQ.png?auto=format&amp;w=760 760w&quot; width=&quot;380&quot; /&gt;
&lt;p&gt;On Android 6 and earlier, the icons are colored to match the system color scheme:&lt;/p&gt;
&lt;img alt=&quot;Notification with action buttons on Chrome for Android.&quot; decoding=&quot;async&quot; height=&quot;296&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/GI8sj9krxVtxWVeHGuvs.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;On Android 7 and later, the action icons aren&#39;t shown at all.&lt;/p&gt;
&lt;p&gt;Chrome will hopefully change it&#39;s behavior on desktop to match Android (i.e. apply the
appropriate color scheme to make the icons match the system look and feel). In the meantime, you
can match Chrome&#39;s text color by making your icons have a color of &lt;code&gt;#333333&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It&#39;s also worth calling out that icons look crisp on Android but &lt;strong&gt;not&lt;/strong&gt; on desktop.&lt;/p&gt;
&lt;p&gt;The best size I could get to work on desktop Chrome was 24px x 24px. This sadly looks out of place
on Android.&lt;/p&gt;
&lt;p&gt;The best practice we can draw from these differences:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Stick to a consistent color scheme for your icons so at least all your icons are consistently
displayed to the user.&lt;/li&gt;
&lt;li&gt;Make sure they work in monochrome as some platforms may display them that way.&lt;/li&gt;
&lt;li&gt;Test the size and see what works for you. 128px × 128px works well on Android for me but was poor
quality on desktop.&lt;/li&gt;
&lt;li&gt;Expect your action icons not to be displayed at all.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Notification spec is exploring a way to define multiple sizes of icons, but it looks like it&#39;ll
be some time before anything is agreed upon.&lt;/p&gt;
&lt;h3 id=&quot;actions-inline-replies&quot;&gt;Actions (Inline Replies) &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-display-a-notification/#actions-inline-replies&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can add an inline reply to the notification by defining an action with the &lt;code&gt;&#39;text&#39;&lt;/code&gt; type:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Alexey Rodionov&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;How are you doing? )&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/avatar-512x512.jpg&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/icon-512x512.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;badge&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/badge-128x128.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;reply&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;text&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Reply&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/action-5-128x128.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This is what it will look like on Android:&lt;/p&gt;
&lt;img alt=&quot;Notification on Android with a reply action button.&quot; decoding=&quot;async&quot; height=&quot;304&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/Ph3WKnKo7I2qIZdHSmzO.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;Clicking on the action button opens a text input field:&lt;/p&gt;
&lt;img alt=&quot;Notification on Android with an opened text input field.&quot; decoding=&quot;async&quot; height=&quot;330&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/3eVno9EWU28kN2DP2xIT.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;You can customize the placeholder for the text input field:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Alexey Rodionov&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;How are you doing? )&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/avatar-512x512.jpg&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;badge&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/badge-128x128.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;reply&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;text&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Reply&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/action-5-128x128.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Type text here&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;img alt=&quot;Notification on Android with customized placeholder for text input field.&quot; decoding=&quot;async&quot; height=&quot;330&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/dD8gIYQMO29voqF3qyHY.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;In Chrome on Windows, the text input field is always visible without having to click the action
button:&lt;/p&gt;
&lt;img alt=&quot;Notification on Windows with a text input field and a reply action button.&quot; decoding=&quot;async&quot; height=&quot;504&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 780px) 780px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qZhA529rWfVHzt7RVacJ.png?auto=format&amp;w=1560 1560w&quot; width=&quot;780&quot; /&gt;
&lt;p&gt;You can add more than one inline reply or combine buttons and inline replies:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Poll&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Do you like this photo?&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/cat-image.jpg&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/icon-512x512.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;badge&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/badge-128x128.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;yes&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;button&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;👍 Yes&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;no&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;text&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;👎 No (explain why)&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Type your explanation here&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;img alt=&quot;Notification on Windows with a text input field and two action buttons.&quot; decoding=&quot;async&quot; height=&quot;891&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/fKYyLvbAKghcnbmwEOfE.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h3 id=&quot;direction&quot;&gt;Direction &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-display-a-notification/#direction&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;dir&lt;/code&gt; parameter allows you to define which direction the text should be displayed,
right-to-left or left-to-right.&lt;/p&gt;
&lt;p&gt;In testing, it seemed that the direction was largely determined by the text rather than this
parameter. According to the spec, this is intended to suggest to the browser how to layout options
like actions, but I saw no difference.&lt;/p&gt;
&lt;p&gt;Probably best to define if you can, otherwise the browser should do the right thing according to
the text supplied.&lt;/p&gt;
&lt;p&gt;The parameter should be set to either &lt;code&gt;auto&lt;/code&gt;, &lt;code&gt;ltr&lt;/code&gt; or &lt;code&gt;rtl&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A right-to-left language used on Chrome on Linux looks like this:&lt;/p&gt;
&lt;img alt=&quot;Notification with right-to-left language on Chrome on Linux.&quot; decoding=&quot;async&quot; height=&quot;234&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 380px) 380px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/epWm0UDjQzcRMz37uaaa.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/epWm0UDjQzcRMz37uaaa.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/epWm0UDjQzcRMz37uaaa.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/epWm0UDjQzcRMz37uaaa.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/epWm0UDjQzcRMz37uaaa.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/epWm0UDjQzcRMz37uaaa.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/epWm0UDjQzcRMz37uaaa.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/epWm0UDjQzcRMz37uaaa.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/epWm0UDjQzcRMz37uaaa.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/epWm0UDjQzcRMz37uaaa.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/epWm0UDjQzcRMz37uaaa.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/epWm0UDjQzcRMz37uaaa.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/epWm0UDjQzcRMz37uaaa.png?auto=format&amp;w=760 760w&quot; width=&quot;380&quot; /&gt;
&lt;p&gt;In Firefox (while hovering over it) you&#39;ll get this:&lt;/p&gt;
&lt;img alt=&quot;Notification with right-to-left language on Firefox on Linux.&quot; decoding=&quot;async&quot; height=&quot;102&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 521px) 521px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ncKq2yMj7ipFkGGOWKBr.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ncKq2yMj7ipFkGGOWKBr.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ncKq2yMj7ipFkGGOWKBr.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ncKq2yMj7ipFkGGOWKBr.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ncKq2yMj7ipFkGGOWKBr.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ncKq2yMj7ipFkGGOWKBr.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ncKq2yMj7ipFkGGOWKBr.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ncKq2yMj7ipFkGGOWKBr.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ncKq2yMj7ipFkGGOWKBr.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ncKq2yMj7ipFkGGOWKBr.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ncKq2yMj7ipFkGGOWKBr.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ncKq2yMj7ipFkGGOWKBr.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ncKq2yMj7ipFkGGOWKBr.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ncKq2yMj7ipFkGGOWKBr.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/ncKq2yMj7ipFkGGOWKBr.png?auto=format&amp;w=1042 1042w&quot; width=&quot;521&quot; /&gt;
&lt;h3 id=&quot;vibrate&quot;&gt;Vibrate &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-display-a-notification/#vibrate&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Support for &lt;a href=&quot;https://crbug.com/971422&quot;&gt;&lt;code&gt;vibrate&lt;/code&gt; has been deprecated&lt;/a&gt; on Android 8 and later. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;The vibrate option allows you to define a vibration pattern that&#39;ll run when a notification is
displayed, assuming the user&#39;s current settings allow for vibrations (i.e. the device isn&#39;t in
silent mode).&lt;/p&gt;
&lt;p&gt;The format of the vibrate option should be an array of numbers that describe the number of
milliseconds the device should vibrate, followed by the number of milliseconds the device should
&lt;em&gt;not&lt;/em&gt; vibrate.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Vibrate Notification&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;// Star Wars shamelessly taken from the awesome Peter Beverloo&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;// https://tests.peter.sh/notification-generator/&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;vibrate&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;110&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;110&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;450&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;110&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;110&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;170&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;450&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;110&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;110&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;170&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token number&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This only affects devices that support vibration.&lt;/p&gt;
&lt;h3 id=&quot;sound&quot;&gt;Sound &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-display-a-notification/#sound&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The sound parameter allows you to define a sound to play when the notification is received.&lt;/p&gt;
&lt;p&gt;At the time of writing, no browser has support for this option.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Sound Notification&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;sound&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/demos/notification-examples/audio/notification-sound.mp3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;timestamp&quot;&gt;Timestamp &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-display-a-notification/#timestamp&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Timestamp allows you to tell the platform the time when an event occurred that resulted in the push
notification being sent.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;timestamp&lt;/code&gt; should be the number of milliseconds since 00:00:00 UTC, which is 1 January 1970
(which is the UNIX epoch).&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Timestamp Notification&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Timestamp is set to &quot;01 Jan 2000 00:00:00&quot;.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;01 Jan 2000 00:00:00&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;ux-best-practices&quot;&gt;UX Best Practices &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-display-a-notification/#ux-best-practices&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The biggest UX failure I&#39;ve seen with notifications is a lack of specificity in the information
displayed by a notification.&lt;/p&gt;
&lt;p&gt;You should consider why you sent the push message in the first place and make sure all of the
notification options are used to help users understand why they are reading that notification.&lt;/p&gt;
&lt;p&gt;To be honest, it&#39;s easy to see examples and think &amp;quot;I&#39;ll never make that mistake&amp;quot;. But it&#39;s easier
to fall into that trap than you might think.&lt;/p&gt;
&lt;p&gt;Some common pitfalls to avoid:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don&#39;t put your website in the title or the body. Browsers include your domain in the
notification so &lt;strong&gt;don&#39;t duplicate it&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Use all the information that you have available. If you send a push message because someone
sent a message to a user, rather than using a title of &#39;New Message&#39; and body of &#39;Click here to
read it.&#39; use a title of &#39;John just sent a new message&#39; and set the body of the notification to
part of the message.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;browsers-and-feature-detection&quot;&gt;Browsers and feature detection &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-display-a-notification/#browsers-and-feature-detection&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At the time of writing, there is a pretty big disparity between Chrome and Firefox in terms of
feature support for notifications.&lt;/p&gt;
&lt;p&gt;Luckily, you can detect support for notification features by looking at the &lt;code&gt;window.Notification&lt;/code&gt;
prototype.&lt;/p&gt;
&lt;p&gt;Let&#39;s say we wanted to know if a notification supports action buttons, we&#39;d do the following:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;actions&#39;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Notification&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Action buttons are supported.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Action buttons are NOT supported.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;With this, we could change the notification we display to our users.&lt;/p&gt;
&lt;p&gt;With the other options, just do the same as above, replacing &lt;code&gt;&#39;actions&#39;&lt;/code&gt; with the desired
parameter name.&lt;/p&gt;
&lt;h2 id=&quot;where-to-go-next&quot;&gt;Where to go next &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-display-a-notification/#where-to-go-next&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-overview/&quot;&gt;Web Push Notification Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-how-push-works/&quot;&gt;How Push Works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-subscribing-a-user/&quot;&gt;Subscribing a User&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-permissions-ux/&quot;&gt;Permission UX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/sending-messages-with-web-push-libraries/&quot;&gt;Sending Messages with Web Push Libraries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-web-push-protocol/&quot;&gt;Web Push Protocol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-handling-messages/&quot;&gt;Handling Push Events&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Displaying a Notification&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-notification-behaviour/&quot;&gt;Notification Behavior&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-common-notification-patterns/&quot;&gt;Common Notification Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-faq/&quot;&gt;Push Notifications FAQ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-common-issues-and-reporting-bugs/&quot;&gt;Common Issues and Reporting Bugs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;code-labs&quot;&gt;Code labs &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-display-a-notification/#code-labs&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-client-codelab/&quot;&gt;Build a push notification client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-server-codelab/&quot;&gt;Build a push notification server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Matt Gaunt</name>
    </author><author>
      <name>Alexey Rodionov</name>
    </author>
  </entry>
  
  <entry>
    <title>Notification behavior</title>
    <link href="https://web.dev/push-notifications-notification-behaviour/"/>
    <updated>2016-06-30T00:00:00Z</updated>
    <id>https://web.dev/push-notifications-notification-behaviour/</id>
    <content type="html" mode="escaped">&lt;p&gt;So far, we&#39;ve looked at the options that alter the visual appearance of a notification. There are
also options that alter the behavior of notifications.&lt;/p&gt;
&lt;p&gt;By default, calling &lt;code&gt;showNotification()&lt;/code&gt; with just visual options will have the following
behaviors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Clicking on the notification does nothing.&lt;/li&gt;
&lt;li&gt;Each new notification is shown one after the other. The browser will not collapse the
notifications in any way.&lt;/li&gt;
&lt;li&gt;The platform may play a sound or vibrate the user&#39;s device (depending on the platform).&lt;/li&gt;
&lt;li&gt;On some platforms, the notification will disappear after a short period of time while others will
show the notification unless the user interacts with it. (For example, compare your notifications
on Android and Desktop.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this section, we are going to look at how we can alter these default behaviors using options
alone. These are relatively easy to implement and take advantage of.&lt;/p&gt;
&lt;h2 id=&quot;notification-click-event&quot;&gt;Notification Click Event &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-notification-behaviour/#notification-click-event&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When a user clicks on a notification, the default behavior is for nothing to happen. It doesn&#39;t
even close or remove the notification.&lt;/p&gt;
&lt;p&gt;The common practice for a notification click is for it to close and perform some other logic (i.e.
open a window or make some API call to the application).&lt;/p&gt;
&lt;p&gt;To achieve this, you need to add a &lt;code&gt;&#39;notificationclick&#39;&lt;/code&gt; event listener to our service worker. This
will be called whenever a notification is clicked.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;notificationclick&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; clickedNotification &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;notification&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  clickedNotification&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Do something as the result of the notification click&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; promiseChain &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;waitUntil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;promiseChain&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;As you can see in this example, the notification that was clicked can be accessed as
&lt;code&gt;event.notification&lt;/code&gt;. From this, you can access the notification&#39;s properties and methods. In this
case, you call its &lt;code&gt;close()&lt;/code&gt; method and perform additional work.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; You need to make use of &lt;code&gt;event.waitUntil()&lt;/code&gt; to keep the service worker running while your code is busy. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;actions&quot;&gt;Actions &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-notification-behaviour/#actions&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Actions allow you to create another level of interaction with your users over just clicking the
notification.&lt;/p&gt;
&lt;h3 id=&quot;buttons&quot;&gt;Buttons &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-notification-behaviour/#buttons&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the previous section, you saw how to define action buttons when calling &lt;code&gt;showNotification()&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Actions Notification&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;coffee-action&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Coffee&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;button&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/action-1-128x128.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;doughnut-action&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;button&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Doughnut&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/action-2-128x128.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;gramophone-action&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;button&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Gramophone&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/action-3-128x128.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;atom-action&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;button&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Atom&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/action-4-128x128.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If the user clicks an action button, check the &lt;code&gt;event.action&lt;/code&gt; value in the &lt;code&gt;noticationclick&lt;/code&gt;
event to tell which action button was clicked.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;event.action&lt;/code&gt; will contain the &lt;code&gt;action&lt;/code&gt; value set in the options. In the example above the
&lt;code&gt;event.action&lt;/code&gt; values would be one of the following: &lt;code&gt;&#39;coffee-action&#39;&lt;/code&gt;, &lt;code&gt;&#39;doughnut-action&#39;&lt;/code&gt;,
&lt;code&gt;&#39;gramophone-action&#39;&lt;/code&gt; or &lt;code&gt;&#39;atom-action&#39;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With this we would detect notification clicks or action clicks like so:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;notificationclick&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;action&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Was a normal notification click&lt;/span&gt;&lt;br /&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Notification Click.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;action&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;coffee-action&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;User ❤️️&#39;s coffee.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;doughnut-action&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;User ❤️️&#39;s doughnuts.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;gramophone-action&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;User ❤️️&#39;s music.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;atom-action&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;User ❤️️&#39;s science.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Unknown action clicked: &#39;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;action&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;inline-replies&quot;&gt;Inline Replies &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-notification-behaviour/#inline-replies&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Also, in the previous section, you saw how to add an inline reply to the notification:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Poll&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Do you like this photo?&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/cat-image.jpg&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/icon-512x512.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;badge&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/images/demos/badge-128x128.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;yes&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;button&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;👍 Yes&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;no&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;text&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;👎 No (explain why)&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Type your explanation here&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;event.reply&lt;/code&gt; will contain the value typed by the user in the input field:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;notificationclick&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; reply &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;reply&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Do something with the user&#39;s reply&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; promiseChain &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reply&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;waitUntil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;promiseChain&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;tag&quot;&gt;Tag &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-notification-behaviour/#tag&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;tag&lt;/code&gt; option is essentially a string ID that &amp;quot;groups&amp;quot; notifications together, providing an easy
way to determine how multiple notifications are displayed to the user. This is easiest to explain
with an example.&lt;/p&gt;
&lt;p&gt;Let&#39;s display a notification and give it a tag, of &lt;code&gt;&#39;message-group-1&#39;&lt;/code&gt;. We&#39;d display the
notification with this code:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Notification 1 of 3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;With &#39;tag&#39; of &#39;message-group-1&#39;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;message-group-1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Which will show our first notification.&lt;/p&gt;
&lt;img alt=&quot;First notification with tag of message group 1.&quot; decoding=&quot;async&quot; height=&quot;222&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 380px) 380px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/UKvAEJq7hWFQsxQjlnKv.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/UKvAEJq7hWFQsxQjlnKv.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/UKvAEJq7hWFQsxQjlnKv.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/UKvAEJq7hWFQsxQjlnKv.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/UKvAEJq7hWFQsxQjlnKv.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/UKvAEJq7hWFQsxQjlnKv.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/UKvAEJq7hWFQsxQjlnKv.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/UKvAEJq7hWFQsxQjlnKv.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/UKvAEJq7hWFQsxQjlnKv.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/UKvAEJq7hWFQsxQjlnKv.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/UKvAEJq7hWFQsxQjlnKv.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/UKvAEJq7hWFQsxQjlnKv.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/UKvAEJq7hWFQsxQjlnKv.png?auto=format&amp;w=760 760w&quot; width=&quot;380&quot; /&gt;
&lt;p&gt;Let&#39;s display a second notification with a new tag of &lt;code&gt;&#39;message-group-2&#39;&lt;/code&gt;, like so:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Notification 2 of 3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;With &#39;tag&#39; of &#39;message-group-2&#39;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;message-group-2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This will display a second notification to the user.&lt;/p&gt;
&lt;img alt=&quot;Two notifications where the second tag of message group 2.&quot; decoding=&quot;async&quot; height=&quot;222&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 380px) 380px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/L1reebxFF4pJ1sIYRvcE.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/L1reebxFF4pJ1sIYRvcE.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/L1reebxFF4pJ1sIYRvcE.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/L1reebxFF4pJ1sIYRvcE.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/L1reebxFF4pJ1sIYRvcE.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/L1reebxFF4pJ1sIYRvcE.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/L1reebxFF4pJ1sIYRvcE.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/L1reebxFF4pJ1sIYRvcE.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/L1reebxFF4pJ1sIYRvcE.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/L1reebxFF4pJ1sIYRvcE.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/L1reebxFF4pJ1sIYRvcE.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/L1reebxFF4pJ1sIYRvcE.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/L1reebxFF4pJ1sIYRvcE.png?auto=format&amp;w=760 760w&quot; width=&quot;380&quot; /&gt;
&lt;p&gt;Now let&#39;s show a third notification but re-use the first tag of &lt;code&gt;&#39;message-group-1&#39;&lt;/code&gt;. Doing this
will close the first notification and replace it with our new notification.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Notification 3 of 3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;With &#39;tag&#39; of &#39;message-group-1&#39;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;message-group-1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Now we have two notifications even though &lt;code&gt;showNotification()&lt;/code&gt; was called three times.&lt;/p&gt;
&lt;img alt=&quot;Two notifications where the first notification is replaced by a third notification.&quot; decoding=&quot;async&quot; height=&quot;222&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 380px) 380px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/RLHBEuD6REvyuZhHgWJw.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/RLHBEuD6REvyuZhHgWJw.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/RLHBEuD6REvyuZhHgWJw.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/RLHBEuD6REvyuZhHgWJw.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/RLHBEuD6REvyuZhHgWJw.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/RLHBEuD6REvyuZhHgWJw.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/RLHBEuD6REvyuZhHgWJw.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/RLHBEuD6REvyuZhHgWJw.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/RLHBEuD6REvyuZhHgWJw.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/RLHBEuD6REvyuZhHgWJw.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/RLHBEuD6REvyuZhHgWJw.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/RLHBEuD6REvyuZhHgWJw.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/RLHBEuD6REvyuZhHgWJw.png?auto=format&amp;w=760 760w&quot; width=&quot;380&quot; /&gt;
&lt;p&gt;The &lt;code&gt;tag&lt;/code&gt; option is simply a way of grouping messages so that any old notifications that are
currently displayed will be closed if they have the same tag as a new notification.&lt;/p&gt;
&lt;p&gt;A subtlety to using &lt;code&gt;tag&lt;/code&gt; is that when it replaces a notification, it will do so &lt;em&gt;without&lt;/em&gt; a sound
or vibration.&lt;/p&gt;
&lt;p&gt;This is where the &lt;code&gt;renotify&lt;/code&gt; option comes in.&lt;/p&gt;
&lt;h2 id=&quot;renotify&quot;&gt;Renotify &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-notification-behaviour/#renotify&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This largely applies to mobile devices at the time of writing. Setting this option makes new
notifications vibrate and play a system sound.&lt;/p&gt;
&lt;p&gt;There are scenarios where you might want a replacing notification to notify the user rather than
silently update. Chat applications are a good example. In this case, you should set &lt;code&gt;tag&lt;/code&gt; and
&lt;code&gt;renotify&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Notification 2 of 2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;renotify&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;renotify&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; If you set &lt;code&gt;renotify&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; on a notification without a &lt;code&gt;tag&lt;/code&gt;, you&#39;ll get the following error: &lt;code&gt;TypeError: Failed to execute &#39;showNotification&#39; on &#39;ServiceWorkerRegistration&#39;: Notifications which set the renotify flag must specify a non-empty tag&lt;/code&gt; &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;silent&quot;&gt;Silent &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-notification-behaviour/#silent&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This option allows you to show a new notification but prevents the default behavior of vibration,
sound and turning on the device&#39;s display.&lt;/p&gt;
&lt;p&gt;This is ideal if your notifications don&#39;t require immediate attention from the user.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Silent Notification&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;silent&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Note: If you define both &lt;code&gt;silent&lt;/code&gt; and &lt;code&gt;renotify&lt;/code&gt;, &lt;code&gt;silent&lt;/code&gt; will take precedence.&lt;/p&gt;
&lt;h2 id=&quot;requires-interaction&quot;&gt;Requires interaction &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-notification-behaviour/#requires-interaction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Chrome on desktop will show notifications for a set time period before hiding them. Chrome on
Android doesn&#39;t have this behavior. Notifications are displayed until the user interacts with them.&lt;/p&gt;
&lt;p&gt;To force a notification to stay visible until the user interacts with it, add the &lt;code&gt;requireInteraction&lt;/code&gt;
option. This will show the notification until the user dismisses or clicks your notification.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Require Interaction Notification&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;requireInteraction&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;registration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showNotification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Use this option with consideration. Showing a notification and forcing the user to stop what
they are doing to dismiss your notification can be frustrating.&lt;/p&gt;
&lt;p&gt;In the next section, we are going to look at some of the common patterns used on the web for
managing notifications and performing actions such as opening pages when a notification is clicked.&lt;/p&gt;
&lt;h2 id=&quot;where-to-go-next&quot;&gt;Where to go next &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-notification-behaviour/#where-to-go-next&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-overview/&quot;&gt;Web Push Notification Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-how-push-works/&quot;&gt;How Push Works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-subscribing-a-user/&quot;&gt;Subscribing a User&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-permissions-ux/&quot;&gt;Permission UX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/sending-messages-with-web-push-libraries/&quot;&gt;Sending Messages with Web Push Libraries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-web-push-protocol/&quot;&gt;Web Push Protocol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-handling-messages/&quot;&gt;Handling Push Events&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-display-a-notification/&quot;&gt;Displaying a Notification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Notification Behavior&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-common-notification-patterns/&quot;&gt;Common Notification Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-faq/&quot;&gt;Push Notifications FAQ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-common-issues-and-reporting-bugs/&quot;&gt;Common Issues and Reporting Bugs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;code-labs&quot;&gt;Code labs &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/push-notifications-notification-behaviour/#code-labs&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-client-codelab/&quot;&gt;Build a push notification client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/push-notifications-server-codelab/&quot;&gt;Build a push notification server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Matt Gaunt</name>
    </author><author>
      <name>Alexey Rodionov</name>
    </author>
  </entry>
</feed>
