diff --git a/web/.eslintrc.js b/web/.eslintrc.js
deleted file mode 100644
index 04262dfd..00000000
--- a/web/.eslintrc.js
+++ /dev/null
@@ -1,34 +0,0 @@
-module.exports = {
-    parser: "babel-eslint",
-    env: {
-        browser: true,
-        commonjs: true,
-        es6: true,
-        node: true,
-        jest: true,
-    },
-    parserOptions: {
-        ecmaVersion: 2020,
-        ecmaFeatures: {
-            impliedStrict: true,
-            jsx: true,
-        },
-        sourceType: "module",
-    },
-    plugins: ["react", "react-hooks"],
-    extends: [
-        "eslint:recommended",
-        "plugin:react/recommended",
-        "plugin:react-hooks/recommended",
-    ],
-    settings: {
-        react: {
-            version: "detect",
-        },
-    },
-    rules: {
-        // You can do your customizations here...
-        // For example, if you don't want to use the prop-types package,
-        // you can turn off that recommended rule with: 'react/prop-types': ['off']
-    },
-};
diff --git a/web/package-lock.json b/web/package-lock.json
index 9c61203c..86f97a32 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -1,24 +1,19 @@
 {
-  "name": "create-react-app",
-  "version": "5.0.0",
+  "name": "ntfy",
+  "version": "1.0.0",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
-      "name": "create-react-app",
-      "version": "5.0.0",
+      "name": "ntfy",
+      "version": "1.0.0",
       "dependencies": {
-        "@babel/core": "^7.17.5",
-        "@babel/preset-env": "^7.16.11",
-        "@babel/preset-react": "^7.16.7",
-        "@emotion/react": "latest",
         "@emotion/styled": "latest",
         "@mui/icons-material": "^5.4.2",
         "@mui/material": "latest",
         "react": "latest",
         "react-dom": "latest",
-        "react-scripts": "^3.0.1",
-        "recharts": "^2.1.9"
+        "react-scripts": "^3.0.1"
       }
     },
     "node_modules/@ampproject/remapping": {
@@ -1837,6 +1832,7 @@
       "version": "11.8.1",
       "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.8.1.tgz",
       "integrity": "sha512-XGaie4nRxmtP1BZYBXqC5JGqMYF2KRKKI7vjqNvQxyRpekVAZhb6QqrElmZCAYXH1L90lAelADSVZC4PFsrJ8Q==",
+      "peer": true,
       "dependencies": {
         "@babel/runtime": "^7.13.10",
         "@emotion/babel-plugin": "^11.7.1",
@@ -2737,45 +2733,6 @@
         "@babel/types": "^7.3.0"
       }
     },
-    "node_modules/@types/d3-color": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-2.0.3.tgz",
-      "integrity": "sha512-+0EtEjBfKEDtH9Rk3u3kLOUXM5F+iZK+WvASPb0MhIZl8J8NUvGeZRwKCXl+P3HkYx5TdU4YtcibpqHkSR9n7w=="
-    },
-    "node_modules/@types/d3-interpolate": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-2.0.2.tgz",
-      "integrity": "sha512-lElyqlUfIPyWG/cD475vl6msPL4aMU7eJvx1//Q177L8mdXoVPFl1djIESF2FKnc0NyaHvQlJpWwKJYwAhUoCw==",
-      "dependencies": {
-        "@types/d3-color": "^2"
-      }
-    },
-    "node_modules/@types/d3-path": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-2.0.1.tgz",
-      "integrity": "sha512-6K8LaFlztlhZO7mwsZg7ClRsdLg3FJRzIIi6SZXDWmmSJc2x8dd2VkESbLXdk3p8cuvz71f36S0y8Zv2AxqvQw=="
-    },
-    "node_modules/@types/d3-scale": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-3.3.2.tgz",
-      "integrity": "sha512-gGqr7x1ost9px3FvIfUMi5XA/F/yAf4UkUDtdQhpH92XCT0Oa7zkkRzY61gPVJq+DxpHn/btouw5ohWkbBsCzQ==",
-      "dependencies": {
-        "@types/d3-time": "^2"
-      }
-    },
-    "node_modules/@types/d3-shape": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-2.1.3.tgz",
-      "integrity": "sha512-HAhCel3wP93kh4/rq+7atLdybcESZ5bRHDEZUojClyZWsRuEMo3A52NGYJSh48SxfxEU6RZIVbZL2YFZ2OAlzQ==",
-      "dependencies": {
-        "@types/d3-path": "^2"
-      }
-    },
-    "node_modules/@types/d3-time": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-2.1.1.tgz",
-      "integrity": "sha512-9MVYlmIgmRR31C5b4FVSWtuMmBHh2mOWQYfl7XAYOa8dsnb7iEmUmRSWSFgXFtkjxO65d7hTUHQC+RhR/9IWFg=="
-    },
     "node_modules/@types/eslint-visitor-keys": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
