diff --git a/cmd/serve.go b/cmd/serve.go
index c281f3ec..b28bf46e 100644
--- a/cmd/serve.go
+++ b/cmd/serve.go
@@ -152,8 +152,8 @@ func execServe(c *cli.Context) error {
 		return errors.New("if smtp-server-listen is set, smtp-server-domain must also be set")
 	} else if attachmentCacheDir != "" && baseURL == "" {
 		return errors.New("if attachment-cache-dir is set, base-url must also be set")
-	} else if baseURL != "" && !strings.HasPrefix(baseURL, "http://") && !strings.HasPrefix(baseURL, "https://") {
-		return errors.New("if set, base-url must start with http:// or https://")
+	} else if baseURL != "" && !strings.HasPrefix(baseURL, "http://") && !strings.HasPrefix(baseURL, "https://") && strings.HasSuffix(baseURL, "/") {
+		return errors.New("if set, base-url must start with http:// or https://, and must not end with a slash (/)")
 	} else if !util.InStringList([]string{"read-write", "read-only", "write-only", "deny-all"}, authDefaultAccess) {
 		return errors.New("if set, auth-default-access must start set to 'read-write', 'read-only', 'write-only' or 'deny-all'")
 	} else if !util.InStringList([]string{"app", "home", "disable"}, webRoot) {
diff --git a/docs/examples.md b/docs/examples.md
index 6183b670..fc4bc1a2 100644
--- a/docs/examples.md
+++ b/docs/examples.md
@@ -9,7 +9,9 @@ those out, too.
     [create a pull request](https://github.com/binwiederhier/ntfy/pulls), and I'll happily include it. Also note, that
     I cannot guarantee that all of these examples are functional. Many of them I have not tried myself.
 
-## A long process is done: backups, copying data, pipelines, ...
+## Cronjobs
+ntfy is perfect for any kind of cronjobs or just when long processes are done (backups, pipelines, rsync copy commands, ...).
+
 I started adding notifications pretty much all of my scripts. Typically, I just chain the <tt>curl</tt> call
 directly to the command I'm running. The following example will either send <i>Laptop backup succeeded</i>
 or ⚠️ <i>Laptop backup failed</i> directly to my phone:
@@ -21,6 +23,15 @@ rsync -a root@laptop /backups/laptop \
   || curl -H tags:warning -H prio:high -d "Laptop backup failed" ntfy.sh/backups
 ```
 
+Here's one for the history books. I desperately want the `github.com/ntfy` organization, but all my tickets with
+GitHub have been hopeless. In case it ever becomes available, I want to know immediately.
+
+``` cron
+# Check github/ntfy user
+*/6 * * * * if curl -s https://api.github.com/users/ntfy | grep "Not Found"; then curl -d "github.com/ntfy is available" -H "Tags: tada" -H "Prio: high" ntfy.sh/my-alerts; fi
+```
+
+
 ## Low disk space alerts
 Here's a simple cronjob that I use to alert me when the disk space on the root disk is running low. It's simple, but 
 effective. 
@@ -42,11 +53,7 @@ if [ -n "$avail" ]; then
 fi
 ```
 
-## Server-sent messages in your web app
-Just as you can [subscribe to topics in the Web UI](subscribe/web.md), you can use ntfy in your own
-web application. Check out the <a href="/example.html">live example</a>.
-
-## Notify on SSH login
+## SSH login alerts
 Years ago my home server was broken into. That shook me hard, so every time someone logs into any machine that I
 own, I now message myself. Here's an example of how to use <a href="https://en.wikipedia.org/wiki/Linux_PAM">PAM</a>
 to notify yourself on SSH login.
@@ -102,7 +109,7 @@ One of my co-workers uses the following Ansible task to let him know when things
     body: "{{ inventory_hostname }} reseeding complete"
 ```
 
-## Watchtower notifications (shoutrrr)
+## Watchtower (shoutrrr)
 You can use [shoutrrr](https://github.com/containrrr/shoutrrr) generic webhook support to send 
 [Watchtower](https://github.com/containrrr/watchtower/) notifications to your ntfy topic.
 
@@ -121,16 +128,7 @@ Or, if you only want to send notifications using shoutrrr:
 shoutrrr send -u "generic+https://ntfy.sh/my_watchtower_topic?title=WatchtowerUpdates" -m "testMessage"
 ```
 
-## Random cronjobs
-Alright, here's one for the history books. I desperately want the `github.com/ntfy` organization, but all my tickets with
-GitHub have been hopeless. In case it ever becomes available, I want to know immediately.
-
-``` cron
-# Check github/ntfy user
-*/6 * * * * if curl -s https://api.github.com/users/ntfy | grep "Not Found"; then curl -d "github.com/ntfy is available" -H "Tags: tada" -H "Prio: high" ntfy.sh/my-alerts; fi
-```
-
-## Download notifications (Sonarr, Radarr, Lidarr, Readarr, Prowlarr, SABnzbd)
+## Sonarr, Radarr, Lidarr, Readarr, Prowlarr, SABnzbd
 It's possible to use custom scripts for all the *arr services, plus SABnzbd. Notifications for downloads, warnings, grabs etc.
 Some simple bash scripts to achieve this are kindly provided in [nickexyz's repository](https://github.com/nickexyz/ntfy-shellscripts). 
 
@@ -343,7 +341,7 @@ You can use the HTTP request node to send messages with [Node-RED](https://noder
 
 ![Node red picture flow](static/img/nodered-picture.png)
 
-## Gatus service health check
+## Gatus
 
 An example for a custom alert with [Gatus](https://github.com/TwiN/gatus):
 ``` yaml
@@ -435,11 +433,37 @@ notify:
 ```
 
 ## Uptime Kuma
-- Go to your [Uptime Kuma](https://github.com/louislam/uptime-kuma) Settings > Notifications, click on **Setup Notification**
-- ![Uptime Kuma Settings](static/img/uptimekuma-settings.png)
-- Set your desired **title** (e.g. "Uptime Kuma"), **ntfy topic**, **Server URL** and **priority (1-5)**
-- ![Uptime Kuma Setup](static/img/uptimekuma-setup.png)
-- You can now test the notifications and apply them to monitors.
-- ![Uptime Kuma iOS Test](static/img/uptimekuma-ios-test.jpg)
-- ![Uptime Kuma iOS Down](static/img/uptimekuma-ios-down.jpg)
-- ![Uptime Kuma iOS Up](static/img/uptimekuma-ios-up.jpg)
\ No newline at end of file
+Go to your [Uptime Kuma](https://github.com/louislam/uptime-kuma) Settings > Notifications, click on **Setup Notification**.
+Then set your desired **title** (e.g. "Uptime Kuma"), **ntfy topic**, **Server URL** and **priority (1-5)**:
+
+<div id="uptimekuma-screenshots" class="screenshots">
+    <a href="../../static/img/uptimekuma-settings.png"><img src="../../static/img/uptimekuma-settings.png"/></a>
+    <a href="../../static/img/uptimekuma-setup.png"><img src="../../static/img/uptimekuma-setup.png"/></a>
+</div>
+
+You can now test the notifications and apply them to monitors:
+
+<div id="uptimekuma-monitor-screenshots" class="screenshots">
+    <a href="../../static/img/uptimekuma-ios-test.jpg"><img src="../../static/img/uptimekuma-ios-test.jpg"/></a>
+    <a href="../../static/img/uptimekuma-ios-down.jpg"><img src="../../static/img/uptimekuma-ios-down.jpg"/></a>
+    <a href="../../static/img/uptimekuma-ios-up.jpg"><img src="../../static/img/uptimekuma-ios-up.jpg"/></a>
+</div>
+
+## Apprise
+ntfy is integrated natively into [Apprise](https://github.com/caronc/apprise) (also check out the 
+[Apprise/ntfy wiki page](https://github.com/caronc/apprise/wiki/Notify_ntfy)).
+
+You can use it like this:
+
+```
+apprise -vv -t "Test Message Title" -b "Test Message Body" \
+   ntfy://mytopic
+```
+
+Or with your own server like this:
+
+```
+apprise -vv -t "Test Message Title" -b "Test Message Body" \
+   ntfy://ntfy.example.com/mytopic
+```
+
diff --git a/docs/faq.md b/docs/faq.md
index 9846170b..cc3e59c0 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -42,3 +42,10 @@ decent now.
 [Instant delivery](subscribe/phone.md#instant-delivery) is a feature in the Android app. If turned on, the app maintains a constant connection to the
 server and listens for incoming notifications. This consumes additional battery (see above),
 but delivers notifications instantly.
+
+## Where can I donate?
+Many people have asked (thanks for that!), but I am currently not accepting any donations. The cost is manageable 
+($25/month for hosting, and $99/year for the Apple cert) right now, and I don't want to have to feel obligated to 
+anyone by accepting their money.
+
+I may ask for donations in the future, though. After all, $400 per year isn't nothing... 
diff --git a/docs/publish.md b/docs/publish.md
index 5f0ae585..82f7beb0 100644
--- a/docs/publish.md
+++ b/docs/publish.md
@@ -2735,6 +2735,22 @@ parameter (or any of its aliases `unifiedpush` or `up`) to `1` to [disable Fireb
 option is mostly equivalent to `Firebase: no`, but was introduced to allow future flexibility. The flag additionally 
 enables auto-detection of the message encoding. If the message is binary, it'll be encoded as base64.
 
+### Matrix Gateway
+The ntfy server implements a [Matrix Push Gateway](https://spec.matrix.org/v1.2/push-gateway-api/) (in combination with
+[UnifiedPush](https://unifiedpush.org) as the [Provider Push Protocol](https://unifiedpush.org/developers/gateway/)). This makes it easier to integrate
+with self-hosted [Matrix](https://matrix.org/) servers (such as [synapse](https://github.com/matrix-org/synapse)), since 
+you don't have to set up a separate push proxy (such as [common-proxies](https://github.com/UnifiedPush/common-proxies)).
+
+In short, ntfy accepts Matrix messages on the `/_matrix/push/v1/notify` endpoint (see [Push Gateway API](https://spec.matrix.org/v1.2/push-gateway-api/)), 
+and forwards them to the ntfy topic defined in the `pushkey` of the message. The message will then be forwarded to the
+ntfy Android app, and passed on to the Matrix client there.
+
+There is a nice diagram in the [Push Gateway docs](https://spec.matrix.org/v1.2/push-gateway-api/). In this diagram, the
+ntfy server plays the role of the Push Gateway, as well as the Push Provider. UnifiedPush is the Provider Push Protocol.
+
+!!! info
+    This is not a generic Matrix Push Gateway. It only works in combination with UnifiedPush and ntfy.
+
 ## Public topics
 Obviously all topics on ntfy.sh are public, but there are a few designated topics that are used in examples, and topics
 that you can use to try out what [authentication and access control](#authentication) looks like.
diff --git a/docs/releases.md b/docs/releases.md
index 56e7fe1f..9150251a 100644
--- a/docs/releases.md
+++ b/docs/releases.md
@@ -13,16 +13,17 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
 
 ## ntfy server v1.26.0 (UNRELEASED)
 
-**Bugs:**
-
-* Web app: Show "notifications not supported" alert on HTTP ([#323](https://github.com/binwiederhier/ntfy/issues/323), thanks to [@milksteakjellybeans](https://github.com/milksteakjellybeans) for reporting)
-
 **Features:**
 
+* ntfy now is a [Matrix Push Gateway](https://spec.matrix.org/v1.2/push-gateway-api/) (in combination with [UnifiedPush](https://unifiedpush.org) as the [Provider Push Protocol](https://unifiedpush.org/developers/gateway/), [#319](https://github.com/binwiederhier/ntfy/issues/319)/[#326](https://github.com/binwiederhier/ntfy/pull/326), thanks to [@MayeulC](https://github.com/MayeulC) for reporting)
 * Windows CLI is now available via [Scoop](https://scoop.sh) ([ScoopInstaller#3594](https://github.com/ScoopInstaller/Main/pull/3594), [#311](https://github.com/binwiederhier/ntfy/pull/311), [#269](https://github.com/binwiederhier/ntfy/issues/269), thanks to [@kzshantonu](https://github.com/kzshantonu))
 * [Uptime Kuma](https://github.com/louislam/uptime-kuma) now allows publishing to ntfy ([uptime-kuma#1674](https://github.com/louislam/uptime-kuma/pull/1674), thanks to [@philippdormann](https://github.com/philippdormann))
 * Display ntfy version in `ntfy serve` command  ([#314](https://github.com/binwiederhier/ntfy/issues/314), thanks to [@poblabs](https://github.com/poblabs))
 
+**Bugs:**
+
+* Web app: Show "notifications not supported" alert on HTTP ([#323](https://github.com/binwiederhier/ntfy/issues/323), thanks to [@milksteakjellybeans](https://github.com/milksteakjellybeans) for reporting)
+
 **Documentation**
 
 * Added [example](examples.md) for [Uptime Kuma](https://github.com/louislam/uptime-kuma) integration ([#315](https://github.com/binwiederhier/ntfy/pull/315), thanks to [@philippdormann](https://github.com/philippdormann))
diff --git a/docs/static/css/extra.css b/docs/static/css/extra.css
index a7370399..6ac0b7e7 100644
--- a/docs/static/css/extra.css
+++ b/docs/static/css/extra.css
@@ -60,7 +60,8 @@ figure video {
 }
 
 .screenshots img {
-    height: 230px;
+    max-height: 230px;
+    max-width: 300px;
     margin: 3px;
     border-radius: 5px;
     filter: drop-shadow(2px 2px 2px #ddd);
diff --git a/docs/subscribe/api.md b/docs/subscribe/api.md
index 7eb3a95e..4c46d221 100644
--- a/docs/subscribe/api.md
+++ b/docs/subscribe/api.md
@@ -87,7 +87,7 @@ recommended way to subscribe to a topic**. The notable exception is JavaScript,
 ### Subscribe as SSE stream
 Using [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) in JavaScript, you can consume
 notifications via a [Server-Sent Events (SSE)](https://en.wikipedia.org/wiki/Server-sent_events) stream. It's incredibly 
-easy to use. Here's what it looks like. You may also want to check out the [live example](/example.html).
+easy to use. Here's what it looks like. You may also want to check out the [full example on GitHub](https://github.com/binwiederhier/ntfy/tree/main/examples/web-example-eventsource).
 
 === "Command line (curl)"
     ```
diff --git a/go.mod b/go.mod
index f022c731..a5caea5f 100644
--- a/go.mod
+++ b/go.mod
@@ -19,7 +19,7 @@ require (
 	golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f
 	golang.org/x/term v0.0.0-20220526004731-065cf7ba2467
 	golang.org/x/time v0.0.0-20220609170525-579cf78fd858
-	google.golang.org/api v0.83.0
+	google.golang.org/api v0.84.0
 	gopkg.in/yaml.v2 v2.4.0
 )
 
@@ -38,19 +38,20 @@ require (
 	github.com/golang/protobuf v1.5.2 // indirect
 	github.com/google/go-cmp v0.5.8 // indirect
 	github.com/google/uuid v1.3.0 // indirect
+	github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect
 	github.com/googleapis/gax-go/v2 v2.4.0 // indirect
 	github.com/googleapis/go-type-adapters v1.0.0 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/russross/blackfriday/v2 v2.1.0 // indirect
 	github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
 	go.opencensus.io v0.23.0 // indirect
-	golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect
-	golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d // indirect
+	golang.org/x/net v0.0.0-20220615171555-694bf12d69de // indirect
+	golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect
 	golang.org/x/text v0.3.7 // indirect
 	golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
 	google.golang.org/appengine v1.6.7 // indirect
 	google.golang.org/appengine/v2 v2.0.1 // indirect
-	google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac // indirect
+	google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90 // indirect
 	google.golang.org/grpc v1.47.0 // indirect
 	google.golang.org/protobuf v1.28.0 // indirect
 	gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
diff --git a/go.sum b/go.sum
index 941fa920..0eaa090a 100644
--- a/go.sum
+++ b/go.sum
@@ -192,6 +192,9 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
 github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
+github.com/googleapis/enterprise-certificate-proxy v0.1.0 h1:zO8WHNx/MYiAKJ3d5spxZXZE6KHmIQGQcAzwUzV7qQw=
+github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
 github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
@@ -341,11 +344,10 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su
 golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220526153639-5463443f8c37/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.0.0-20220531201128-c960675eff93 h1:MYimHLfoXEpOhqd/zgoA/uoXzHB86AEky4LAx5ij9xA=
-golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8=
 golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.0.0-20220615171555-694bf12d69de h1:ogOG2+P6LjO2j55AkRScrkB2BFpd+Z8TY2wcM0Z3MGo=
+golang.org/x/net v0.0.0-20220615171555-694bf12d69de/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -366,7 +368,6 @@ golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ
 golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
 golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
 golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
-golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401 h1:zwrSfklXn0gxyLRX/aR+q6cgHbV/ItVyzbPlbA+dkAw=
 golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
 golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb h1:8tDJ3aechhddbdPAxpycgXHJRMLpk/Ab+aa4OgdN5/g=
 golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
@@ -381,7 +382,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8=
 golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -443,10 +443,11 @@ golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d h1:Zu/JngovGLVi6t2J3nmAf3AoTDwuzw85YZ3b9o4yU7s=
 golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU=
+golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM=
@@ -464,8 +465,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w=
-golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U=
 golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -524,7 +523,6 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618=
 golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
 golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0=
 golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
@@ -571,10 +569,10 @@ google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRR
 google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
 google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
 google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
-google.golang.org/api v0.82.0 h1:h6EGeZuzhoKSS7BUznzkW+2wHZ+4Ubd6rsVvvh3dRkw=
-google.golang.org/api v0.82.0/go.mod h1:Ld58BeTlL9DIYr2M2ajvoSqmGLei0BMn+kVBmkam1os=
 google.golang.org/api v0.83.0 h1:pMvST+6v+46Gabac4zlJlalxZjCeRcepwg2EdBU+nCc=
 google.golang.org/api v0.83.0/go.mod h1:CNywQoj/AfhTw26ZWAa6LwOv+6WFxHmeLPZq2uncLZk=
+google.golang.org/api v0.84.0 h1:NMB9J4cCxs9xEm+1Z9QiO3eFvn7EnQj3Eo3hN6ugVlg=
+google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -669,11 +667,11 @@ google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX
 google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
 google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
 google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
-google.golang.org/genproto v0.0.0-20220527130721-00d5c0f3be58/go.mod h1:yKyY4AMRwFiC8yMMNaMi+RkCnjZJt9LoWuvhXjMs+To=
-google.golang.org/genproto v0.0.0-20220602131408-e326c6e8e9c8 h1:qRu95HZ148xXw+XeZ3dvqe85PxH4X8+jIo0iRPKcEnM=
 google.golang.org/genproto v0.0.0-20220602131408-e326c6e8e9c8/go.mod h1:yKyY4AMRwFiC8yMMNaMi+RkCnjZJt9LoWuvhXjMs+To=
 google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac h1:ByeiW1F67iV9o8ipGskA+HWzSkMbRJuKLlwCdPxzn7A=
 google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
+google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90 h1:4SPz2GL2CXJt28MTF8V6Ap/9ZiVbQlJeGSd9qtA7DLs=
+google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
diff --git a/server/errors.go b/server/errors.go
index 32c1b3b9..28dbca3a 100644
--- a/server/errors.go
+++ b/server/errors.go
@@ -50,10 +50,13 @@ var (
 	errHTTPBadRequestWebSocketsUpgradeHeaderMissing  = &errHTTP{40016, http.StatusBadRequest, "invalid request: client not using the websocket protocol", "https://ntfy.sh/docs/subscribe/api/#websockets"}
 	errHTTPBadRequestJSONInvalid                     = &errHTTP{40017, http.StatusBadRequest, "invalid request: request body must be message JSON", "https://ntfy.sh/docs/publish/#publish-as-json"}
 	errHTTPBadRequestActionsInvalid                  = &errHTTP{40018, http.StatusBadRequest, "invalid request: actions invalid", "https://ntfy.sh/docs/publish/#action-buttons"}
+	errHTTPBadRequestMatrixMessageInvalid            = &errHTTP{40019, http.StatusBadRequest, "invalid request: Matrix JSON invalid", "https://ntfy.sh/docs/publish/#matrix-gateway"}
+	errHTTPBadRequestMatrixPushkeyBaseURLMismatch    = &errHTTP{40020, http.StatusBadRequest, "invalid request: push key must be prefixed with base URL", "https://ntfy.sh/docs/publish/#matrix-gateway"}
 	errHTTPNotFound                                  = &errHTTP{40401, http.StatusNotFound, "page not found", ""}
 	errHTTPUnauthorized                              = &errHTTP{40101, http.StatusUnauthorized, "unauthorized", "https://ntfy.sh/docs/publish/#authentication"}
 	errHTTPForbidden                                 = &errHTTP{40301, http.StatusForbidden, "forbidden", "https://ntfy.sh/docs/publish/#authentication"}
 	errHTTPEntityTooLargeAttachmentTooLarge          = &errHTTP{41301, http.StatusRequestEntityTooLarge, "attachment too large, or bandwidth limit reached", "https://ntfy.sh/docs/publish/#limitations"}
+	errHTTPEntityTooLargeMatrixRequestTooLarge       = &errHTTP{41302, http.StatusRequestEntityTooLarge, "Matrix request is larger than the max allowed length", ""}
 	errHTTPTooManyRequestsLimitRequests              = &errHTTP{42901, http.StatusTooManyRequests, "limit reached: too many requests, please be nice", "https://ntfy.sh/docs/publish/#limitations"}
 	errHTTPTooManyRequestsLimitEmails                = &errHTTP{42902, http.StatusTooManyRequests, "limit reached: too many emails, please be nice", "https://ntfy.sh/docs/publish/#limitations"}
 	errHTTPTooManyRequestsLimitSubscriptions         = &errHTTP{42903, http.StatusTooManyRequests, "limit reached: too many active subscriptions, please be nice", "https://ntfy.sh/docs/publish/#limitations"}
@@ -61,4 +64,5 @@ var (
 	errHTTPTooManyRequestsAttachmentBandwidthLimit   = &errHTTP{42905, http.StatusTooManyRequests, "too many requests: daily bandwidth limit reached", "https://ntfy.sh/docs/publish/#limitations"}
 	errHTTPInternalError                             = &errHTTP{50001, http.StatusInternalServerError, "internal server error", ""}
 	errHTTPInternalErrorInvalidFilePath              = &errHTTP{50002, http.StatusInternalServerError, "internal server error: invalid file path", ""}
+	errHTTPInternalErrorMissingBaseURL               = &errHTTP{50003, http.StatusInternalServerError, "internal server error: base-url must be be configured for this feature", "https://ntfy.sh/docs/config/"}
 )
diff --git a/server/example.html b/server/example.html
deleted file mode 100644
index e558ef12..00000000
--- a/server/example.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    <meta charset="UTF-8">
-    <title>ntfy.sh: EventSource Example</title>
-    <meta name="robots" content="noindex, nofollow" />
-    <style>
-        body { font-size: 1.2em; line-height: 130%; }
-        #events { font-family: monospace; }
-    </style>
-</head>
-<body>
-<h1>ntfy.sh: EventSource Example</h1>
-<p>
-    This is an example showing how to use <a href="https://ntfy.sh">ntfy.sh</a> with
-    <a href="https://developer.mozilla.org/en-US/docs/Web/API/EventSource">EventSource</a>.<br/>
-    This example doesn't need a server. You can just save the HTML page and run it from anywhere.
-</p>
-<button id="publishButton">Send test notification</button>
-<p><b>Log:</b></p>
-<div id="events"></div>
-
-<script type="text/javascript">
-    const publishURL = `https://ntfy.sh/example`;
-    const subscribeURL = `https://ntfy.sh/example/sse`;
-    const events = document.getElementById('events');
-    const eventSource = new EventSource(subscribeURL);
-
-    // Publish button
-    document.getElementById("publishButton").onclick = () => {
-        fetch(publishURL, {
-            method: 'POST', // works with PUT as well, though that sends an OPTIONS request too!
-            body: `It is ${new Date().toString()}. This is a test.`
-        })
-    };
-
-    // Incoming events
-    eventSource.onopen = () => {
-        let event = document.createElement('div');
-        event.innerHTML = `EventSource connected to ${subscribeURL}`;
-        events.appendChild(event);
-    };
-    eventSource.onerror = (e) => {
-        let event = document.createElement('div');
-        event.innerHTML = `EventSource error: Failed to connect to ${subscribeURL}`;
-        events.appendChild(event);
-    };
-    eventSource.onmessage = (e) => {
-        let event = document.createElement('div');
-        event.innerHTML = e.data;
-        events.appendChild(event);
-    };
-</script>
-
-</body>
-</html>
diff --git a/server/server.go b/server/server.go
index 2f01b07f..21a6c584 100644
--- a/server/server.go
+++ b/server/server.go
@@ -68,15 +68,13 @@ var (
 
 	webConfigPath    = "/config.js"
 	userStatsPath    = "/user/stats"
+	matrixPushPath   = "/_matrix/push/v1/notify"
 	staticRegex      = regexp.MustCompile(`^/static/.+`)
 	docsRegex        = regexp.MustCompile(`^/docs(|/.*)$`)
 	fileRegex        = regexp.MustCompile(`^/file/([-_A-Za-z0-9]{1,64})(?:\.[A-Za-z0-9]{1,16})?$`)
 	disallowedTopics = []string{"docs", "static", "file", "app", "settings"} // If updated, also update in Android app
 	attachURLRegex   = regexp.MustCompile(`^https?://`)
 
-	//go:embed "example.html"
-	exampleSource string
-
 	//go:embed site
 	webFs        embed.FS
 	webFsCached  = &util.CachingEmbedFS{ModTime: time.Now(), FS: webFs}
@@ -258,6 +256,10 @@ func (s *Server) handle(w http.ResponseWriter, r *http.Request) {
 			}
 			return // Do not attempt to write to upgraded connection
 		}
+		if matrixErr, ok := err.(*errMatrix); ok {
+			writeMatrixError(w, r, v, matrixErr)
+			return
+		}
 		httpErr, ok := err.(*errHTTP)
 		if !ok {
 			httpErr = errHTTPInternalError
@@ -278,14 +280,14 @@ func (s *Server) handle(w http.ResponseWriter, r *http.Request) {
 func (s *Server) handleInternal(w http.ResponseWriter, r *http.Request, v *visitor) error {
 	if r.Method == http.MethodGet && r.URL.Path == "/" {
 		return s.ensureWebEnabled(s.handleHome)(w, r, v)
-	} else if r.Method == http.MethodGet && r.URL.Path == "/example.html" {
-		return s.ensureWebEnabled(s.handleExample)(w, r, v)
 	} else if r.Method == http.MethodHead && r.URL.Path == "/" {
 		return s.ensureWebEnabled(s.handleEmpty)(w, r, v)
 	} else if r.Method == http.MethodGet && r.URL.Path == webConfigPath {
 		return s.ensureWebEnabled(s.handleWebConfig)(w, r, v)
 	} else if r.Method == http.MethodGet && r.URL.Path == userStatsPath {
 		return s.handleUserStats(w, r, v)
+	} else if r.Method == http.MethodGet && r.URL.Path == matrixPushPath {
+		return s.handleMatrixDiscovery(w)
 	} else if r.Method == http.MethodGet && staticRegex.MatchString(r.URL.Path) {
 		return s.ensureWebEnabled(s.handleStatic)(w, r, v)
 	} else if r.Method == http.MethodGet && docsRegex.MatchString(r.URL.Path) {
@@ -296,6 +298,8 @@ func (s *Server) handleInternal(w http.ResponseWriter, r *http.Request, v *visit
 		return s.ensureWebEnabled(s.handleOptions)(w, r, v)
 	} else if (r.Method == http.MethodPut || r.Method == http.MethodPost) && r.URL.Path == "/" {
 		return s.limitRequests(s.transformBodyJSON(s.authWrite(s.handlePublish)))(w, r, v)
+	} else if r.Method == http.MethodPost && r.URL.Path == matrixPushPath {
+		return s.limitRequests(s.transformMatrixJSON(s.authWrite(s.handlePublishMatrix)))(w, r, v)
 	} else if (r.Method == http.MethodPut || r.Method == http.MethodPost) && topicPathRegex.MatchString(r.URL.Path) {
 		return s.limitRequests(s.authWrite(s.handlePublish))(w, r, v)
 	} else if r.Method == http.MethodGet && publishPathRegex.MatchString(r.URL.Path) {
@@ -348,11 +352,6 @@ func (s *Server) handleTopicAuth(w http.ResponseWriter, _ *http.Request, _ *visi
 	return err
 }
 
-func (s *Server) handleExample(w http.ResponseWriter, _ *http.Request, _ *visitor) error {
-	_, err := io.WriteString(w, exampleSource)
-	return err
-}
-
 func (s *Server) handleWebConfig(w http.ResponseWriter, _ *http.Request, _ *visitor) error {
 	appRoot := "/"
 	if !s.config.WebRootIsApp {
@@ -425,25 +424,29 @@ func (s *Server) handleFile(w http.ResponseWriter, r *http.Request, v *visitor)
 	return nil
 }
 
-func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, v *visitor) error {
+func (s *Server) handleMatrixDiscovery(w http.ResponseWriter) error {
+	return writeMatrixDiscoveryResponse(w)
+}
+
+func (s *Server) handlePublishWithoutResponse(r *http.Request, v *visitor) (*message, error) {
 	t, err := s.topicFromPath(r.URL.Path)
 	if err != nil {
-		return err
+		return nil, err
 	}
 	body, err := util.Peek(r.Body, s.config.MessageLimit)
 	if err != nil {
-		return err
+		return nil, err
 	}
 	m := newDefaultMessage(t.ID, "")
 	cache, firebase, email, unifiedpush, err := s.parsePublishParams(r, v, m)
 	if err != nil {
-		return err
+		return nil, err
 	}
 	if m.PollID != "" {
 		m = newPollRequestMessage(t.ID, m.PollID)
 	}
 	if err := s.handlePublishBody(r, v, m, body, unifiedpush); err != nil {
-		return err
+		return nil, err
 	}
 	if m.Message == "" {
 		m.Message = emptyMessageBody
@@ -456,7 +459,7 @@ func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, v *visito
 	}
 	if !delayed {
 		if err := t.Publish(v, m); err != nil {
-			return err
+			return nil, err
 		}
 		if s.firebaseClient != nil && firebase {
 			go s.sendToFirebase(v, m)
@@ -472,20 +475,36 @@ func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, v *visito
 	}
 	if cache {
 		if err := s.messageCache.AddMessage(m); err != nil {
-			return err
+			return nil, err
 		}
 	}
+	s.mu.Lock()
+	s.messages++
+	s.mu.Unlock()
+	return m, nil
+}
+
+func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, v *visitor) error {
+	m, err := s.handlePublishWithoutResponse(r, v)
+	if err != nil {
+		return err
+	}
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Access-Control-Allow-Origin", "*") // CORS, allow cross-origin requests
 	if err := json.NewEncoder(w).Encode(m); err != nil {
 		return err
 	}
-	s.mu.Lock()
-	s.messages++
-	s.mu.Unlock()
 	return nil
 }
 
+func (s *Server) handlePublishMatrix(w http.ResponseWriter, r *http.Request, v *visitor) error {
+	_, err := s.handlePublishWithoutResponse(r, v)
+	if err != nil {
+		return &errMatrix{pushKey: r.Header.Get(matrixPushKeyHeader), err: err}
+	}
+	return writeMatrixSuccess(w)
+}
+
 func (s *Server) sendToFirebase(v *visitor, m *message) {
 	log.Debug("%s Publishing to Firebase", logMessagePrefix(v, m))
 	if err := s.firebaseClient.Send(v, m); err != nil {
@@ -1286,6 +1305,19 @@ func (s *Server) transformBodyJSON(next handleFunc) handleFunc {
 	}
 }
 
+func (s *Server) transformMatrixJSON(next handleFunc) handleFunc {
+	return func(w http.ResponseWriter, r *http.Request, v *visitor) error {
+		newRequest, err := newRequestFromMatrixJSON(r, s.config.BaseURL, s.config.MessageLimit)
+		if err != nil {
+			return err
+		}
+		if err := next(w, newRequest, v); err != nil {
+			return &errMatrix{pushKey: newRequest.Header.Get(matrixPushKeyHeader), err: err}
+		}
+		return nil
+	}
+}
+
 func (s *Server) authWrite(next handleFunc) handleFunc {
 	return s.withAuth(next, auth.PermissionWrite)
 }
diff --git a/server/server.yml b/server/server.yml
index 01a212d0..65f1db3c 100644
--- a/server/server.yml
+++ b/server/server.yml
@@ -4,8 +4,12 @@
 # All options also support underscores (_) instead of dashes (-) to comply with the YAML spec.
 
 # Public facing base URL of the service (e.g. https://ntfy.sh or https://ntfy.example.com)
-# This setting is currently only used by attachments, e-mail sending (outgoing mail only), as well
-# as in combination with upstream-base-url (for iOS push notifications for self-hosted servers).
+#
+# This setting is required for any of the following features:
+# - attachments (to return a download URL)
+# - e-mail sending (for the topic URL in the email footer)
+# - iOS push notifications for self-hosted servers (to calculate the Firebase poll_request topic)
+# - Matrix Push Gateway (to validate that the pushkey is correct)
 #
 # base-url:
 
diff --git a/server/server_matrix.go b/server/server_matrix.go
new file mode 100644
index 00000000..2113c5ac
--- /dev/null
+++ b/server/server_matrix.go
@@ -0,0 +1,175 @@
+package server
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"heckel.io/ntfy/log"
+	"heckel.io/ntfy/util"
+	"io"
+	"net/http"
+	"strings"
+)
+
+// Matrix Push Gateway / UnifiedPush / ntfy integration:
+//
+// ntfy implements a Matrix Push Gateway (as defined in https://spec.matrix.org/v1.2/push-gateway-api/),
+// in combination with UnifiedPush as the Provider Push Protocol (as defined in https://unifiedpush.org/developers/gateway/).
+//
+// In the picture below, ntfy is the Push Gateway (mostly in this file), as well as the Push Provider (ntfy's
+// main functionality). UnifiedPush is the Provider Push Protocol, as implemented by the ntfy server and the
+// ntfy Android app.
+//
+//                                    +--------------------+  +-------------------+
+//                  Matrix HTTP      |                    |  |                   |
+//             Notification Protocol |   App Developer    |  |   Device Vendor   |
+//                                   |                    |  |                   |
+//           +-------------------+   | +----------------+ |  | +---------------+ |
+//           |                   |   | |                | |  | |               | |
+//           | Matrix homeserver +----->  Push Gateway  +------> Push Provider | |
+//           |                   |   | |                | |  | |               | |
+//           +-^-----------------+   | +----------------+ |  | +----+----------+ |
+//             |                     |                    |  |      |            |
+//    Matrix   |                     |                    |  |      |            |
+// Client/Server API  +              |                    |  |      |            |
+//             |      |              +--------------------+  +-------------------+
+//             |   +--+-+                                           |
+//             |   |    <-------------------------------------------+
+//             +---+    |
+//                 |    |          Provider Push Protocol
+//                 +----+
+//
+//         Mobile Device or Client
+//
+
+// matrixRequest represents a Matrix message, as it is sent to a Push Gateway (as per
+// this spec: https://spec.matrix.org/v1.2/push-gateway-api/).
+//
+// From the message, we only require the "pushkey", as it represents our target topic URL.
+// A message may look like this (excerpt):
+//    {
+//      "notification": {
+//        "devices": [
+//           {
+//              "pushkey": "https://ntfy.sh/upDAHJKFFDFD?up=1",
+//              ...
+//           }
+//        ]
+//      }
+//    }
+//
+type matrixRequest struct {
+	Notification *struct {
+		Devices []*struct {
+			PushKey string `json:"pushkey"`
+		} `json:"devices"`
+	} `json:"notification"`
+}
+
+// matrixResponse represents the response to a Matrix push gateway message, as defined
+// in the spec (https://spec.matrix.org/v1.2/push-gateway-api/).
+type matrixResponse struct {
+	Rejected []string `json:"rejected"`
+}
+
+// errMatrix represents an error when handing Matrix gateway messages
+type errMatrix struct {
+	pushKey string
+	err     error
+}
+
+func (e errMatrix) Error() string {
+	if e.err != nil {
+		return fmt.Sprintf("message with push key %s rejected: %s", e.pushKey, e.err.Error())
+	}
+	return fmt.Sprintf("message with push key %s rejected", e.pushKey)
+}
+
+const (
+	// matrixPushKeyHeader is a header that's used internally to pass the Matrix push key (from the matrixRequest)
+	// along with the request. The push key is only used if an error occurs down the line.
+	matrixPushKeyHeader = "X-Matrix-Pushkey"
+)
+
+// newRequestFromMatrixJSON reads the request body as a Matrix JSON message, parses the "pushkey", and creates a new
+// HTTP request that looks like a normal ntfy request from it.
+//
+// It basically converts a Matrix push gatewqy request:
+//
+//    POST /_matrix/push/v1/notify HTTP/1.1
+//    { "notification": { "devices": [ { "pushkey": "https://ntfy.sh/upDAHJKFFDFD?up=1", ... } ] } }
+//
+// to a ntfy request, looking like this:
+//
+//    POST /upDAHJKFFDFD?up=1 HTTP/1.1
+//    { "notification": { "devices": [ { "pushkey": "https://ntfy.sh/upDAHJKFFDFD?up=1", ... } ] } }
+//
+func newRequestFromMatrixJSON(r *http.Request, baseURL string, messageLimit int) (*http.Request, error) {
+	if baseURL == "" {
+		return nil, errHTTPInternalErrorMissingBaseURL
+	}
+	body, err := util.Peek(r.Body, messageLimit)
+	if err != nil {
+		return nil, err
+	}
+	defer r.Body.Close()
+	if body.LimitReached {
+		return nil, errHTTPEntityTooLargeMatrixRequestTooLarge
+	}
+	var m matrixRequest
+	if err := json.Unmarshal(body.PeekedBytes, &m); err != nil {
+		return nil, errHTTPBadRequestMatrixMessageInvalid
+	} else if m.Notification == nil || len(m.Notification.Devices) == 0 || m.Notification.Devices[0].PushKey == "" {
+		return nil, errHTTPBadRequestMatrixMessageInvalid
+	}
+	pushKey := m.Notification.Devices[0].PushKey // We ignore other devices for now, see discussion in #316
+	if !strings.HasPrefix(pushKey, baseURL+"/") {
+		return nil, &errMatrix{pushKey: pushKey, err: errHTTPBadRequestMatrixPushkeyBaseURLMismatch}
+	}
+	newRequest, err := http.NewRequest(http.MethodPost, pushKey, io.NopCloser(bytes.NewReader(body.PeekedBytes)))
+	if err != nil {
+		return nil, &errMatrix{pushKey: pushKey, err: err}
+	}
+	newRequest.RemoteAddr = r.RemoteAddr // Not strictly necessary, since visitor was already extracted
+	if r.Header.Get("X-Forwarded-For") != "" {
+		newRequest.Header.Set("X-Forwarded-For", r.Header.Get("X-Forwarded-For"))
+	}
+	newRequest.Header.Set(matrixPushKeyHeader, pushKey)
+	return newRequest, nil
+}
+
+// writeMatrixDiscoveryResponse writes the UnifiedPush Matrix Gateway Discovery response to the given http.ResponseWriter,
+// as per the spec (https://unifiedpush.org/developers/gateway/).
+func writeMatrixDiscoveryResponse(w http.ResponseWriter) error {
+	w.Header().Set("Content-Type", "application/json")
+	_, err := io.WriteString(w, `{"unifiedpush":{"gateway":"matrix"}}`+"\n")
+	return err
+}
+
+// writeMatrixError logs and writes the errMatrix to the given http.ResponseWriter as a matrixResponse
+func writeMatrixError(w http.ResponseWriter, r *http.Request, v *visitor, err *errMatrix) error {
+	log.Debug("%s Matrix gateway error: %s", logHTTPPrefix(v, r), err.Error())
+	return writeMatrixResponse(w, err.pushKey)
+}
+
+// writeMatrixSuccess writes a successful matrixResponse (no rejected push key) to the given http.ResponseWriter
+func writeMatrixSuccess(w http.ResponseWriter) error {
+	return writeMatrixResponse(w, "")
+}
+
+// writeMatrixResponse writes a matrixResponse to the given http.ResponseWriter, as defined in
+// the spec (https://spec.matrix.org/v1.2/push-gateway-api/)
+func writeMatrixResponse(w http.ResponseWriter, rejectedPushKey string) error {
+	rejected := make([]string, 0)
+	if rejectedPushKey != "" {
+		rejected = append(rejected, rejectedPushKey)
+	}
+	response := &matrixResponse{
+		Rejected: rejected,
+	}
+	w.Header().Set("Content-Type", "application/json")
+	if err := json.NewEncoder(w).Encode(response); err != nil {
+		return err
+	}
+	return nil
+}
diff --git a/server/server_matrix_test.go b/server/server_matrix_test.go
new file mode 100644
index 00000000..9129d6c4
--- /dev/null
+++ b/server/server_matrix_test.go
@@ -0,0 +1,84 @@
+package server
+
+import (
+	"github.com/stretchr/testify/require"
+	"net/http"
+	"net/http/httptest"
+	"strings"
+	"testing"
+)
+
+func TestMatrix_NewRequestFromMatrixJSON_Success(t *testing.T) {
+	baseURL := "https://ntfy.sh"
+	maxLength := 4096
+	body := `{"notification":{"content":{"body":"I'm floating in a most peculiar way.","msgtype":"m.text"},"counts":{"missed_calls":1,"unread":2},"devices":[{"app_id":"org.matrix.matrixConsole.ios","data":{},"pushkey":"https://ntfy.sh/upABCDEFGHI?up=1","pushkey_ts":12345678,"tweaks":{"sound":"bing"}}],"event_id":"$3957tyerfgewrf384","prio":"high","room_alias":"#exampleroom:matrix.org","room_id":"!slw48wfj34rtnrf:example.com","room_name":"Mission Control","sender":"@exampleuser:matrix.org","sender_display_name":"Major Tom","type":"m.room.message"}}`
+	r, _ := http.NewRequest("POST", "http://ntfy.example.com/_matrix/push/v1/notify", strings.NewReader(body))
+	newRequest, err := newRequestFromMatrixJSON(r, baseURL, maxLength)
+	require.Nil(t, err)
+	require.Equal(t, "POST", newRequest.Method)
+	require.Equal(t, "https://ntfy.sh/upABCDEFGHI?up=1", newRequest.URL.String())
+	require.Equal(t, "https://ntfy.sh/upABCDEFGHI?up=1", newRequest.Header.Get("X-Matrix-Pushkey"))
+	require.Equal(t, body, readAll(t, newRequest.Body))
+}
+
+func TestMatrix_NewRequestFromMatrixJSON_TooLarge(t *testing.T) {
+	baseURL := "https://ntfy.sh"
+	maxLength := 10 // Small
+	body := `{"notification":{"content":{"body":"I'm floating in a most peculiar way.","msgtype":"m.text"},"counts":{"missed_calls":1,"unread":2},"devices":[{"app_id":"org.matrix.matrixConsole.ios","data":{},"pushkey":"https://ntfy.sh/upABCDEFGHI?up=1","pushkey_ts":12345678,"tweaks":{"sound":"bing"}}],"event_id":"$3957tyerfgewrf384","prio":"high","room_alias":"#exampleroom:matrix.org","room_id":"!slw48wfj34rtnrf:example.com","room_name":"Mission Control","sender":"@exampleuser:matrix.org","sender_display_name":"Major Tom","type":"m.room.message"}}`
+	r, _ := http.NewRequest("POST", "http://ntfy.example.com/_matrix/push/v1/notify", strings.NewReader(body))
+	_, err := newRequestFromMatrixJSON(r, baseURL, maxLength)
+	require.Equal(t, errHTTPEntityTooLargeMatrixRequestTooLarge, err)
+}
+
+func TestMatrix_NewRequestFromMatrixJSON_InvalidJSON(t *testing.T) {
+	baseURL := "https://ntfy.sh"
+	maxLength := 4096
+	body := `this is not json`
+	r, _ := http.NewRequest("POST", "http://ntfy.example.com/_matrix/push/v1/notify", strings.NewReader(body))
+	_, err := newRequestFromMatrixJSON(r, baseURL, maxLength)
+	require.Equal(t, errHTTPBadRequestMatrixMessageInvalid, err)
+}
+
+func TestMatrix_NewRequestFromMatrixJSON_NotAMatrixMessage(t *testing.T) {
+	baseURL := "https://ntfy.sh"
+	maxLength := 4096
+	body := `{"message":"this is not a matrix message, but valid json"}`
+	r, _ := http.NewRequest("POST", "http://ntfy.example.com/_matrix/push/v1/notify", strings.NewReader(body))
+	_, err := newRequestFromMatrixJSON(r, baseURL, maxLength)
+	require.Equal(t, errHTTPBadRequestMatrixMessageInvalid, err)
+}
+
+func TestMatrix_NewRequestFromMatrixJSON_MismatchingPushKey(t *testing.T) {
+	baseURL := "https://ntfy.sh" // Mismatch!
+	maxLength := 4096
+	body := `{"notification":{"content":{"body":"I'm floating in a most peculiar way.","msgtype":"m.text"},"counts":{"missed_calls":1,"unread":2},"devices":[{"app_id":"org.matrix.matrixConsole.ios","data":{},"pushkey":"https://ntfy.example.com/upABCDEFGHI?up=1","pushkey_ts":12345678,"tweaks":{"sound":"bing"}}],"event_id":"$3957tyerfgewrf384","prio":"high","room_alias":"#exampleroom:matrix.org","room_id":"!slw48wfj34rtnrf:example.com","room_name":"Mission Control","sender":"@exampleuser:matrix.org","sender_display_name":"Major Tom","type":"m.room.message"}}`
+	r, _ := http.NewRequest("POST", "http://ntfy.example.com/_matrix/push/v1/notify", strings.NewReader(body))
+	_, err := newRequestFromMatrixJSON(r, baseURL, maxLength)
+	matrixErr, ok := err.(*errMatrix)
+	require.True(t, ok)
+	require.Equal(t, errHTTPBadRequestMatrixPushkeyBaseURLMismatch, matrixErr.err)
+	require.Equal(t, "https://ntfy.example.com/upABCDEFGHI?up=1", matrixErr.pushKey)
+}
+
+func TestMatrix_WriteMatrixDiscoveryResponse(t *testing.T) {
+	w := httptest.NewRecorder()
+	require.Nil(t, writeMatrixDiscoveryResponse(w))
+	require.Equal(t, 200, w.Result().StatusCode)
+	require.Equal(t, `{"unifiedpush":{"gateway":"matrix"}}`+"\n", w.Body.String())
+}
+
+func TestMatrix_WriteMatrixError(t *testing.T) {
+	w := httptest.NewRecorder()
+	r, _ := http.NewRequest("POST", "http://ntfy.example.com/_matrix/push/v1/notify", nil)
+	v := newVisitor(newTestConfig(t), nil, "1.2.3.4")
+	require.Nil(t, writeMatrixError(w, r, v, &errMatrix{"https://ntfy.example.com/upABCDEFGHI?up=1", errHTTPBadRequestMatrixPushkeyBaseURLMismatch}))
+	require.Equal(t, 200, w.Result().StatusCode)
+	require.Equal(t, `{"rejected":["https://ntfy.example.com/upABCDEFGHI?up=1"]}`+"\n", w.Body.String())
+}
+
+func TestMatrix_WriteMatrixSuccess(t *testing.T) {
+	w := httptest.NewRecorder()
+	require.Nil(t, writeMatrixSuccess(w))
+	require.Equal(t, 200, w.Result().StatusCode)
+	require.Equal(t, `{"rejected":[]}`+"\n", w.Body.String())
+}
diff --git a/server/server_test.go b/server/server_test.go
index 32f4fc2d..55125c3e 100644
--- a/server/server_test.go
+++ b/server/server_test.go
@@ -6,6 +6,7 @@ import (
 	"encoding/base64"
 	"encoding/json"
 	"fmt"
+	"io"
 	"math/rand"
 	"net/http"
 	"net/http/httptest"
@@ -171,10 +172,6 @@ func TestServer_StaticSites(t *testing.T) {
 	require.Equal(t, 301, rr.Code)
 
 	// Docs test removed, it was failing annoyingly.
-
-	rr = request(t, s, "GET", "/example.html", "", nil)
-	require.Equal(t, 200, rr.Code)
-	require.Contains(t, rr.Body.String(), "</html>")
 }
 
 func TestServer_WebEnabled(t *testing.T) {
@@ -185,9 +182,6 @@ func TestServer_WebEnabled(t *testing.T) {
 	rr := request(t, s, "GET", "/", "", nil)
 	require.Equal(t, 404, rr.Code)
 
-	rr = request(t, s, "GET", "/example.html", "", nil)
-	require.Equal(t, 404, rr.Code)
-
 	rr = request(t, s, "GET", "/config.js", "", nil)
 	require.Equal(t, 404, rr.Code)
 
@@ -201,9 +195,6 @@ func TestServer_WebEnabled(t *testing.T) {
 	rr = request(t, s2, "GET", "/", "", nil)
 	require.Equal(t, 200, rr.Code)
 
-	rr = request(t, s2, "GET", "/example.html", "", nil)
-	require.Equal(t, 200, rr.Code)
-
 	rr = request(t, s2, "GET", "/config.js", "", nil)
 	require.Equal(t, 200, rr.Code)
 
@@ -916,6 +907,60 @@ func TestServer_PublishUnifiedPushText(t *testing.T) {
 	require.Equal(t, "this is a unifiedpush text message", m.Message)
 }
 
+func TestServer_MatrixGateway_Discovery(t *testing.T) {
+	s := newTestServer(t, newTestConfig(t))
+	response := request(t, s, "GET", "/_matrix/push/v1/notify", "", nil)
+	require.Equal(t, 200, response.Code)
+	require.Equal(t, `{"unifiedpush":{"gateway":"matrix"}}`+"\n", response.Body.String())
+}
+
+func TestServer_MatrixGateway_Push_Success(t *testing.T) {
+	s := newTestServer(t, newTestConfig(t))
+	notification := `{"notification":{"devices":[{"pushkey":"http://127.0.0.1:12345/mytopic?up=1"}]}}`
+	response := request(t, s, "POST", "/_matrix/push/v1/notify", notification, nil)
+	require.Equal(t, 200, response.Code)
+	require.Equal(t, `{"rejected":[]}`+"\n", response.Body.String())
+
+	response = request(t, s, "GET", "/mytopic/json?poll=1", "", nil)
+	require.Equal(t, 200, response.Code)
+	m := toMessage(t, response.Body.String())
+	require.Equal(t, notification, m.Message)
+}
+
+func TestServer_MatrixGateway_Push_Failure_InvalidPushkey(t *testing.T) {
+	s := newTestServer(t, newTestConfig(t))
+	notification := `{"notification":{"devices":[{"pushkey":"http://wrong-base-url.com/mytopic?up=1"}]}}`
+	response := request(t, s, "POST", "/_matrix/push/v1/notify", notification, nil)
+	require.Equal(t, 200, response.Code)
+	require.Equal(t, `{"rejected":["http://wrong-base-url.com/mytopic?up=1"]}`+"\n", response.Body.String())
+
+	response = request(t, s, "GET", "/mytopic/json?poll=1", "", nil)
+	require.Equal(t, 200, response.Code)
+	require.Equal(t, "", response.Body.String()) // Empty!
+}
+
+func TestServer_MatrixGateway_Push_Failure_EverythingIsWrong(t *testing.T) {
+	s := newTestServer(t, newTestConfig(t))
+	notification := `{"message":"this is not really a Matrix message"}`
+	response := request(t, s, "POST", "/_matrix/push/v1/notify", notification, nil)
+	require.Equal(t, 400, response.Code)
+	err := toHTTPError(t, response.Body.String())
+	require.Equal(t, 40019, err.Code)
+	require.Equal(t, 400, err.HTTPCode)
+}
+
+func TestServer_MatrixGateway_Push_Failure_Unconfigured(t *testing.T) {
+	c := newTestConfig(t)
+	c.BaseURL = ""
+	s := newTestServer(t, c)
+	notification := `{"notification":{"devices":[{"pushkey":"http://127.0.0.1:12345/mytopic?up=1"}]}}`
+	response := request(t, s, "POST", "/_matrix/push/v1/notify", notification, nil)
+	require.Equal(t, 500, response.Code)
+	err := toHTTPError(t, response.Body.String())
+	require.Equal(t, 50003, err.Code)
+	require.Equal(t, 500, err.HTTPCode)
+}
+
 func TestServer_PublishActions_AndPoll(t *testing.T) {
 	s := newTestServer(t, newTestConfig(t))
 	response := request(t, s, "PUT", "/mytopic", "my message", map[string]string{
@@ -1348,3 +1393,11 @@ func toHTTPError(t *testing.T, s string) *errHTTP {
 func basicAuth(s string) string {
 	return fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(s)))
 }
+
+func readAll(t *testing.T, rc io.ReadCloser) string {
+	b, err := io.ReadAll(rc)
+	if err != nil {
+		t.Fatal(err)
+	}
+	return string(b)
+}
diff --git a/server/smtp_server_test.go b/server/smtp_server_test.go
index 8e9d5892..c0de7079 100644
--- a/server/smtp_server_test.go
+++ b/server/smtp_server_test.go
@@ -3,7 +3,6 @@ package server
 import (
 	"github.com/emersion/go-smtp"
 	"github.com/stretchr/testify/require"
-	"io"
 	"net"
 	"net/http"
 	"strings"
@@ -304,14 +303,6 @@ func newTestBackend(t *testing.T, handler func(http.ResponseWriter, *http.Reques
 	return conf, backend
 }
 
-func readAll(t *testing.T, rc io.ReadCloser) string {
-	b, err := io.ReadAll(rc)
-	if err != nil {
-		t.Fatal(err)
-	}
-	return string(b)
-}
-
 func fakeConnState(t *testing.T, remoteAddr string) *smtp.ConnectionState {
 	ip, err := net.ResolveIPAddr("ip", remoteAddr)
 	if err != nil {
diff --git a/util/peek.go b/util/peek.go
index f7219253..40150cbc 100644
--- a/util/peek.go
+++ b/util/peek.go
@@ -18,7 +18,8 @@ type PeekedReadCloser struct {
 	closed       bool
 }
 
-// Peek reads the underlying ReadCloser into memory up until the limit and returns a PeekedReadCloser
+// Peek reads the underlying ReadCloser into memory up until the limit and returns a PeekedReadCloser.
+// It does not return an error if limit is reached. Instead, LimitReached will be set to true.
 func Peek(underlying io.ReadCloser, limit int) (*PeekedReadCloser, error) {
 	if underlying == nil {
 		underlying = io.NopCloser(strings.NewReader(""))
diff --git a/web/package-lock.json b/web/package-lock.json
index f4d0bb5a..dc733ba5 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -52,17 +52,17 @@
       }
     },
     "node_modules/@babel/compat-data": {
-      "version": "7.17.10",
-      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz",
-      "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==",
+      "version": "7.18.5",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.5.tgz",
+      "integrity": "sha512-BxhE40PVCBxVEJsSBhB6UWyAuqJRxGsAw8BdHMJ3AKGydcwuWW4kOO3HmqBQAdcq/OP+/DlTVxLvsCzRTnZuGg==",
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/core": {
-      "version": "7.18.2",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.2.tgz",
-      "integrity": "sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==",
+      "version": "7.18.5",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.5.tgz",
+      "integrity": "sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ==",
       "dependencies": {
         "@ampproject/remapping": "^2.1.0",
         "@babel/code-frame": "^7.16.7",
@@ -70,10 +70,10 @@
         "@babel/helper-compilation-targets": "^7.18.2",
         "@babel/helper-module-transforms": "^7.18.0",
         "@babel/helpers": "^7.18.2",
-        "@babel/parser": "^7.18.0",
+        "@babel/parser": "^7.18.5",
         "@babel/template": "^7.16.7",
-        "@babel/traverse": "^7.18.2",
-        "@babel/types": "^7.18.2",
+        "@babel/traverse": "^7.18.5",
+        "@babel/types": "^7.18.4",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.2",
@@ -471,9 +471,9 @@
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.18.4",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.4.tgz",
-      "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==",
+      "version": "7.18.5",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.5.tgz",
+      "integrity": "sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==",
       "bin": {
         "parser": "bin/babel-parser.js"
       },
@@ -1276,9 +1276,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-modules-systemjs": {
-      "version": "7.18.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.4.tgz",
-      "integrity": "sha512-lH2UaQaHVOAeYrUUuZ8i38o76J/FnO8vu21OE+tD1MyP9lxdZoSfz+pDbWkq46GogUrdrMz3tiz/FYGB+bVThg==",
+      "version": "7.18.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.5.tgz",
+      "integrity": "sha512-SEewrhPpcqMF1V7DhnEbhVJLrC+nnYfe1E0piZMZXBpxi9WvZqWGwpsk7JYP7wPWeqaBh4gyKlBhHJu3uz5g4Q==",
       "dependencies": {
         "@babel/helper-hoist-variables": "^7.16.7",
         "@babel/helper-module-transforms": "^7.18.0",
@@ -1324,9 +1324,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-new-target": {
-      "version": "7.17.12",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.17.12.tgz",
-      "integrity": "sha512-CaOtzk2fDYisbjAD4Sd1MTKGVIpRtx9bWLyj24Y/k6p4s4gQ3CqDGJauFJxt8M/LEx003d0i3klVqnN73qvK3w==",
+      "version": "7.18.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.5.tgz",
+      "integrity": "sha512-TuRL5uGW4KXU6OsRj+mLp9BM7pO8e7SGNTEokQRRxHFkXYMFiy2jlKSZPFtI/mKORDzciH+hneskcSOp0gU8hg==",
       "dependencies": {
         "@babel/helper-plugin-utils": "^7.17.12"
       },
@@ -1485,9 +1485,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-runtime": {
-      "version": "7.18.2",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.2.tgz",
-      "integrity": "sha512-mr1ufuRMfS52ttq+1G1PD8OJNqgcTFjq3hwn8SZ5n1x1pBhi0E36rYMdTK0TsKtApJ4lDEdfXJwtGobQMHSMPg==",
+      "version": "7.18.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.5.tgz",
+      "integrity": "sha512-Q17hHxXr2fplrE+5BSC1j1Fo5cOA8YeP8XW3/1paI8MzF/faZGh0MaH1KC4jLAvqLPamQWHB5/B7KqSLY1kuHA==",
       "dependencies": {
         "@babel/helper-module-imports": "^7.16.7",
         "@babel/helper-plugin-utils": "^7.17.12",
@@ -1794,9 +1794,9 @@
       }
     },
     "node_modules/@babel/traverse": {
-      "version": "7.18.2",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.2.tgz",
-      "integrity": "sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==",
+      "version": "7.18.5",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.5.tgz",
+      "integrity": "sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==",
       "dependencies": {
         "@babel/code-frame": "^7.16.7",
         "@babel/generator": "^7.18.2",
@@ -1804,8 +1804,8 @@
         "@babel/helper-function-name": "^7.17.9",
         "@babel/helper-hoist-variables": "^7.16.7",
         "@babel/helper-split-export-declaration": "^7.16.7",
-        "@babel/parser": "^7.18.0",
-        "@babel/types": "^7.18.2",
+        "@babel/parser": "^7.18.5",
+        "@babel/types": "^7.18.4",
         "debug": "^4.1.0",
         "globals": "^11.1.0"
       },
@@ -3007,14 +3007,14 @@
       "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A=="
     },
     "node_modules/@mui/base": {
-      "version": "5.0.0-alpha.84",
-      "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.84.tgz",
-      "integrity": "sha512-uDx+wGVytS+ZHiWHyzUyijY83GSIXJpzSJ0PGc/8/s+8nBzeHvaPKrAyJz15ASLr52hYRA6PQGqn0eRAsB7syQ==",
+      "version": "5.0.0-alpha.85",
+      "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.85.tgz",
+      "integrity": "sha512-ONlQJOmQrxmR+pYF9AqH69FOG4ofwzVzNltwb2xKAQIW3VbsNZahcHIpzhFd70W6EIU+QHzB9TzamSM+Fg/U7w==",
       "dependencies": {
         "@babel/runtime": "^7.17.2",
         "@emotion/is-prop-valid": "^1.1.2",
-        "@mui/types": "^7.1.3",
-        "@mui/utils": "^5.8.0",
+        "@mui/types": "^7.1.4",
+        "@mui/utils": "^5.8.4",
         "@popperjs/core": "^2.11.5",
         "clsx": "^1.1.1",
         "prop-types": "^15.8.1",
@@ -3039,9 +3039,9 @@
       }
     },
     "node_modules/@mui/icons-material": {
-      "version": "5.8.3",
-      "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.8.3.tgz",
-      "integrity": "sha512-dAdhimSLKOV0Q8FR7AYGEaCrTUh9OV7zU4Ueo5REoUt4cC3Vy+UBKDjZk66x5ezaYb63AFgQIFwtnZj3B/QDbQ==",
+      "version": "5.8.4",
+      "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.8.4.tgz",
+      "integrity": "sha512-9Z/vyj2szvEhGWDvb+gG875bOGm8b8rlHBKOD1+nA3PcgC3fV6W1AU6pfOorPeBfH2X4mb9Boe97vHvaSndQvA==",
       "dependencies": {
         "@babel/runtime": "^7.17.2"
       },
@@ -3064,19 +3064,18 @@
       }
     },
     "node_modules/@mui/material": {
-      "version": "5.8.3",
-      "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.8.3.tgz",
-      "integrity": "sha512-8UecY/W9SMtEZm5PMCUcMbujajVP6fobu0BgBPiIWwwWRblZVEzqprY6v1P2me7qCyrve4L4V/rqAKPKhVHOSg==",
+      "version": "5.8.4",
+      "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.8.4.tgz",
+      "integrity": "sha512-KlOJS1JGhwuhdoF4fulmz41h/YxyMdZSc+ncz+HAah0GKn8ovAs5774f1w0lIasxbtI1Ziunwvmnu9PvvUKdMw==",
       "dependencies": {
         "@babel/runtime": "^7.17.2",
-        "@mui/base": "5.0.0-alpha.84",
-        "@mui/system": "^5.8.3",
-        "@mui/types": "^7.1.3",
-        "@mui/utils": "^5.8.0",
+        "@mui/base": "5.0.0-alpha.85",
+        "@mui/system": "^5.8.4",
+        "@mui/types": "^7.1.4",
+        "@mui/utils": "^5.8.4",
         "@types/react-transition-group": "^4.4.4",
         "clsx": "^1.1.1",
         "csstype": "^3.1.0",
-        "hoist-non-react-statics": "^3.3.2",
         "prop-types": "^15.8.1",
         "react-is": "^17.0.2",
         "react-transition-group": "^4.4.2"
@@ -3108,12 +3107,12 @@
       }
     },
     "node_modules/@mui/private-theming": {
-      "version": "5.8.0",
-      "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.8.0.tgz",
-      "integrity": "sha512-MjRAneTmCKLR9u2S4jtjLUe6gpHxlbb4g2bqpDJ2PdwlvwsWIUzbc/gVB4dvccljXeWxr5G2M/Co2blXisvFIw==",
+      "version": "5.8.4",
+      "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.8.4.tgz",
+      "integrity": "sha512-3Lp0VAEjtQygJ70MWEyHkKvg327O6YoBH6ZNEy6fIsrK6gmRIj+YrlvJ7LQCbowY+qDGnbdMrTBd1hfThlI8lg==",
       "dependencies": {
         "@babel/runtime": "^7.17.2",
-        "@mui/utils": "^5.8.0",
+        "@mui/utils": "^5.8.4",
         "prop-types": "^15.8.1"
       },
       "engines": {
@@ -3164,15 +3163,15 @@
       }
     },
     "node_modules/@mui/system": {
-      "version": "5.8.3",
-      "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.8.3.tgz",
-      "integrity": "sha512-/tyGQcYqZT0nl98qV9XnGiedTO+V7VHc28k4POfhMJNedB1CRrwWRm767DeEdc5f/8CU2See3WD16ikP6pYiOA==",
+      "version": "5.8.4",
+      "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.8.4.tgz",
+      "integrity": "sha512-eeYZXlOn4p+tYwqqDlci6wW4knJ68aGx5A24YU9ubYZ5o0IwveoNP3LC9sHAMxigk/mUTqL4bpSMJ2HbTn2aQg==",
       "dependencies": {
         "@babel/runtime": "^7.17.2",
-        "@mui/private-theming": "^5.8.0",
+        "@mui/private-theming": "^5.8.4",
         "@mui/styled-engine": "^5.8.0",
-        "@mui/types": "^7.1.3",
-        "@mui/utils": "^5.8.0",
+        "@mui/types": "^7.1.4",
+        "@mui/utils": "^5.8.4",
         "clsx": "^1.1.1",
         "csstype": "^3.1.0",
         "prop-types": "^15.8.1"
@@ -3203,9 +3202,9 @@
       }
     },
     "node_modules/@mui/types": {
-      "version": "7.1.3",
-      "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.1.3.tgz",
-      "integrity": "sha512-DDF0UhMBo4Uezlk+6QxrlDbchF79XG6Zs0zIewlR4c0Dt6GKVFfUtzPtHCH1tTbcSlq/L2bGEdiaoHBJ9Y1gSA==",
+      "version": "7.1.4",
+      "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.1.4.tgz",
+      "integrity": "sha512-uveM3byMbthO+6tXZ1n2zm0W3uJCQYtwt/v5zV5I77v2v18u0ITkb8xwhsDD2i3V2Kye7SaNR6FFJ6lMuY/WqQ==",
       "peerDependencies": {
         "@types/react": "*"
       },
@@ -3216,9 +3215,9 @@
       }
     },
     "node_modules/@mui/utils": {
-      "version": "5.8.0",
-      "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.8.0.tgz",
-      "integrity": "sha512-7LgUtCvz78676iC0wpTH7HizMdCrTphhBmRWimIMFrp5Ph6JbDFVuKS1CwYnWWxRyYKL0QzXrDL0lptAU90EXg==",
+      "version": "5.8.4",
+      "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.8.4.tgz",
+      "integrity": "sha512-BHYErfrjqqh76KaDAm8wZlhEip1Uj7Cmco65NcsF3BWrAl3FWngACpaPZeEbTgmaEwyWAQEE6LZhsmy43hfyqQ==",
       "dependencies": {
         "@babel/runtime": "^7.17.2",
         "@types/prop-types": "^15.7.5",
@@ -3805,9 +3804,9 @@
       }
     },
     "node_modules/@types/express-serve-static-core": {
-      "version": "4.17.28",
-      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz",
-      "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==",
+      "version": "4.17.29",
+      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.29.tgz",
+      "integrity": "sha512-uMd++6dMKS32EOuw1Uli3e3BPgdLIXmezcfHv7N4c1s3gkhikBplORPpMq3fuWkxncZN1reb16d5n8yhQ80x7Q==",
       "dependencies": {
         "@types/node": "*",
         "@types/qs": "*",
@@ -3872,9 +3871,9 @@
       "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw=="
     },
     "node_modules/@types/node": {
-      "version": "17.0.42",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.42.tgz",
-      "integrity": "sha512-Q5BPGyGKcvQgAMbsr7qEGN/kIPN6zZecYYABeTDBizOsau+2NMdSVTar9UQw21A2+JyA2KRNDYaYrPB0Rpk2oQ=="
+      "version": "18.0.0",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.0.tgz",
+      "integrity": "sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA=="
     },
     "node_modules/@types/parse-json": {
       "version": "4.0.0",
@@ -3907,9 +3906,9 @@
       "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
     },
     "node_modules/@types/react": {
-      "version": "18.0.12",
-      "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.12.tgz",
-      "integrity": "sha512-duF1OTASSBQtcigUvhuiTB1Ya3OvSy+xORCiEf20H0P0lzx+/KeVsA99U5UjLXSbyo1DRJDlLKqTeM1ngosqtg==",
+      "version": "18.0.13",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.13.tgz",
+      "integrity": "sha512-psqptIYQxGUFuGYwP3KCFVtPTkMpIcrqFmtKblWEUQhLuYLpHBwJkXhjp6eHfDM5IbyskY4x7qQpLedEsPkHlA==",
       "dependencies": {
         "@types/prop-types": "*",
         "@types/scheduler": "*",
@@ -4007,13 +4006,13 @@
       "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA=="
     },
     "node_modules/@typescript-eslint/eslint-plugin": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.1.tgz",
-      "integrity": "sha512-6dM5NKT57ZduNnJfpY81Phe9nc9wolnMCnknb1im6brWi1RYv84nbMS3olJa27B6+irUVV1X/Wb+Am0FjJdGFw==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.28.0.tgz",
+      "integrity": "sha512-DXVU6Cg29H2M6EybqSg2A+x8DgO9TCUBRp4QEXQHJceLS7ogVDP0g3Lkg/SZCqcvkAP/RruuQqK0gdlkgmhSUA==",
       "dependencies": {
-        "@typescript-eslint/scope-manager": "5.27.1",
-        "@typescript-eslint/type-utils": "5.27.1",
-        "@typescript-eslint/utils": "5.27.1",
+        "@typescript-eslint/scope-manager": "5.28.0",
+        "@typescript-eslint/type-utils": "5.28.0",
+        "@typescript-eslint/utils": "5.28.0",
         "debug": "^4.3.4",
         "functional-red-black-tree": "^1.0.1",
         "ignore": "^5.2.0",
@@ -4053,11 +4052,11 @@
       }
     },
     "node_modules/@typescript-eslint/experimental-utils": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.27.1.tgz",
-      "integrity": "sha512-Vd8uewIixGP93sEnmTRIH6jHZYRQRkGPDPpapACMvitJKX8335VHNyqKTE+mZ+m3E2c5VznTZfSsSsS5IF7vUA==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.28.0.tgz",
+      "integrity": "sha512-pPQ1Ng4qezQijXBBfYlogcOPnMs1q14l8C4fWJJ4PnFla4MA2b2oBfdkf02r1lNak2tpBVNJxvey9oWlPQWc4w==",
       "dependencies": {
-        "@typescript-eslint/utils": "5.27.1"
+        "@typescript-eslint/utils": "5.28.0"
       },
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -4071,13 +4070,13 @@
       }
     },
     "node_modules/@typescript-eslint/parser": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.27.1.tgz",
-      "integrity": "sha512-7Va2ZOkHi5NP+AZwb5ReLgNF6nWLGTeUJfxdkVUAPPSaAdbWNnFZzLZ4EGGmmiCTg+AwlbE1KyUYTBglosSLHQ==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.28.0.tgz",
+      "integrity": "sha512-ekqoNRNK1lAcKhZESN/PdpVsWbP9jtiNqzFWkp/yAUdZvJalw2heCYuqRmM5eUJSIYEkgq5sGOjq+ZqsLMjtRA==",
       "dependencies": {
-        "@typescript-eslint/scope-manager": "5.27.1",
-        "@typescript-eslint/types": "5.27.1",
-        "@typescript-eslint/typescript-estree": "5.27.1",
+        "@typescript-eslint/scope-manager": "5.28.0",
+        "@typescript-eslint/types": "5.28.0",
+        "@typescript-eslint/typescript-estree": "5.28.0",
         "debug": "^4.3.4"
       },
       "engines": {
@@ -4097,12 +4096,12 @@
       }
     },
     "node_modules/@typescript-eslint/scope-manager": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.27.1.tgz",
-      "integrity": "sha512-fQEOSa/QroWE6fAEg+bJxtRZJTH8NTskggybogHt4H9Da8zd4cJji76gA5SBlR0MgtwF7rebxTbDKB49YUCpAg==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.28.0.tgz",
+      "integrity": "sha512-LeBLTqF/he1Z+boRhSqnso6YrzcKMTQ8bO/YKEe+6+O/JGof9M0g3IJlIsqfrK/6K03MlFIlycbf1uQR1IjE+w==",
       "dependencies": {
-        "@typescript-eslint/types": "5.27.1",
-        "@typescript-eslint/visitor-keys": "5.27.1"
+        "@typescript-eslint/types": "5.28.0",
+        "@typescript-eslint/visitor-keys": "5.28.0"
       },
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -4113,11 +4112,11 @@
       }
     },
     "node_modules/@typescript-eslint/type-utils": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.27.1.tgz",
-      "integrity": "sha512-+UC1vVUWaDHRnC2cQrCJ4QtVjpjjCgjNFpg8b03nERmkHv9JV9X5M19D7UFMd+/G7T/sgFwX2pGmWK38rqyvXw==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.28.0.tgz",
+      "integrity": "sha512-SyKjKh4CXPglueyC6ceAFytjYWMoPHMswPQae236zqe1YbhvCVQyIawesYywGiu98L9DwrxsBN69vGIVxJ4mQQ==",
       "dependencies": {
-        "@typescript-eslint/utils": "5.27.1",
+        "@typescript-eslint/utils": "5.28.0",
         "debug": "^4.3.4",
         "tsutils": "^3.21.0"
       },
@@ -4138,9 +4137,9 @@
       }
     },
     "node_modules/@typescript-eslint/types": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.27.1.tgz",
-      "integrity": "sha512-LgogNVkBhCTZU/m8XgEYIWICD6m4dmEDbKXESCbqOXfKZxRKeqpiJXQIErv66sdopRKZPo5l32ymNqibYEH/xg==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.28.0.tgz",
+      "integrity": "sha512-2OOm8ZTOQxqkPbf+DAo8oc16sDlVR5owgJfKheBkxBKg1vAfw2JsSofH9+16VPlN9PWtv8Wzhklkqw3k/zCVxA==",
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
       },
@@ -4150,12 +4149,12 @@
       }
     },
     "node_modules/@typescript-eslint/typescript-estree": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.1.tgz",
-      "integrity": "sha512-DnZvvq3TAJ5ke+hk0LklvxwYsnXpRdqUY5gaVS0D4raKtbznPz71UJGnPTHEFo0GDxqLOLdMkkmVZjSpET1hFw==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.28.0.tgz",
+      "integrity": "sha512-9GX+GfpV+F4hdTtYc6OV9ZkyYilGXPmQpm6AThInpBmKJEyRSIjORJd1G9+bknb7OTFYL+Vd4FBJAO6T78OVqA==",
       "dependencies": {
-        "@typescript-eslint/types": "5.27.1",
-        "@typescript-eslint/visitor-keys": "5.27.1",
+        "@typescript-eslint/types": "5.28.0",
+        "@typescript-eslint/visitor-keys": "5.28.0",
         "debug": "^4.3.4",
         "globby": "^11.1.0",
         "is-glob": "^4.0.3",
@@ -4190,14 +4189,14 @@
       }
     },
     "node_modules/@typescript-eslint/utils": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.27.1.tgz",
-      "integrity": "sha512-mZ9WEn1ZLDaVrhRaYgzbkXBkTPghPFsup8zDbbsYTxC5OmqrFE7skkKS/sraVsLP3TcT3Ki5CSyEFBRkLH/H/w==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.28.0.tgz",
+      "integrity": "sha512-E60N5L0fjv7iPJV3UGc4EC+A3Lcj4jle9zzR0gW7vXhflO7/J29kwiTGITA2RlrmPokKiZbBy2DgaclCaEUs6g==",
       "dependencies": {
         "@types/json-schema": "^7.0.9",
-        "@typescript-eslint/scope-manager": "5.27.1",
-        "@typescript-eslint/types": "5.27.1",
-        "@typescript-eslint/typescript-estree": "5.27.1",
+        "@typescript-eslint/scope-manager": "5.28.0",
+        "@typescript-eslint/types": "5.28.0",
+        "@typescript-eslint/typescript-estree": "5.28.0",
         "eslint-scope": "^5.1.1",
         "eslint-utils": "^3.0.0"
       },
@@ -4233,11 +4232,11 @@
       }
     },
     "node_modules/@typescript-eslint/visitor-keys": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.1.tgz",
-      "integrity": "sha512-xYs6ffo01nhdJgPieyk7HAOpjhTsx7r/oB9LWEhwAXgwn33tkr+W8DI2ChboqhZlC4q3TC6geDYPoiX8ROqyOQ==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.28.0.tgz",
+      "integrity": "sha512-BtfP1vCor8cWacovzzPFOoeW4kBQxzmhxGoOpt0v1SFvG+nJ0cWaVdJk7cky1ArTcFHHKNIxyo2LLr3oNkSuXA==",
       "dependencies": {
-        "@typescript-eslint/types": "5.27.1",
+        "@typescript-eslint/types": "5.28.0",
         "eslint-visitor-keys": "^3.3.0"
       },
       "engines": {
@@ -5375,9 +5374,9 @@
       }
     },
     "node_modules/caniuse-lite": {
-      "version": "1.0.30001352",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001352.tgz",
-      "integrity": "sha512-GUgH8w6YergqPQDGWhJGt8GDRnY0L/iJVQcU3eJ46GYf52R8tk0Wxp0PymuFVZboJYXGiCqwozAYZNRjVj6IcA==",
+      "version": "1.0.30001355",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001355.tgz",
+      "integrity": "sha512-Sd6pjJHF27LzCB7pT7qs+kuX2ndurzCzkpJl6Qct7LPSZ9jn0bkOA8mdgMgmqnQAWLVOOGjLpc+66V57eLtb1g==",
       "funding": [
         {
           "type": "opencollective",
@@ -5485,9 +5484,9 @@
       }
     },
     "node_modules/ci-info": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.1.tgz",
-      "integrity": "sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg=="
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz",
+      "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg=="
     },
     "node_modules/cjs-module-lexer": {
       "version": "1.2.2",
@@ -5577,9 +5576,9 @@
       "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ=="
     },
     "node_modules/colorette": {
-      "version": "2.0.17",
-      "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.17.tgz",
-      "integrity": "sha512-hJo+3Bkn0NCHybn9Tu35fIeoOKGOk5OCC32y4Hz2It+qlCO2Q3DeQ1hRn/tDDMQKRYUEzqsl7jbF6dYKjlE60g=="
+      "version": "2.0.19",
+      "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz",
+      "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ=="
     },
     "node_modules/combined-stream": {
       "version": "1.0.8",
@@ -5737,9 +5736,9 @@
       "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
     },
     "node_modules/core-js": {
-      "version": "3.22.8",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.8.tgz",
-      "integrity": "sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA==",
+      "version": "3.23.1",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.23.1.tgz",
+      "integrity": "sha512-wfMYHWi1WQjpgZNC9kAlN4ut04TM9fUTdi7CqIoTVM7yaiOUQTklOzfb+oWH3r9edQcT3F887swuVmxrV+CC8w==",
       "hasInstallScript": true,
       "funding": {
         "type": "opencollective",
@@ -5747,11 +5746,11 @@
       }
     },
     "node_modules/core-js-compat": {
-      "version": "3.22.8",
-      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.22.8.tgz",
-      "integrity": "sha512-pQnwg4xtuvc2Bs/5zYQPaEYYSuTxsF7LBWF0SvnVhthZo/Qe+rJpcEekrdNK5DWwDJ0gv0oI9NNX5Mppdy0ctg==",
+      "version": "3.23.1",
+      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.1.tgz",
+      "integrity": "sha512-KeYrEc8t6FJsKYB2qnDwRHWaC0cJNaqlHfCpMe5q3j/W1nje3moib/txNklddLPCtGb+etcBIyJ8zuMa/LN5/A==",
       "dependencies": {
-        "browserslist": "^4.20.3",
+        "browserslist": "^4.20.4",
         "semver": "7.0.0"
       },
       "funding": {
@@ -5768,9 +5767,9 @@
       }
     },
     "node_modules/core-js-pure": {
-      "version": "3.22.8",
-      "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.22.8.tgz",
-      "integrity": "sha512-bOxbZIy9S5n4OVH63XaLVXZ49QKicjowDx/UELyJ68vxfCRpYsbyh/WNZNfEfAk+ekA8vSjt+gCDpvh672bc3w==",
+      "version": "3.23.1",
+      "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.23.1.tgz",
+      "integrity": "sha512-3qNgf6TqI3U1uhuSYRzJZGfFd4T+YlbyVPl+jgRiKjdZopvG4keZQwWZDAWpu1UH9nCgTpUzIV3GFawC7cJsqg==",
       "hasInstallScript": true,
       "funding": {
         "type": "opencollective",
@@ -6480,9 +6479,9 @@
       "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg=="
     },
     "node_modules/dns-packet": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.3.1.tgz",
-      "integrity": "sha512-spBwIj0TK0Ey3666GwIdWVfUpLyubpU53BTCu8iPn4r4oXd9O14Hjg3EHw3ts2oed77/SeckunUYCyRlSngqHw==",
+      "version": "5.4.0",
+      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.4.0.tgz",
+      "integrity": "sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==",
       "dependencies": {
         "@leichtgewicht/ip-codec": "^2.0.1"
       },
@@ -6635,9 +6634,9 @@
       }
     },
     "node_modules/electron-to-chromium": {
-      "version": "1.4.152",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.152.tgz",
-      "integrity": "sha512-jk4Ju5SGZAQQJ1iI4Rgru7dDlvkQPLpNPWH9gIZmwCD4YteA5Bbk1xPcPDUf5jUYs3e1e80RXdi8XgKQZaigeg=="
+      "version": "1.4.158",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.158.tgz",
+      "integrity": "sha512-gppO3/+Y6sP432HtvwvuU8S+YYYLH4PmAYvQwqUtt9HDOmEsBwQfLnK9T8+1NIKwAS1BEygIjTaATC4H5EzvxQ=="
     },
     "node_modules/emittery": {
       "version": "0.8.1",
@@ -7197,9 +7196,9 @@
       }
     },
     "node_modules/eslint-plugin-react-hooks": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.5.0.tgz",
-      "integrity": "sha512-8k1gRt7D7h03kd+SAAlzXkQwWK22BnK6GKZG+FJA6BAGy22CFvl8kCIXKpVux0cCxMWDQUPqSok0LKaZ0aOcCw==",
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
+      "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
       "engines": {
         "node": ">=10"
       },
@@ -8653,9 +8652,9 @@
       }
     },
     "node_modules/i18next": {
-      "version": "21.8.9",
-      "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.8.9.tgz",
-      "integrity": "sha512-PY9a/8ADVmnju1tETeglbbVQi+nM5pcJQWm9kvKMTE3GPgHHtpDsHy5HQ/hccz2/xtW7j3vuso23JdQSH0EttA==",
+      "version": "21.8.10",
+      "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.8.10.tgz",
+      "integrity": "sha512-7xRb6y4QlSqZRZ3uA5BIEsLuZpmxpzHLizQyKjDDThOcvdfgICOX7aFoBnh4BSWcLtJamTqSweaOuK22A2xqkA==",
       "funding": [
         {
           "type": "individual",
@@ -8737,9 +8736,9 @@
       }
     },
     "node_modules/immer": {
-      "version": "9.0.14",
-      "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.14.tgz",
-      "integrity": "sha512-ubBeqQutOSLIFCUBN03jGeOS6a3DoYlSYwYJTa+gSKEZKU5redJIqkIdZ3JVv/4RZpfcXdAWH5zCNLWPRv2WDw==",
+      "version": "9.0.15",
+      "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz",
+      "integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==",
       "funding": {
         "type": "opencollective",
         "url": "https://opencollective.com/immer"
@@ -11003,9 +11002,9 @@
       }
     },
     "node_modules/jest-watch-typeahead/node_modules/react-is": {
-      "version": "18.1.0",
-      "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz",
-      "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg=="
+      "version": "18.2.0",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+      "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
     },
     "node_modules/jest-watch-typeahead/node_modules/slash": {
       "version": "4.0.0",
@@ -11653,9 +11652,9 @@
       }
     },
     "node_modules/mini-css-extract-plugin": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.0.tgz",
-      "integrity": "sha512-ndG8nxCEnAemsg4FSgS+yNyHKgkTB4nPKqCOgh65j3/30qqC5RaSQQXMm++Y6sb6E1zRSxPkztj9fqxhS1Eo6w==",
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz",
+      "integrity": "sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg==",
       "dependencies": {
         "schema-utils": "^4.0.0"
       },
@@ -13810,9 +13809,9 @@
       }
     },
     "node_modules/react": {
-      "version": "18.1.0",
-      "resolved": "https://registry.npmjs.org/react/-/react-18.1.0.tgz",
-      "integrity": "sha512-4oL8ivCz5ZEPyclFQXaNksK3adutVS8l2xzZU0cqEFrE9Sb7fC0EFK5uEk74wIreL1DERyjvsU915j1pcT2uEQ==",
+      "version": "18.2.0",
+      "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
+      "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
       "dependencies": {
         "loose-envify": "^1.1.0"
       },
@@ -13943,15 +13942,15 @@
       }
     },
     "node_modules/react-dom": {
-      "version": "18.1.0",
-      "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.1.0.tgz",
-      "integrity": "sha512-fU1Txz7Budmvamp7bshe4Zi32d0ll7ect+ccxNu9FlObT605GOEB8BfO4tmRJ39R5Zj831VCpvQ05QPBW5yb+w==",
+      "version": "18.2.0",
+      "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
+      "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
       "dependencies": {
         "loose-envify": "^1.1.0",
-        "scheduler": "^0.22.0"
+        "scheduler": "^0.23.0"
       },
       "peerDependencies": {
-        "react": "^18.1.0"
+        "react": "^18.2.0"
       }
     },
     "node_modules/react-error-overlay": {
@@ -13960,9 +13959,9 @@
       "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
     },
     "node_modules/react-i18next": {
-      "version": "11.17.1",
-      "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.17.1.tgz",
-      "integrity": "sha512-4H4fK9vWsQtPP0iAdqzGfdPKLaSXpCjuh1xaGsejX/CO8tx8zCnrOnlQhMgrJf+OlUfzth5YaDPXYGp3RHxV1g==",
+      "version": "11.17.2",
+      "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.17.2.tgz",
+      "integrity": "sha512-/HG4XSResWDY450cFmoUqLgCYDu8VYMFISGcMnZlxRSV05naj3+F7DoebwnPu6z/akA3Wd0Xe7KGTYdywL9z9g==",
       "dependencies": {
         "@babel/runtime": "^7.14.5",
         "html-escaper": "^2.0.2",
@@ -14623,9 +14622,9 @@
       }
     },
     "node_modules/scheduler": {
-      "version": "0.22.0",
-      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.22.0.tgz",
-      "integrity": "sha512-6QAm1BgQI88NPYymgGQLCZgvep4FyePDWFpXVK+zNSUgHwlqpJy8VEh8Et0KxTACS4VWwMousBElAZOH9nkkoQ==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
+      "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
       "dependencies": {
         "loose-envify": "^1.1.0"
       }
@@ -15386,11 +15385,11 @@
       "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="
     },
     "node_modules/tailwindcss": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.2.tgz",
-      "integrity": "sha512-yJ6L5s1U5AeS5g7HHy212zdQfjwD426FBfm59pet/JsyneuZuD4C2W7PpJEg4ppisiB21uLqtNagv8KXury3+Q==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.3.tgz",
+      "integrity": "sha512-PRJNYdSIthrb8hjmAyymEyEN8Yo61TMXpzyFUpxULeeyRn3Y3gpvuw6FlRTKrJvK7thSGKRnhT36VovVx4WeMA==",
       "dependencies": {
-        "arg": "^5.0.1",
+        "arg": "^5.0.2",
         "chokidar": "^3.5.3",
         "color-name": "^1.1.4",
         "detective": "^5.2.1",
@@ -16866,14 +16865,14 @@
       }
     },
     "@babel/compat-data": {
-      "version": "7.17.10",
-      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz",
-      "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw=="
+      "version": "7.18.5",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.5.tgz",
+      "integrity": "sha512-BxhE40PVCBxVEJsSBhB6UWyAuqJRxGsAw8BdHMJ3AKGydcwuWW4kOO3HmqBQAdcq/OP+/DlTVxLvsCzRTnZuGg=="
     },
     "@babel/core": {
-      "version": "7.18.2",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.2.tgz",
-      "integrity": "sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==",
+      "version": "7.18.5",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.5.tgz",
+      "integrity": "sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ==",
       "requires": {
         "@ampproject/remapping": "^2.1.0",
         "@babel/code-frame": "^7.16.7",
@@ -16881,10 +16880,10 @@
         "@babel/helper-compilation-targets": "^7.18.2",
         "@babel/helper-module-transforms": "^7.18.0",
         "@babel/helpers": "^7.18.2",
-        "@babel/parser": "^7.18.0",
+        "@babel/parser": "^7.18.5",
         "@babel/template": "^7.16.7",
-        "@babel/traverse": "^7.18.2",
-        "@babel/types": "^7.18.2",
+        "@babel/traverse": "^7.18.5",
+        "@babel/types": "^7.18.4",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.2",
@@ -17173,9 +17172,9 @@
       }
     },
     "@babel/parser": {
-      "version": "7.18.4",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.4.tgz",
-      "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow=="
+      "version": "7.18.5",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.5.tgz",
+      "integrity": "sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw=="
     },
     "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
       "version": "7.17.12",
@@ -17675,9 +17674,9 @@
       }
     },
     "@babel/plugin-transform-modules-systemjs": {
-      "version": "7.18.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.4.tgz",
-      "integrity": "sha512-lH2UaQaHVOAeYrUUuZ8i38o76J/FnO8vu21OE+tD1MyP9lxdZoSfz+pDbWkq46GogUrdrMz3tiz/FYGB+bVThg==",
+      "version": "7.18.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.5.tgz",
+      "integrity": "sha512-SEewrhPpcqMF1V7DhnEbhVJLrC+nnYfe1E0piZMZXBpxi9WvZqWGwpsk7JYP7wPWeqaBh4gyKlBhHJu3uz5g4Q==",
       "requires": {
         "@babel/helper-hoist-variables": "^7.16.7",
         "@babel/helper-module-transforms": "^7.18.0",
@@ -17705,9 +17704,9 @@
       }
     },
     "@babel/plugin-transform-new-target": {
-      "version": "7.17.12",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.17.12.tgz",
-      "integrity": "sha512-CaOtzk2fDYisbjAD4Sd1MTKGVIpRtx9bWLyj24Y/k6p4s4gQ3CqDGJauFJxt8M/LEx003d0i3klVqnN73qvK3w==",
+      "version": "7.18.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.5.tgz",
+      "integrity": "sha512-TuRL5uGW4KXU6OsRj+mLp9BM7pO8e7SGNTEokQRRxHFkXYMFiy2jlKSZPFtI/mKORDzciH+hneskcSOp0gU8hg==",
       "requires": {
         "@babel/helper-plugin-utils": "^7.17.12"
       }
@@ -17800,9 +17799,9 @@
       }
     },
     "@babel/plugin-transform-runtime": {
-      "version": "7.18.2",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.2.tgz",
-      "integrity": "sha512-mr1ufuRMfS52ttq+1G1PD8OJNqgcTFjq3hwn8SZ5n1x1pBhi0E36rYMdTK0TsKtApJ4lDEdfXJwtGobQMHSMPg==",
+      "version": "7.18.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.5.tgz",
+      "integrity": "sha512-Q17hHxXr2fplrE+5BSC1j1Fo5cOA8YeP8XW3/1paI8MzF/faZGh0MaH1KC4jLAvqLPamQWHB5/B7KqSLY1kuHA==",
       "requires": {
         "@babel/helper-module-imports": "^7.16.7",
         "@babel/helper-plugin-utils": "^7.17.12",
@@ -18025,9 +18024,9 @@
       }
     },
     "@babel/traverse": {
-      "version": "7.18.2",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.2.tgz",
-      "integrity": "sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==",
+      "version": "7.18.5",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.5.tgz",
+      "integrity": "sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==",
       "requires": {
         "@babel/code-frame": "^7.16.7",
         "@babel/generator": "^7.18.2",
@@ -18035,8 +18034,8 @@
         "@babel/helper-function-name": "^7.17.9",
         "@babel/helper-hoist-variables": "^7.16.7",
         "@babel/helper-split-export-declaration": "^7.16.7",
-        "@babel/parser": "^7.18.0",
-        "@babel/types": "^7.18.2",
+        "@babel/parser": "^7.18.5",
+        "@babel/types": "^7.18.4",
         "debug": "^4.1.0",
         "globals": "^11.1.0"
       }
@@ -18883,14 +18882,14 @@
       "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A=="
     },
     "@mui/base": {
-      "version": "5.0.0-alpha.84",
-      "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.84.tgz",
-      "integrity": "sha512-uDx+wGVytS+ZHiWHyzUyijY83GSIXJpzSJ0PGc/8/s+8nBzeHvaPKrAyJz15ASLr52hYRA6PQGqn0eRAsB7syQ==",
+      "version": "5.0.0-alpha.85",
+      "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.85.tgz",
+      "integrity": "sha512-ONlQJOmQrxmR+pYF9AqH69FOG4ofwzVzNltwb2xKAQIW3VbsNZahcHIpzhFd70W6EIU+QHzB9TzamSM+Fg/U7w==",
       "requires": {
         "@babel/runtime": "^7.17.2",
         "@emotion/is-prop-valid": "^1.1.2",
-        "@mui/types": "^7.1.3",
-        "@mui/utils": "^5.8.0",
+        "@mui/types": "^7.1.4",
+        "@mui/utils": "^5.8.4",
         "@popperjs/core": "^2.11.5",
         "clsx": "^1.1.1",
         "prop-types": "^15.8.1",
@@ -18898,39 +18897,38 @@
       }
     },
     "@mui/icons-material": {
-      "version": "5.8.3",
-      "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.8.3.tgz",
-      "integrity": "sha512-dAdhimSLKOV0Q8FR7AYGEaCrTUh9OV7zU4Ueo5REoUt4cC3Vy+UBKDjZk66x5ezaYb63AFgQIFwtnZj3B/QDbQ==",
+      "version": "5.8.4",
+      "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.8.4.tgz",
+      "integrity": "sha512-9Z/vyj2szvEhGWDvb+gG875bOGm8b8rlHBKOD1+nA3PcgC3fV6W1AU6pfOorPeBfH2X4mb9Boe97vHvaSndQvA==",
       "requires": {
         "@babel/runtime": "^7.17.2"
       }
     },
     "@mui/material": {
-      "version": "5.8.3",
-      "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.8.3.tgz",
-      "integrity": "sha512-8UecY/W9SMtEZm5PMCUcMbujajVP6fobu0BgBPiIWwwWRblZVEzqprY6v1P2me7qCyrve4L4V/rqAKPKhVHOSg==",
+      "version": "5.8.4",
+      "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.8.4.tgz",
+      "integrity": "sha512-KlOJS1JGhwuhdoF4fulmz41h/YxyMdZSc+ncz+HAah0GKn8ovAs5774f1w0lIasxbtI1Ziunwvmnu9PvvUKdMw==",
       "requires": {
         "@babel/runtime": "^7.17.2",
-        "@mui/base": "5.0.0-alpha.84",
-        "@mui/system": "^5.8.3",
-        "@mui/types": "^7.1.3",
-        "@mui/utils": "^5.8.0",
+        "@mui/base": "5.0.0-alpha.85",
+        "@mui/system": "^5.8.4",
+        "@mui/types": "^7.1.4",
+        "@mui/utils": "^5.8.4",
         "@types/react-transition-group": "^4.4.4",
         "clsx": "^1.1.1",
         "csstype": "^3.1.0",
-        "hoist-non-react-statics": "^3.3.2",
         "prop-types": "^15.8.1",
         "react-is": "^17.0.2",
         "react-transition-group": "^4.4.2"
       }
     },
     "@mui/private-theming": {
-      "version": "5.8.0",
-      "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.8.0.tgz",
-      "integrity": "sha512-MjRAneTmCKLR9u2S4jtjLUe6gpHxlbb4g2bqpDJ2PdwlvwsWIUzbc/gVB4dvccljXeWxr5G2M/Co2blXisvFIw==",
+      "version": "5.8.4",
+      "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.8.4.tgz",
+      "integrity": "sha512-3Lp0VAEjtQygJ70MWEyHkKvg327O6YoBH6ZNEy6fIsrK6gmRIj+YrlvJ7LQCbowY+qDGnbdMrTBd1hfThlI8lg==",
       "requires": {
         "@babel/runtime": "^7.17.2",
-        "@mui/utils": "^5.8.0",
+        "@mui/utils": "^5.8.4",
         "prop-types": "^15.8.1"
       }
     },
@@ -18945,30 +18943,30 @@
       }
     },
     "@mui/system": {
-      "version": "5.8.3",
-      "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.8.3.tgz",
-      "integrity": "sha512-/tyGQcYqZT0nl98qV9XnGiedTO+V7VHc28k4POfhMJNedB1CRrwWRm767DeEdc5f/8CU2See3WD16ikP6pYiOA==",
+      "version": "5.8.4",
+      "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.8.4.tgz",
+      "integrity": "sha512-eeYZXlOn4p+tYwqqDlci6wW4knJ68aGx5A24YU9ubYZ5o0IwveoNP3LC9sHAMxigk/mUTqL4bpSMJ2HbTn2aQg==",
       "requires": {
         "@babel/runtime": "^7.17.2",
-        "@mui/private-theming": "^5.8.0",
+        "@mui/private-theming": "^5.8.4",
         "@mui/styled-engine": "^5.8.0",
-        "@mui/types": "^7.1.3",
-        "@mui/utils": "^5.8.0",
+        "@mui/types": "^7.1.4",
+        "@mui/utils": "^5.8.4",
         "clsx": "^1.1.1",
         "csstype": "^3.1.0",
         "prop-types": "^15.8.1"
       }
     },
     "@mui/types": {
-      "version": "7.1.3",
-      "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.1.3.tgz",
-      "integrity": "sha512-DDF0UhMBo4Uezlk+6QxrlDbchF79XG6Zs0zIewlR4c0Dt6GKVFfUtzPtHCH1tTbcSlq/L2bGEdiaoHBJ9Y1gSA==",
+      "version": "7.1.4",
+      "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.1.4.tgz",
+      "integrity": "sha512-uveM3byMbthO+6tXZ1n2zm0W3uJCQYtwt/v5zV5I77v2v18u0ITkb8xwhsDD2i3V2Kye7SaNR6FFJ6lMuY/WqQ==",
       "requires": {}
     },
     "@mui/utils": {
-      "version": "5.8.0",
-      "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.8.0.tgz",
-      "integrity": "sha512-7LgUtCvz78676iC0wpTH7HizMdCrTphhBmRWimIMFrp5Ph6JbDFVuKS1CwYnWWxRyYKL0QzXrDL0lptAU90EXg==",
+      "version": "5.8.4",
+      "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.8.4.tgz",
+      "integrity": "sha512-BHYErfrjqqh76KaDAm8wZlhEip1Uj7Cmco65NcsF3BWrAl3FWngACpaPZeEbTgmaEwyWAQEE6LZhsmy43hfyqQ==",
       "requires": {
         "@babel/runtime": "^7.17.2",
         "@types/prop-types": "^15.7.5",
@@ -19366,9 +19364,9 @@
       }
     },
     "@types/express-serve-static-core": {
-      "version": "4.17.28",
-      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz",
-      "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==",
+      "version": "4.17.29",
+      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.29.tgz",
+      "integrity": "sha512-uMd++6dMKS32EOuw1Uli3e3BPgdLIXmezcfHv7N4c1s3gkhikBplORPpMq3fuWkxncZN1reb16d5n8yhQ80x7Q==",
       "requires": {
         "@types/node": "*",
         "@types/qs": "*",
@@ -19433,9 +19431,9 @@
       "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw=="
     },
     "@types/node": {
-      "version": "17.0.42",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.42.tgz",
-      "integrity": "sha512-Q5BPGyGKcvQgAMbsr7qEGN/kIPN6zZecYYABeTDBizOsau+2NMdSVTar9UQw21A2+JyA2KRNDYaYrPB0Rpk2oQ=="
+      "version": "18.0.0",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.0.tgz",
+      "integrity": "sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA=="
     },
     "@types/parse-json": {
       "version": "4.0.0",
@@ -19468,9 +19466,9 @@
       "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
     },
     "@types/react": {
-      "version": "18.0.12",
-      "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.12.tgz",
-      "integrity": "sha512-duF1OTASSBQtcigUvhuiTB1Ya3OvSy+xORCiEf20H0P0lzx+/KeVsA99U5UjLXSbyo1DRJDlLKqTeM1ngosqtg==",
+      "version": "18.0.13",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.13.tgz",
+      "integrity": "sha512-psqptIYQxGUFuGYwP3KCFVtPTkMpIcrqFmtKblWEUQhLuYLpHBwJkXhjp6eHfDM5IbyskY4x7qQpLedEsPkHlA==",
       "requires": {
         "@types/prop-types": "*",
         "@types/scheduler": "*",
@@ -19568,13 +19566,13 @@
       "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA=="
     },
     "@typescript-eslint/eslint-plugin": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.1.tgz",
-      "integrity": "sha512-6dM5NKT57ZduNnJfpY81Phe9nc9wolnMCnknb1im6brWi1RYv84nbMS3olJa27B6+irUVV1X/Wb+Am0FjJdGFw==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.28.0.tgz",
+      "integrity": "sha512-DXVU6Cg29H2M6EybqSg2A+x8DgO9TCUBRp4QEXQHJceLS7ogVDP0g3Lkg/SZCqcvkAP/RruuQqK0gdlkgmhSUA==",
       "requires": {
-        "@typescript-eslint/scope-manager": "5.27.1",
-        "@typescript-eslint/type-utils": "5.27.1",
-        "@typescript-eslint/utils": "5.27.1",
+        "@typescript-eslint/scope-manager": "5.28.0",
+        "@typescript-eslint/type-utils": "5.28.0",
+        "@typescript-eslint/utils": "5.28.0",
         "debug": "^4.3.4",
         "functional-red-black-tree": "^1.0.1",
         "ignore": "^5.2.0",
@@ -19594,55 +19592,55 @@
       }
     },
     "@typescript-eslint/experimental-utils": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.27.1.tgz",
-      "integrity": "sha512-Vd8uewIixGP93sEnmTRIH6jHZYRQRkGPDPpapACMvitJKX8335VHNyqKTE+mZ+m3E2c5VznTZfSsSsS5IF7vUA==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.28.0.tgz",
+      "integrity": "sha512-pPQ1Ng4qezQijXBBfYlogcOPnMs1q14l8C4fWJJ4PnFla4MA2b2oBfdkf02r1lNak2tpBVNJxvey9oWlPQWc4w==",
       "requires": {
-        "@typescript-eslint/utils": "5.27.1"
+        "@typescript-eslint/utils": "5.28.0"
       }
     },
     "@typescript-eslint/parser": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.27.1.tgz",
-      "integrity": "sha512-7Va2ZOkHi5NP+AZwb5ReLgNF6nWLGTeUJfxdkVUAPPSaAdbWNnFZzLZ4EGGmmiCTg+AwlbE1KyUYTBglosSLHQ==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.28.0.tgz",
+      "integrity": "sha512-ekqoNRNK1lAcKhZESN/PdpVsWbP9jtiNqzFWkp/yAUdZvJalw2heCYuqRmM5eUJSIYEkgq5sGOjq+ZqsLMjtRA==",
       "requires": {
-        "@typescript-eslint/scope-manager": "5.27.1",
-        "@typescript-eslint/types": "5.27.1",
-        "@typescript-eslint/typescript-estree": "5.27.1",
+        "@typescript-eslint/scope-manager": "5.28.0",
+        "@typescript-eslint/types": "5.28.0",
+        "@typescript-eslint/typescript-estree": "5.28.0",
         "debug": "^4.3.4"
       }
     },
     "@typescript-eslint/scope-manager": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.27.1.tgz",
-      "integrity": "sha512-fQEOSa/QroWE6fAEg+bJxtRZJTH8NTskggybogHt4H9Da8zd4cJji76gA5SBlR0MgtwF7rebxTbDKB49YUCpAg==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.28.0.tgz",
+      "integrity": "sha512-LeBLTqF/he1Z+boRhSqnso6YrzcKMTQ8bO/YKEe+6+O/JGof9M0g3IJlIsqfrK/6K03MlFIlycbf1uQR1IjE+w==",
       "requires": {
-        "@typescript-eslint/types": "5.27.1",
-        "@typescript-eslint/visitor-keys": "5.27.1"
+        "@typescript-eslint/types": "5.28.0",
+        "@typescript-eslint/visitor-keys": "5.28.0"
       }
     },
     "@typescript-eslint/type-utils": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.27.1.tgz",
-      "integrity": "sha512-+UC1vVUWaDHRnC2cQrCJ4QtVjpjjCgjNFpg8b03nERmkHv9JV9X5M19D7UFMd+/G7T/sgFwX2pGmWK38rqyvXw==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.28.0.tgz",
+      "integrity": "sha512-SyKjKh4CXPglueyC6ceAFytjYWMoPHMswPQae236zqe1YbhvCVQyIawesYywGiu98L9DwrxsBN69vGIVxJ4mQQ==",
       "requires": {
-        "@typescript-eslint/utils": "5.27.1",
+        "@typescript-eslint/utils": "5.28.0",
         "debug": "^4.3.4",
         "tsutils": "^3.21.0"
       }
     },
     "@typescript-eslint/types": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.27.1.tgz",
-      "integrity": "sha512-LgogNVkBhCTZU/m8XgEYIWICD6m4dmEDbKXESCbqOXfKZxRKeqpiJXQIErv66sdopRKZPo5l32ymNqibYEH/xg=="
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.28.0.tgz",
+      "integrity": "sha512-2OOm8ZTOQxqkPbf+DAo8oc16sDlVR5owgJfKheBkxBKg1vAfw2JsSofH9+16VPlN9PWtv8Wzhklkqw3k/zCVxA=="
     },
     "@typescript-eslint/typescript-estree": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.1.tgz",
-      "integrity": "sha512-DnZvvq3TAJ5ke+hk0LklvxwYsnXpRdqUY5gaVS0D4raKtbznPz71UJGnPTHEFo0GDxqLOLdMkkmVZjSpET1hFw==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.28.0.tgz",
+      "integrity": "sha512-9GX+GfpV+F4hdTtYc6OV9ZkyYilGXPmQpm6AThInpBmKJEyRSIjORJd1G9+bknb7OTFYL+Vd4FBJAO6T78OVqA==",
       "requires": {
-        "@typescript-eslint/types": "5.27.1",
-        "@typescript-eslint/visitor-keys": "5.27.1",
+        "@typescript-eslint/types": "5.28.0",
+        "@typescript-eslint/visitor-keys": "5.28.0",
         "debug": "^4.3.4",
         "globby": "^11.1.0",
         "is-glob": "^4.0.3",
@@ -19661,14 +19659,14 @@
       }
     },
     "@typescript-eslint/utils": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.27.1.tgz",
-      "integrity": "sha512-mZ9WEn1ZLDaVrhRaYgzbkXBkTPghPFsup8zDbbsYTxC5OmqrFE7skkKS/sraVsLP3TcT3Ki5CSyEFBRkLH/H/w==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.28.0.tgz",
+      "integrity": "sha512-E60N5L0fjv7iPJV3UGc4EC+A3Lcj4jle9zzR0gW7vXhflO7/J29kwiTGITA2RlrmPokKiZbBy2DgaclCaEUs6g==",
       "requires": {
         "@types/json-schema": "^7.0.9",
-        "@typescript-eslint/scope-manager": "5.27.1",
-        "@typescript-eslint/types": "5.27.1",
-        "@typescript-eslint/typescript-estree": "5.27.1",
+        "@typescript-eslint/scope-manager": "5.28.0",
+        "@typescript-eslint/types": "5.28.0",
+        "@typescript-eslint/typescript-estree": "5.28.0",
         "eslint-scope": "^5.1.1",
         "eslint-utils": "^3.0.0"
       },
@@ -19690,11 +19688,11 @@
       }
     },
     "@typescript-eslint/visitor-keys": {
-      "version": "5.27.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.1.tgz",
-      "integrity": "sha512-xYs6ffo01nhdJgPieyk7HAOpjhTsx7r/oB9LWEhwAXgwn33tkr+W8DI2ChboqhZlC4q3TC6geDYPoiX8ROqyOQ==",
+      "version": "5.28.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.28.0.tgz",
+      "integrity": "sha512-BtfP1vCor8cWacovzzPFOoeW4kBQxzmhxGoOpt0v1SFvG+nJ0cWaVdJk7cky1ArTcFHHKNIxyo2LLr3oNkSuXA==",
       "requires": {
-        "@typescript-eslint/types": "5.27.1",
+        "@typescript-eslint/types": "5.28.0",
         "eslint-visitor-keys": "^3.3.0"
       }
     },
@@ -20572,9 +20570,9 @@
       }
     },
     "caniuse-lite": {
-      "version": "1.0.30001352",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001352.tgz",
-      "integrity": "sha512-GUgH8w6YergqPQDGWhJGt8GDRnY0L/iJVQcU3eJ46GYf52R8tk0Wxp0PymuFVZboJYXGiCqwozAYZNRjVj6IcA=="
+      "version": "1.0.30001355",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001355.tgz",
+      "integrity": "sha512-Sd6pjJHF27LzCB7pT7qs+kuX2ndurzCzkpJl6Qct7LPSZ9jn0bkOA8mdgMgmqnQAWLVOOGjLpc+66V57eLtb1g=="
     },
     "case-sensitive-paths-webpack-plugin": {
       "version": "2.4.0",
@@ -20644,9 +20642,9 @@
       "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg=="
     },
     "ci-info": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.1.tgz",
-      "integrity": "sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg=="
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz",
+      "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg=="
     },
     "cjs-module-lexer": {
       "version": "1.2.2",
@@ -20722,9 +20720,9 @@
       "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ=="
     },
     "colorette": {
-      "version": "2.0.17",
-      "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.17.tgz",
-      "integrity": "sha512-hJo+3Bkn0NCHybn9Tu35fIeoOKGOk5OCC32y4Hz2It+qlCO2Q3DeQ1hRn/tDDMQKRYUEzqsl7jbF6dYKjlE60g=="
+      "version": "2.0.19",
+      "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz",
+      "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ=="
     },
     "combined-stream": {
       "version": "1.0.8",
@@ -20845,16 +20843,16 @@
       "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
     },
     "core-js": {
-      "version": "3.22.8",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.8.tgz",
-      "integrity": "sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA=="
+      "version": "3.23.1",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.23.1.tgz",
+      "integrity": "sha512-wfMYHWi1WQjpgZNC9kAlN4ut04TM9fUTdi7CqIoTVM7yaiOUQTklOzfb+oWH3r9edQcT3F887swuVmxrV+CC8w=="
     },
     "core-js-compat": {
-      "version": "3.22.8",
-      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.22.8.tgz",
-      "integrity": "sha512-pQnwg4xtuvc2Bs/5zYQPaEYYSuTxsF7LBWF0SvnVhthZo/Qe+rJpcEekrdNK5DWwDJ0gv0oI9NNX5Mppdy0ctg==",
+      "version": "3.23.1",
+      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.1.tgz",
+      "integrity": "sha512-KeYrEc8t6FJsKYB2qnDwRHWaC0cJNaqlHfCpMe5q3j/W1nje3moib/txNklddLPCtGb+etcBIyJ8zuMa/LN5/A==",
       "requires": {
-        "browserslist": "^4.20.3",
+        "browserslist": "^4.20.4",
         "semver": "7.0.0"
       },
       "dependencies": {
@@ -20866,9 +20864,9 @@
       }
     },
     "core-js-pure": {
-      "version": "3.22.8",
-      "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.22.8.tgz",
-      "integrity": "sha512-bOxbZIy9S5n4OVH63XaLVXZ49QKicjowDx/UELyJ68vxfCRpYsbyh/WNZNfEfAk+ekA8vSjt+gCDpvh672bc3w=="
+      "version": "3.23.1",
+      "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.23.1.tgz",
+      "integrity": "sha512-3qNgf6TqI3U1uhuSYRzJZGfFd4T+YlbyVPl+jgRiKjdZopvG4keZQwWZDAWpu1UH9nCgTpUzIV3GFawC7cJsqg=="
     },
     "core-util-is": {
       "version": "1.0.3",
@@ -21361,9 +21359,9 @@
       "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg=="
     },
     "dns-packet": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.3.1.tgz",
-      "integrity": "sha512-spBwIj0TK0Ey3666GwIdWVfUpLyubpU53BTCu8iPn4r4oXd9O14Hjg3EHw3ts2oed77/SeckunUYCyRlSngqHw==",
+      "version": "5.4.0",
+      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.4.0.tgz",
+      "integrity": "sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==",
       "requires": {
         "@leichtgewicht/ip-codec": "^2.0.1"
       }
@@ -21479,9 +21477,9 @@
       }
     },
     "electron-to-chromium": {
-      "version": "1.4.152",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.152.tgz",
-      "integrity": "sha512-jk4Ju5SGZAQQJ1iI4Rgru7dDlvkQPLpNPWH9gIZmwCD4YteA5Bbk1xPcPDUf5jUYs3e1e80RXdi8XgKQZaigeg=="
+      "version": "1.4.158",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.158.tgz",
+      "integrity": "sha512-gppO3/+Y6sP432HtvwvuU8S+YYYLH4PmAYvQwqUtt9HDOmEsBwQfLnK9T8+1NIKwAS1BEygIjTaATC4H5EzvxQ=="
     },
     "emittery": {
       "version": "0.8.1",
@@ -21996,9 +21994,9 @@
       }
     },
     "eslint-plugin-react-hooks": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.5.0.tgz",
-      "integrity": "sha512-8k1gRt7D7h03kd+SAAlzXkQwWK22BnK6GKZG+FJA6BAGy22CFvl8kCIXKpVux0cCxMWDQUPqSok0LKaZ0aOcCw==",
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
+      "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
       "requires": {}
     },
     "eslint-plugin-testing-library": {
@@ -22949,9 +22947,9 @@
       "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="
     },
     "i18next": {
-      "version": "21.8.9",
-      "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.8.9.tgz",
-      "integrity": "sha512-PY9a/8ADVmnju1tETeglbbVQi+nM5pcJQWm9kvKMTE3GPgHHtpDsHy5HQ/hccz2/xtW7j3vuso23JdQSH0EttA==",
+      "version": "21.8.10",
+      "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.8.10.tgz",
+      "integrity": "sha512-7xRb6y4QlSqZRZ3uA5BIEsLuZpmxpzHLizQyKjDDThOcvdfgICOX7aFoBnh4BSWcLtJamTqSweaOuK22A2xqkA==",
       "requires": {
         "@babel/runtime": "^7.17.2"
       }
@@ -23005,9 +23003,9 @@
       "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ=="
     },
     "immer": {
-      "version": "9.0.14",
-      "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.14.tgz",
-      "integrity": "sha512-ubBeqQutOSLIFCUBN03jGeOS6a3DoYlSYwYJTa+gSKEZKU5redJIqkIdZ3JVv/4RZpfcXdAWH5zCNLWPRv2WDw=="
+      "version": "9.0.15",
+      "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz",
+      "integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ=="
     },
     "import-fresh": {
       "version": "3.3.0",
@@ -24631,9 +24629,9 @@
           }
         },
         "react-is": {
-          "version": "18.1.0",
-          "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz",
-          "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg=="
+          "version": "18.2.0",
+          "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+          "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
         },
         "slash": {
           "version": "4.0.0",
@@ -25115,9 +25113,9 @@
       "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
     },
     "mini-css-extract-plugin": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.0.tgz",
-      "integrity": "sha512-ndG8nxCEnAemsg4FSgS+yNyHKgkTB4nPKqCOgh65j3/30qqC5RaSQQXMm++Y6sb6E1zRSxPkztj9fqxhS1Eo6w==",
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz",
+      "integrity": "sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg==",
       "requires": {
         "schema-utils": "^4.0.0"
       },
@@ -26491,9 +26489,9 @@
       }
     },
     "react": {
-      "version": "18.1.0",
-      "resolved": "https://registry.npmjs.org/react/-/react-18.1.0.tgz",
-      "integrity": "sha512-4oL8ivCz5ZEPyclFQXaNksK3adutVS8l2xzZU0cqEFrE9Sb7fC0EFK5uEk74wIreL1DERyjvsU915j1pcT2uEQ==",
+      "version": "18.2.0",
+      "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
+      "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
       "requires": {
         "loose-envify": "^1.1.0"
       }
@@ -26593,12 +26591,12 @@
       }
     },
     "react-dom": {
-      "version": "18.1.0",
-      "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.1.0.tgz",
-      "integrity": "sha512-fU1Txz7Budmvamp7bshe4Zi32d0ll7ect+ccxNu9FlObT605GOEB8BfO4tmRJ39R5Zj831VCpvQ05QPBW5yb+w==",
+      "version": "18.2.0",
+      "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
+      "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
       "requires": {
         "loose-envify": "^1.1.0",
-        "scheduler": "^0.22.0"
+        "scheduler": "^0.23.0"
       }
     },
     "react-error-overlay": {
@@ -26607,9 +26605,9 @@
       "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
     },
     "react-i18next": {
-      "version": "11.17.1",
-      "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.17.1.tgz",
-      "integrity": "sha512-4H4fK9vWsQtPP0iAdqzGfdPKLaSXpCjuh1xaGsejX/CO8tx8zCnrOnlQhMgrJf+OlUfzth5YaDPXYGp3RHxV1g==",
+      "version": "11.17.2",
+      "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.17.2.tgz",
+      "integrity": "sha512-/HG4XSResWDY450cFmoUqLgCYDu8VYMFISGcMnZlxRSV05naj3+F7DoebwnPu6z/akA3Wd0Xe7KGTYdywL9z9g==",
       "requires": {
         "@babel/runtime": "^7.14.5",
         "html-escaper": "^2.0.2",
@@ -27066,9 +27064,9 @@
       }
     },
     "scheduler": {
-      "version": "0.22.0",
-      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.22.0.tgz",
-      "integrity": "sha512-6QAm1BgQI88NPYymgGQLCZgvep4FyePDWFpXVK+zNSUgHwlqpJy8VEh8Et0KxTACS4VWwMousBElAZOH9nkkoQ==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
+      "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
       "requires": {
         "loose-envify": "^1.1.0"
       }
@@ -27678,11 +27676,11 @@
       "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="
     },
     "tailwindcss": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.2.tgz",
-      "integrity": "sha512-yJ6L5s1U5AeS5g7HHy212zdQfjwD426FBfm59pet/JsyneuZuD4C2W7PpJEg4ppisiB21uLqtNagv8KXury3+Q==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.3.tgz",
+      "integrity": "sha512-PRJNYdSIthrb8hjmAyymEyEN8Yo61TMXpzyFUpxULeeyRn3Y3gpvuw6FlRTKrJvK7thSGKRnhT36VovVx4WeMA==",
       "requires": {
-        "arg": "^5.0.1",
+        "arg": "^5.0.2",
         "chokidar": "^3.5.3",
         "color-name": "^1.1.4",
         "detective": "^5.2.1",