return {"status": "success", "subid": row["subid"]}
 
+@bp.post("/update-subscription/<int:subid>")
+@auth.requires_login
+def update_subscription(subid):
+    if not request.json:
+        # Request must contain valid subscription JSON
+        abort(400)
+
+    row = db.query(
+            """
+            UPDATE users_push_subscriptions
+            SET subscription = ?
+            WHERE subid = ? AND userid = ?
+            RETURNING subid
+            """,
+            [json.dumps(request.json), subid, g.userid], expect_one=True)
+    db.commit()
+
+    current_app.logger.info(f"{g.username} updated push subscription")
+
+    return {"status": "success", "subid": row["subid"]}
+
 @bp.get("/settings")
 @auth.requires_login
 def get_settings():
 
     }
 });
 
+self.addEventListener("pushsubscriptionchanged", (event) => {
+    console.log("Subscription expired");
+    event.waitUntil(
+        self.registration.pushManager.subscribe({ userVisibleOnly: true })
+        .then((subscription) => {
+            console.log("Register new subscription");
+            const subid = window.localStorage.getItem("subid");
+            return fetch(`/push-notifications/update-subscription/${subid}`, {
+                method: "post",
+                headers: {"Content-Type": "application/json"},
+                body: JSON.stringify(subscription)
+            });
+        });
+    );
+});
+
 // TODO: handle notificationclick event