@@ -2868,11 +2825,6 @@
         "@types/react": "*"
       }
     },
-    "node_modules/@types/resize-observer-browser": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/@types/resize-observer-browser/-/resize-observer-browser-0.1.7.tgz",
-      "integrity": "sha512-G9eN0Sn0ii9PWQ3Vl72jDPgeJwRWhv2Qk/nQkJuWmRmOB4HX3/BhD5SE1dZs/hzPZL/WKnvF0RHdTSG54QJFyg=="
-    },
     "node_modules/@types/scheduler": {
       "version": "0.16.2",
       "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
@@ -5000,11 +4952,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/classnames": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
-      "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA=="
-    },
     "node_modules/clean-css": {
       "version": "4.2.4",
       "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz",
@@ -5694,11 +5641,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/css-unit-converter": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz",
-      "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA=="
-    },
     "node_modules/css-what": {
       "version": "5.1.0",
       "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz",
@@ -5937,73 +5879,6 @@
         "type": "^1.0.1"
       }
     },
-    "node_modules/d3-array": {
-      "version": "2.12.1",
-      "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
-      "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
-      "dependencies": {
-        "internmap": "^1.0.0"
-      }
-    },
-    "node_modules/d3-color": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz",
-      "integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ=="
-    },
-    "node_modules/d3-format": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz",
-      "integrity": "sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA=="
-    },
-    "node_modules/d3-interpolate": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz",
-      "integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==",
-      "dependencies": {
-        "d3-color": "1 - 2"
-      }
-    },
-    "node_modules/d3-path": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-2.0.0.tgz",
-      "integrity": "sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA=="
-    },
-    "node_modules/d3-scale": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.3.0.tgz",
-      "integrity": "sha512-1JGp44NQCt5d1g+Yy+GeOnZP7xHo0ii8zsQp6PGzd+C1/dl0KGsp9A7Mxwp+1D1o4unbTTxVdU/ZOIEBoeZPbQ==",
-      "dependencies": {
-        "d3-array": "^2.3.0",
-        "d3-format": "1 - 2",
-        "d3-interpolate": "1.2.0 - 2",
-        "d3-time": "^2.1.1",
-        "d3-time-format": "2 - 3"
-      }
-    },
-    "node_modules/d3-shape": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-2.1.0.tgz",
-      "integrity": "sha512-PnjUqfM2PpskbSLTJvAzp2Wv4CZsnAgTfcVRTwW03QR3MkXF8Uo7B1y/lWkAsmbKwuecto++4NlsYcvYpXpTHA==",
-      "dependencies": {
-        "d3-path": "1 - 2"
-      }
-    },
-    "node_modules/d3-time": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.1.1.tgz",
-      "integrity": "sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==",
-      "dependencies": {
-        "d3-array": "2"
-      }
-    },
-    "node_modules/d3-time-format": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz",
-      "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==",
-      "dependencies": {
-        "d3-time": "1 - 2"
-      }
-    },
     "node_modules/damerau-levenshtein": {
       "version": "1.0.8",
       "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
@@ -6064,11 +5939,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/decimal.js-light": {
-      "version": "2.5.1",
-      "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
-      "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="
-    },
     "node_modules/decode-uri-component": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
