diff --git a/src/hub.js b/src/hub.js
index 50dcd8aa9cd06d74323b163e5182c94b330456fc..8470ce8916d149bf384088ea90a2c4211dc4c005 100644
--- a/src/hub.js
+++ b/src/hub.js
@@ -311,8 +311,11 @@ document.addEventListener("DOMContentLoaded", async () => {
   console.log(`Hub ID: ${hubId}`);
 
   const subscriptions = new Subscriptions(hubId);
-  navigator.serviceWorker.register("/hub.service.js");
-  navigator.serviceWorker.ready.then(registration => subscriptions.setRegistration(registration));
+
+  if (navigator.serviceWorker) {
+    navigator.serviceWorker.register("/hub.service.js");
+    navigator.serviceWorker.ready.then(registration => subscriptions.setRegistration(registration));
+  }
 
   const scene = document.querySelector("a-scene");
   const hubChannel = new HubChannel(store);
diff --git a/src/hub.service.js b/src/hub.service.js
index d039f7290f0122d7019e76d1f3656097f317a499..6208f8620ad1e989cb70f823a3c31181071fc333 100644
--- a/src/hub.service.js
+++ b/src/hub.service.js
@@ -1,10 +1,39 @@
 self.addEventListener("install", function(e) {
-  e.waitUntil(self.skipWaiting());
+  return e.waitUntil(self.skipWaiting());
 });
+
 self.addEventListener("activate", function(e) {
-  e.waitUntil(self.clients.claim());
+  return e.waitUntil(self.clients.claim());
+});
+
+self.addEventListener("push", function(e) {
+  const payload = JSON.parse(e.data.text());
+
+  return e.waitUntil(
+    self.registration.showNotification("Hubs by Mozilla", {
+      body: "Someone has joined " + payload.hub_name,
+      image: payload.image,
+      icon: "/favicon.ico",
+      badge: "/favicon.ico",
+      tag: payload.hub_id,
+      data: { hub_url: payload.hub_url }
+    })
+  );
 });
 
-self.addEventListener("push", function() {});
+self.addEventListener("notificationclick", function(e) {
+  e.notification.close();
+
+  e.waitUntil(
+    self.clients.matchAll({ type: "window" }).then(function(clientList) {
+      for (let i = 0; i < clientList.length; i++) {
+        const client = clientList[i];
+        if (client.url.indexOf(e.notification.data.hub_url) >= 0 && "focus" in client) return client.focus();
+      }
 
-self.addEventListener("notificationclick", function() {});
+      if (self.clients.openWindow) {
+        return self.clients.openWindow(e.notification.data.hub_url);
+      }
+    })
+  );
+});
diff --git a/src/react-components/ui-root.js b/src/react-components/ui-root.js
index 0c85be53d51831bc5f8a4df7630b7710230c9fbf..57de5be3fc179e75074af0e2f98d84c88b93fb89 100644
--- a/src/react-components/ui-root.js
+++ b/src/react-components/ui-root.js
@@ -687,7 +687,7 @@ class UIRoot extends Component {
   };
 
   renderEntryStartPanel = () => {
-    const hasPush = "PushManager" in window;
+    const hasPush = navigator.serviceWorker && "PushManager" in window;
 
     return (
       <div className={entryStyles.entryPanel}>