# Request must contain valid subscription JSON
         abort(400)
 
-    row = db.query(
-            """
-            INSERT INTO users_push_subscriptions (userid, subscription, settings)
-            VALUES (?, ?, ?)
-            RETURNING subid
-            """,
-            [g.userid, json.dumps(request.json), 0], expect_one=True)
+    subid = request.args.get("subid", None)
+    existing_sub = None
+    if subid:
+        existing_sub = db.query(
+                "SELECT * FROM users_push_subscriptions WHERE subid = ? AND userid = ?",
+                [subid, g.userid])
+
+    if existing_sub:
+        row = db.query(
+                """
+                UPDATE users_push_subscriptions
+                SET userid = ?, subscription = ?
+                WHERE subid = ? AND userid = ?
+                RETURNING subid
+                """,
+                [g.userid, json.dumps(request.json), subid, g.userid], expect_one=True)
+    else:
+        row = db.query(
+                """
+                INSERT INTO users_push_subscriptions (userid, subscription, settings)
+                VALUES (?, ?, ?)
+                RETURNING subid
+                """,
+                [g.userid, json.dumps(request.json), 0], expect_one=True)
     db.commit()
 
     current_app.logger.info(f"{g.username} registered push subscription")
 
     return {"status": "success", "subid": row["subid"]}
 
+@bp.get("/vapid-public-key")
+def vapid_public_key():
+    try:
+        with open(datadir.get_vapid_public_key_path(), "r") as keyfile:
+            key = keyfile.read().strip()
+        return {"status": "ok", "public_key": key}
+    except OSError:
+        return {"status": "error"}
+
 @bp.get("/settings")
 @auth.requires_login
 def get_settings():
 
     });
 }
 
+async function periodicPushSync() {
+    console.log("sync");
+    if (!("serviceWorker" in navigator)) {
+        return;  // No service woker available
+    }
+    const subid = window.localStorage.getItem("subid");
+    console.log(subid);
+    if (subid) {
+        await syncPushSubscription();
+    }
+}
+
+async function syncPushSubscription() {
+    const registration = await navigator.serviceWorker.getRegistration();
+    let subscription = await registration.pushManager.getSubscription();
+    if (!subscription)
+    {
+        // Subscribe via browser's push service
+        const data = await fetch("/push-notifications/vapid-public-key").then((r) => { return r.json() });
+        const vapid_public_key = data.public_key;
+        const options = {userVisibleOnly: true, applicationServerKey: vapid_public_key};
+        subscription = await registration.pushManager.subscribe(options);
+        console.log(JSON.stringify(subscription));
+    }
+
+    // Register (or update) subscription with LSP server
+    const subid = window.localStorage.getItem("subid");
+    const params = subid ? `?subid=${subid}` : "";
+    const response = await fetch(
+        `/push-notifications/subscribe${params}`, {
+            method: "post",
+            headers: {"Content-Type": "application/json"},
+            body: JSON.stringify(subscription)
+        }
+    );
+
+    const rspJson = await response.json();
+    console.log("Subscription ID:", rspJson.subid);
+    window.localStorage.setItem("subid", rspJson.subid);
+}
+
+periodicPushSync();
+setInterval(periodicPushSync, 10000);
+
 
     if (permission === "granted") {
         // Subscribe to push notifications (if we don't already have an active subscription)
         try {
-            const registration = await navigator.serviceWorker.getRegistration();
-            const existingSubscription = await registration.pushManager.getSubscription();
-            if (!existingSubscription || !window.localStorage.getItem("subid"))
-            {
-                // Subscribe via browser's push service
-                const vapid_public_key = "{{ vapid_public_key }}";
-                const options = {userVisibleOnly: true, applicationServerKey: vapid_public_key};
-                const subscription = await registration.pushManager.subscribe(options);
-                console.log(JSON.stringify(subscription));
-
-                // Register subscription with LSP server
-                const response = await fetch(
-                    "/push-notifications/subscribe", {
-                        method: "post",
-                        headers: {"Content-Type": "application/json"},
-                        body: JSON.stringify(subscription)
-                    }
-                );
-
-                const rspJson = await response.json();
-                console.log("Subscription ID:", rspJson.subid);
-                window.localStorage.setItem("subid", rspJson.subid);
-            }
+            await syncPushSubscription();
         }
         catch (err) {
             console.log("Error subscribing to push notifications:", err);