@@ -7584,11 +7454,6 @@
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
     },
-    "node_modules/fast-equals": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-2.0.4.tgz",
-      "integrity": "sha512-caj/ZmjHljPrZtbzJ3kfH5ia/k4mTJe/qSiXAGzxZWRZgsgDV0cvNaQULqUX8t0/JVlzzEdYOwCN5DmzTxoD4w=="
-    },
     "node_modules/fast-glob": {
       "version": "2.2.7",
       "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz",
@@ -8953,11 +8818,6 @@
         "node": ">= 0.4"
       }
     },
-    "node_modules/internmap": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz",
-      "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="
-    },
     "node_modules/invariant": {
       "version": "2.2.4",
       "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
@@ -13813,25 +13673,6 @@
       "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
       "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
     },
-    "node_modules/react-lifecycles-compat": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
-      "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
-    },
-    "node_modules/react-resize-detector": {
-      "version": "6.7.8",
-      "resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-6.7.8.tgz",
-      "integrity": "sha512-0FaEcUBAbn+pq3PT5a9hHRebUfuS1SRLGLpIw8LydU7zX429I6XJgKerKAMPsJH0qWAl6o5bVKNqFJqr6tGPYw==",
-      "dependencies": {
-        "@types/resize-observer-browser": "^0.1.6",
-        "lodash": "^4.17.21",
-        "resize-observer-polyfill": "^1.5.1"
-      },
-      "peerDependencies": {
-        "react": "^16.0.0 || ^17.0.0",
-        "react-dom": "^16.0.0 || ^17.0.0"
-      }
-    },
     "node_modules/react-scripts": {
       "version": "3.4.4",
       "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.4.4.tgz",
@@ -13957,44 +13798,6 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
-    "node_modules/react-smooth": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-2.0.0.tgz",
-      "integrity": "sha512-wK4dBBR6P21otowgMT9toZk+GngMplGS1O5gk+2WSiHEXIrQgDvhR5IIlT74Vtu//qpTcipkgo21dD7a7AUNxw==",
-      "dependencies": {
-        "fast-equals": "^2.0.0",
-        "raf": "^3.4.0",
-        "react-transition-group": "2.9.0"
-      },
-      "peerDependencies": {
-        "prop-types": "^15.6.0",
-        "react": "^15.0.0 || ^16.0.0 || ^17.0.0",
-        "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0"
-      }
-    },
-    "node_modules/react-smooth/node_modules/dom-helpers": {
-      "version": "3.4.0",
-      "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
-      "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==",
-      "dependencies": {
-        "@babel/runtime": "^7.1.2"
-      }
-    },
-    "node_modules/react-smooth/node_modules/react-transition-group": {
-      "version": "2.9.0",
-      "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
-      "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==",
-      "dependencies": {
-        "dom-helpers": "^3.4.0",
-        "loose-envify": "^1.4.0",
-        "prop-types": "^15.6.2",
-        "react-lifecycles-compat": "^3.0.4"
-      },
-      "peerDependencies": {
-        "react": ">=15.0.0",
-        "react-dom": ">=15.0.0"
-      }
-    },
     "node_modules/react-transition-group": {
       "version": "4.4.2",
       "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz",
@@ -14143,47 +13946,6 @@
         "node": ">=4"
       }
     },
-    "node_modules/recharts": {
-      "version": "2.1.9",
-      "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.1.9.tgz",
-      "integrity": "sha512-VozH5uznUvGqD7n224FGj7cmMAenlS0HPCs+7r2HeeHiQK6un6z0CTZfWVAB860xbcr4m+BN/EGMPZmYWd34Rg==",
-      "dependencies": {
-        "@types/d3-interpolate": "^2.0.0",
-        "@types/d3-scale": "^3.0.0",
-        "@types/d3-shape": "^2.0.0",
-        "classnames": "^2.2.5",
-        "d3-interpolate": "^2.0.0",
-        "d3-scale": "^3.0.0",
-        "d3-shape": "^2.0.0",
-        "eventemitter3": "^4.0.1",
-        "lodash": "^4.17.19",
-        "react-is": "^16.10.2",
-        "react-resize-detector": "^6.6.3",
-        "react-smooth": "^2.0.0",
-        "recharts-scale": "^0.4.4",
-        "reduce-css-calc": "^2.1.8"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "peerDependencies": {
-        "react": "^16.0.0 || ^17.0.0",
-        "react-dom": "^16.0.0 || ^17.0.0"
-      }
-    },
-    "node_modules/recharts-scale": {
-      "version": "0.4.5",
-      "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz",
-      "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==",
-      "dependencies": {
-        "decimal.js-light": "^2.4.1"
-      }
-    },
-    "node_modules/recharts/node_modules/react-is": {
-      "version": "16.13.1",
-      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
-      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
-    },
     "node_modules/recursive-readdir": {
       "version": "2.2.2",
       "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz",
@@ -14206,20 +13968,6 @@
         "node": "*"
       }
     },
-    "node_modules/reduce-css-calc": {
-      "version": "2.1.8",
-      "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz",
-      "integrity": "sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg==",
-      "dependencies": {
-        "css-unit-converter": "^1.1.1",
-        "postcss-value-parser": "^3.3.0"
-      }
-    },
-    "node_modules/reduce-css-calc/node_modules/postcss-value-parser": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
-      "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="
-    },
     "node_modules/regenerate": {
       "version": "1.4.2",
       "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@@ -14472,11 +14220,6 @@
       "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
       "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
     },
-    "node_modules/resize-observer-polyfill": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
-      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
-    },
     "node_modules/resolve": {
       "version": "1.22.0",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
@@ -19230,6 +18973,7 @@
       "version": "11.8.1",
       "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.8.1.tgz",
       "integrity": "sha512-XGaie4nRxmtP1BZYBXqC5JGqMYF2KRKKI7vjqNvQxyRpekVAZhb6QqrElmZCAYXH1L90lAelADSVZC4PFsrJ8Q==",
+      "peer": true,
       "requires": {
         "@babel/runtime": "^7.13.10",
         "@emotion/babel-plugin": "^11.7.1",
@@ -19855,45 +19599,6 @@
         "@babel/types": "^7.3.0"
       }
     },
-    "@types/d3-color": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-2.0.3.tgz",
-      "integrity": "sha512-+0EtEjBfKEDtH9Rk3u3kLOUXM5F+iZK+WvASPb0MhIZl8J8NUvGeZRwKCXl+P3HkYx5TdU4YtcibpqHkSR9n7w=="
-    },
-    "@types/d3-interpolate": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-2.0.2.tgz",
-      "integrity": "sha512-lElyqlUfIPyWG/cD475vl6msPL4aMU7eJvx1//Q177L8mdXoVPFl1djIESF2FKnc0NyaHvQlJpWwKJYwAhUoCw==",
-      "requires": {
-        "@types/d3-color": "^2"
-      }
-    },
-    "@types/d3-path": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-2.0.1.tgz",
-      "integrity": "sha512-6K8LaFlztlhZO7mwsZg7ClRsdLg3FJRzIIi6SZXDWmmSJc2x8dd2VkESbLXdk3p8cuvz71f36S0y8Zv2AxqvQw=="
-    },
-    "@types/d3-scale": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-3.3.2.tgz",
-      "integrity": "sha512-gGqr7x1ost9px3FvIfUMi5XA/F/yAf4UkUDtdQhpH92XCT0Oa7zkkRzY61gPVJq+DxpHn/btouw5ohWkbBsCzQ==",
-      "requires": {
-        "@types/d3-time": "^2"
-      }
-    },
-    "@types/d3-shape": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-2.1.3.tgz",
-      "integrity": "sha512-HAhCel3wP93kh4/rq+7atLdybcESZ5bRHDEZUojClyZWsRuEMo3A52NGYJSh48SxfxEU6RZIVbZL2YFZ2OAlzQ==",
-      "requires": {
-        "@types/d3-path": "^2"
-      }
-    },
-    "@types/d3-time": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-2.1.1.tgz",
-      "integrity": "sha512-9MVYlmIgmRR31C5b4FVSWtuMmBHh2mOWQYfl7XAYOa8dsnb7iEmUmRSWSFgXFtkjxO65d7hTUHQC+RhR/9IWFg=="
-    },
     "@types/eslint-visitor-keys": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
@@ -19986,11 +19691,6 @@
         "@types/react": "*"
       }
     },
-    "@types/resize-observer-browser": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/@types/resize-observer-browser/-/resize-observer-browser-0.1.7.tgz",
-      "integrity": "sha512-G9eN0Sn0ii9PWQ3Vl72jDPgeJwRWhv2Qk/nQkJuWmRmOB4HX3/BhD5SE1dZs/hzPZL/WKnvF0RHdTSG54QJFyg=="
-    },
     "@types/scheduler": {
       "version": "0.16.2",
       "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
@@ -21702,11 +21402,6 @@
         }
       }
     },
-    "classnames": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
-      "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA=="
-    },
     "clean-css": {
       "version": "4.2.4",
       "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz",
@@ -22256,11 +21951,6 @@
         }
       }
     },
-    "css-unit-converter": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz",
-      "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA=="
-    },
     "css-what": {
       "version": "5.1.0",
       "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz",
@@ -22444,73 +22134,6 @@
         "type": "^1.0.1"
       }
     },
-    "d3-array": {
-      "version": "2.12.1",
-      "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
-      "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
-      "requires": {
-        "internmap": "^1.0.0"
-      }
-    },
-    "d3-color": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz",
-      "integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ=="
-    },
-    "d3-format": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz",
-      "integrity": "sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA=="
-    },
-    "d3-interpolate": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz",
-      "integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==",
-      "requires": {
-        "d3-color": "1 - 2"
-      }
-    },
-    "d3-path": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-2.0.0.tgz",
-      "integrity": "sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA=="
-    },
-    "d3-scale": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.3.0.tgz",
-      "integrity": "sha512-1JGp44NQCt5d1g+Yy+GeOnZP7xHo0ii8zsQp6PGzd+C1/dl0KGsp9A7Mxwp+1D1o4unbTTxVdU/ZOIEBoeZPbQ==",
-      "requires": {
-        "d3-array": "^2.3.0",
-        "d3-format": "1 - 2",
-        "d3-interpolate": "1.2.0 - 2",
-        "d3-time": "^2.1.1",
-        "d3-time-format": "2 - 3"
-      }
-    },
-    "d3-shape": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-2.1.0.tgz",
-      "integrity": "sha512-PnjUqfM2PpskbSLTJvAzp2Wv4CZsnAgTfcVRTwW03QR3MkXF8Uo7B1y/lWkAsmbKwuecto++4NlsYcvYpXpTHA==",
-      "requires": {
-        "d3-path": "1 - 2"
-      }
-    },
-    "d3-time": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.1.1.tgz",
-      "integrity": "sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==",
-      "requires": {
-        "d3-array": "2"
-      }
-    },
-    "d3-time-format": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz",
-      "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==",
-      "requires": {
-        "d3-time": "1 - 2"
-      }
-    },
     "damerau-levenshtein": {
       "version": "1.0.8",
       "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
@@ -22559,11 +22182,6 @@
       "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
       "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
     },
-    "decimal.js-light": {
-      "version": "2.5.1",
-      "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
-      "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="
-    },
     "decode-uri-component": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
@@ -23759,11 +23377,6 @@
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
     },
-    "fast-equals": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-2.0.4.tgz",
-      "integrity": "sha512-caj/ZmjHljPrZtbzJ3kfH5ia/k4mTJe/qSiXAGzxZWRZgsgDV0cvNaQULqUX8t0/JVlzzEdYOwCN5DmzTxoD4w=="
-    },
     "fast-glob": {
       "version": "2.2.7",
       "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz",
@@ -24805,11 +24418,6 @@
         "side-channel": "^1.0.4"
       }
     },
-    "internmap": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz",
-      "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="
-    },
     "invariant": {
       "version": "2.2.4",
       "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
@@ -28682,21 +28290,6 @@
       "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
       "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
     },
-    "react-lifecycles-compat": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
-      "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
-    },
-    "react-resize-detector": {
-      "version": "6.7.8",
-      "resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-6.7.8.tgz",
-      "integrity": "sha512-0FaEcUBAbn+pq3PT5a9hHRebUfuS1SRLGLpIw8LydU7zX429I6XJgKerKAMPsJH0qWAl6o5bVKNqFJqr6tGPYw==",
-      "requires": {
-        "@types/resize-observer-browser": "^0.1.6",
-        "lodash": "^4.17.21",
-        "resize-observer-polyfill": "^1.5.1"
-      }
-    },
     "react-scripts": {
       "version": "3.4.4",
       "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.4.4.tgz",
@@ -28797,37 +28390,6 @@
         }
       }
     },
-    "react-smooth": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-2.0.0.tgz",
-      "integrity": "sha512-wK4dBBR6P21otowgMT9toZk+GngMplGS1O5gk+2WSiHEXIrQgDvhR5IIlT74Vtu//qpTcipkgo21dD7a7AUNxw==",
-      "requires": {
-        "fast-equals": "^2.0.0",
-        "raf": "^3.4.0",
-        "react-transition-group": "2.9.0"
-      },
-      "dependencies": {
-        "dom-helpers": {
-          "version": "3.4.0",
-          "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
-          "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==",
-          "requires": {
-            "@babel/runtime": "^7.1.2"
-          }
-        },
-        "react-transition-group": {
-          "version": "2.9.0",
-          "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
-          "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==",
-          "requires": {
-            "dom-helpers": "^3.4.0",
-            "loose-envify": "^1.4.0",
-            "prop-types": "^15.6.2",
-            "react-lifecycles-compat": "^3.0.4"
-          }
-        }
-      }
-    },
     "react-transition-group": {
       "version": "4.4.2",
       "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz",
@@ -28943,42 +28505,6 @@
         "util.promisify": "^1.0.0"
       }
     },
-    "recharts": {
-      "version": "2.1.9",
-      "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.1.9.tgz",
-      "integrity": "sha512-VozH5uznUvGqD7n224FGj7cmMAenlS0HPCs+7r2HeeHiQK6un6z0CTZfWVAB860xbcr4m+BN/EGMPZmYWd34Rg==",
-      "requires": {
-        "@types/d3-interpolate": "^2.0.0",
-        "@types/d3-scale": "^3.0.0",
-        "@types/d3-shape": "^2.0.0",
-        "classnames": "^2.2.5",
-        "d3-interpolate": "^2.0.0",
-        "d3-scale": "^3.0.0",
-        "d3-shape": "^2.0.0",
-        "eventemitter3": "^4.0.1",
-        "lodash": "^4.17.19",
-        "react-is": "^16.10.2",
-        "react-resize-detector": "^6.6.3",
-        "react-smooth": "^2.0.0",
-        "recharts-scale": "^0.4.4",
-        "reduce-css-calc": "^2.1.8"
-      },
-      "dependencies": {
-        "react-is": {
-          "version": "16.13.1",
-          "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
-          "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
-        }
-      }
-    },
-    "recharts-scale": {
-      "version": "0.4.5",
-      "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz",
-      "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==",
-      "requires": {
-        "decimal.js-light": "^2.4.1"
-      }
-    },
     "recursive-readdir": {
       "version": "2.2.2",
       "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz",
@@ -28997,22 +28523,6 @@
         }
       }
     },
-    "reduce-css-calc": {
-      "version": "2.1.8",
-      "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz",
-      "integrity": "sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg==",
-      "requires": {
-        "css-unit-converter": "^1.1.1",
-        "postcss-value-parser": "^3.3.0"
-      },
-      "dependencies": {
-        "postcss-value-parser": {
-          "version": "3.3.1",
-          "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
-          "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="
-        }
-      }
-    },
     "regenerate": {
       "version": "1.4.2",
       "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@@ -29207,11 +28717,6 @@
       "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
       "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
     },
-    "resize-observer-polyfill": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
-      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
-    },
     "resolve": {
       "version": "1.22.0",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
diff --git a/web/package.json b/web/package.json
index 0399dafe..a4279efa 100644
--- a/web/package.json
+++ b/web/package.json
@@ -1,6 +1,6 @@
 {
-  "name": "create-react-app",
-  "version": "5.0.0",
+  "name": "ntfy",
+  "version": "1.0.0",
   "private": true,
   "scripts": {
     "start": "react-scripts start",
@@ -9,17 +9,12 @@
     "eject": "react-scripts eject"
   },
   "dependencies": {
-    "@babel/core": "^7.17.5",
-    "@babel/preset-env": "^7.16.11",
-    "@babel/preset-react": "^7.16.7",
-    "@emotion/react": "latest",
-    "@emotion/styled": "latest",
-    "@mui/icons-material": "^5.4.2",
-    "@mui/material": "latest",
     "react": "latest",
     "react-dom": "latest",
     "react-scripts": "^3.0.1",
-    "recharts": "^2.1.9"
+    "@mui/icons-material": "^5.4.2",
+    "@mui/material": "latest",
+    "@emotion/styled": "latest"
   },
   "browserslist": {
     "production": [
diff --git a/web/public/index.html b/web/public/index.html
index 1ffa44f4..5457d960 100644
--- a/web/public/index.html
+++ b/web/public/index.html
@@ -20,21 +20,10 @@
       Learn how to configure a non-root public URL by running `npm run build`.
     -->
     <title>My page</title>
-    <!-- Fonts to support Material Design -->
     <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
   </head>
   <body>
     <noscript>You need to enable JavaScript to run this app.</noscript>
     <div id="root"></div>
-    <!--
-      This HTML file is a template.
-      If you open it directly in the browser, you will see an empty page.
-
-      You can add webfonts, meta tags, or analytics to this file.
-      The build step will place the bundled scripts into the <body> tag.
-
-      To begin the development, run `npm start` or `yarn start`.
-      To create a production bundle, use `npm run build` or `yarn build`.
-    -->
   </body>
 </html>
diff --git a/web/src/components/App.js b/web/src/components/App.js
index 3e93b6aa..16f3484c 100644
--- a/web/src/components/App.js
+++ b/web/src/components/App.js
@@ -105,21 +105,31 @@ const App = () => {
     const [subscriptions, setSubscriptions] = useState(LocalStorage.getSubscriptions());
     const [connections, setConnections] = useState({});
     const [selectedSubscription, setSelectedSubscription] = useState(null);
-    const [addDialogOpen, setAddDialogOpen] = useState(false);
+    const [subscribeDialogOpen, setSubscribeDialogOpen] = useState(false);
     const subscriptionChanged = (subscription) => {
         setSubscriptions(prev => ({...prev, [subscription.id]: subscription})); // Fake-replace
     };
-    const handleAddSubmit = (subscription) => {
+    const handleSubscribeSubmit = (subscription) => {
         const connection = new WsConnection(subscription, subscriptionChanged);
-        setAddDialogOpen(false);
+        setSubscribeDialogOpen(false);
         setSubscriptions(prev => ({...prev, [subscription.id]: subscription}));
         setConnections(prev => ({...prev, [subscription.id]: connection}));
         connection.start();
     };
-    const handleAddCancel = () => {
+    const handleSubscribeCancel = () => {
         console.log(`Cancel clicked`);
-        setAddDialogOpen(false);
-    }
+        setSubscribeDialogOpen(false);
+    };
+    const handleUnsubscribe = (subscription) => {
+        setSubscriptions(prev => {
+            const newSubscriptions = {...prev};
+            delete newSubscriptions[subscription.id];
+            if (newSubscriptions.length > 0) {
+                setSelectedSubscription(newSubscriptions[0]);
+            }
+            return newSubscriptions;
+        });
+    };
     const handleSubscriptionClick = (subscriptionId) => {
         console.log(`Selected subscription ${subscriptionId}`);
         setSelectedSubscription(subscriptions[subscriptionId]);
@@ -176,7 +186,10 @@ const App = () => {
                         >
                             {(selectedSubscription != null) ? selectedSubscription.shortUrl() : "ntfy.sh"}
                         </Typography>
-                        <DetailSettingsIcon/>
+                        <DetailSettingsIcon
+                            subscription={selectedSubscription}
+                            onUnsubscribe={handleUnsubscribe}
+                        />
                     </Toolbar>
                 </AppBar>
                 <Drawer variant="permanent" open={drawerOpen}>
@@ -206,7 +219,7 @@ const App = () => {
                             </ListItemIcon>
                             <ListItemText primary="Settings" />
                         </ListItemButton>
-                        <ListItemButton onClick={() => setAddDialogOpen(true)}>
+                        <ListItemButton onClick={() => setSubscribeDialogOpen(true)}>
                             <ListItemIcon>
                                 <AddIcon />
                             </ListItemIcon>
@@ -231,9 +244,9 @@ const App = () => {
                 </Box>
             </Box>
             <AddDialog
-                open={addDialogOpen}
-                onCancel={handleAddCancel}
-                onSubmit={handleAddSubmit}
+                open={subscribeDialogOpen}
+                onCancel={handleSubscribeCancel}
+                onSubmit={handleSubscribeSubmit}
             />
         </ThemeProvider>
     );
diff --git a/web/src/components/DetailSettingsIcon.js b/web/src/components/DetailSettingsIcon.js
index 077e3797..e2c067ba 100644
--- a/web/src/components/DetailSettingsIcon.js
+++ b/web/src/components/DetailSettingsIcon.js
@@ -10,7 +10,7 @@ import IconButton from "@mui/material/IconButton";
 import MoreVertIcon from "@mui/icons-material/MoreVert";
 
 // Originally from https://mui.com/components/menus/#MenuListComposition.js
-const DetailSettingsIcon = () => {
+const DetailSettingsIcon = (props) => {
     const [open, setOpen] = useState(false);
     const anchorRef = useRef(null);
 
@@ -23,6 +23,7 @@ const DetailSettingsIcon = () => {
             return;
         }
         setOpen(false);
+        props.onUnsubscribe(props.subscription);
     };
 
     function handleListKeyDown(event) {
diff --git a/web/src/react-app-env.d.ts b/web/src/react-app-env.d.ts
deleted file mode 100644
index 6431bc5f..00000000
--- a/web/src/react-app-env.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-/// <reference types="react-scripts" />
diff --git a/web/tsconfig.json b/web/tsconfig.json
deleted file mode 100644
index 0980b23f..00000000
--- a/web/tsconfig.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-  "compilerOptions": {
-    "target": "es5",
-    "lib": [
-      "dom",
-      "dom.iterable",
-      "esnext"
-    ],
-    "allowJs": true,
-    "skipLibCheck": true,
-    "esModuleInterop": true,
-    "allowSyntheticDefaultImports": true,
-    "strict": true,
-    "forceConsistentCasingInFileNames": true,
-    "module": "esnext",
-    "moduleResolution": "node",
-    "resolveJsonModule": true,
-    "isolatedModules": true,
-    "noEmit": true,
-    "jsx": "preserve"
-  },
-  "include": [
-    "src"
-  ]
-}