diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0fc62abdc3844c2e79a49503b7dee24cee365765..327488997079d175964ed4c01ddc5fb669cd61e8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-image: code.castopod.org:5050/adaures/castopod:php8.0
+image: code.castopod.org:5050/adaures/castopod:php8.1
 
 stages:
   - prepare
@@ -49,8 +49,9 @@ lint-php:
     - vendor/bin/ecs check --ansi
     # phpstan - increase memory limit to 1GB to prevent script failure
     - php -d memory_limit=1G vendor/bin/phpstan analyse --ansi
+    # FIXME: rector keeps failing in CI
     # run rector to check for php errors
-    - vendor/bin/rector process --dry-run --ansi
+    # - vendor/bin/rector process --dry-run --ansi
   dependencies:
     - php-dependencies
 
diff --git a/app/Config/Fediverse.php b/app/Config/Fediverse.php
index 4834d67938225be1410547453a67d31d65e5d32f..cb10bc1afc1e17541ea174befd2996c2a00fb256 100644
--- a/app/Config/Fediverse.php
+++ b/app/Config/Fediverse.php
@@ -42,7 +42,7 @@ class Fediverse extends FediverseBaseConfig
         }
 
         ['dirname' => $dirname, 'extension' => $extension, 'filename' => $filename] = pathinfo(
-            $defaultBanner['path']
+            (string) $defaultBanner['path']
         );
         $defaultBannerPath = $filename;
         if ($dirname !== '.') {
diff --git a/app/Controllers/EpisodeController.php b/app/Controllers/EpisodeController.php
index 6b9c5cf01a95fc69d9ac2fc0d406959ccef78643..5b59cf55472d99b415edaf260df6a1ccc081c68a 100644
--- a/app/Controllers/EpisodeController.php
+++ b/app/Controllers/EpisodeController.php
@@ -176,7 +176,7 @@ class EpisodeController extends BaseController
         $session = Services::session();
         $session->start();
         if (isset($_SERVER['HTTP_REFERER'])) {
-            $session->set('embed_domain', parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST));
+            $session->set('embed_domain', parse_url((string) $_SERVER['HTTP_REFERER'], PHP_URL_HOST));
         }
 
         $cacheName = implode(
diff --git a/app/Controllers/WebmanifestController.php b/app/Controllers/WebmanifestController.php
index 8a1bd83eb0ab2c37c3e992dcc9a51ae38b01375d..653bcaae6cb4b57da66eae14d804b15b51d4c17b 100644
--- a/app/Controllers/WebmanifestController.php
+++ b/app/Controllers/WebmanifestController.php
@@ -20,7 +20,7 @@ class WebmanifestController extends Controller
     /**
      * @var array<string, array<string, string>>
      */
-    public const THEME_COLORS = [
+    final public const THEME_COLORS = [
         'pine' => [
             'theme' => '#009486',
             'background' => '#F0F9F8',
diff --git a/app/Entities/Clip/VideoClip.php b/app/Entities/Clip/VideoClip.php
index a4add00824e1df7cb8280edf5ac2cfc05d35d86a..960296f9ce1d812a31f645d2234908352946b7f9 100644
--- a/app/Entities/Clip/VideoClip.php
+++ b/app/Entities/Clip/VideoClip.php
@@ -53,7 +53,7 @@ class VideoClip extends BaseClip
 
     public function setFormat(string $format): self
     {
-        $this->attributes['metadata'] = json_decode($this->attributes['metadata'], true);
+        $this->attributes['metadata'] = json_decode((string) $this->attributes['metadata'], true);
 
         $this->attributes['format'] = $format;
         $this->attributes['metadata']['format'] = $format;
diff --git a/app/Entities/Episode.php b/app/Entities/Episode.php
index d58059c235e563121dbbcaa1c6d9dcc8bc55182f..56d8af8a41c1a6851e8b7066383198c924f9ea7d 100644
--- a/app/Entities/Episode.php
+++ b/app/Entities/Episode.php
@@ -536,7 +536,7 @@ class Episode extends Entity
     {
         if ($this->description === null) {
             $this->description = trim(
-                preg_replace('~\s+~', ' ', strip_tags($this->attributes['description_html'])),
+                preg_replace('~\s+~', ' ', strip_tags((string) $this->attributes['description_html'])),
             );
         }
 
@@ -620,7 +620,7 @@ class Episode extends Entity
             'elements' => $this->custom_rss,
         ], $xmlNode);
 
-        return (string) str_replace(['<item>', '</item>'], '', $xmlNode->asXML());
+        return str_replace(['<item>', '</item>'], '', (string) $xmlNode->asXML());
     }
 
     /**
@@ -659,7 +659,7 @@ class Episode extends Entity
             $this->getPodcast()
                 ->partner_id .
             '&guid=' .
-            urlencode($this->attributes['guid']);
+            urlencode((string) $this->attributes['guid']);
 
         if ($serviceSlug !== null) {
             $partnerLink .= '&_from=' . $serviceSlug;
@@ -675,7 +675,7 @@ class Episode extends Entity
             $this->getPodcast()
                 ->partner_id .
             '&guid=' .
-            urlencode($this->attributes['guid']) .
+            urlencode((string) $this->attributes['guid']) .
             ($serviceSlug !== null ? '&_from=' . $serviceSlug : '');
     }
 }
diff --git a/app/Entities/Location.php b/app/Entities/Location.php
index 0062cd7dff7db4b35f5b29b5638dee5be1c4df96..b1098687fdc966a2bfbb17c86a90b36a428e4d49 100644
--- a/app/Entities/Location.php
+++ b/app/Entities/Location.php
@@ -115,7 +115,7 @@ class Location extends Entity
             $places[0],
             'osm_id'
         ) && $places[0]->osm_id !== null)) {
-            $this->attributes['osm'] = strtoupper(substr($places[0]->osm_type, 0, 1)) . $places[0]->osm_id;
+            $this->attributes['osm'] = strtoupper(substr((string) $places[0]->osm_type, 0, 1)) . $places[0]->osm_id;
         }
 
         return $this;
diff --git a/app/Entities/Podcast.php b/app/Entities/Podcast.php
index efcdb88de08cf59f787fc3a20ab7e9ee0539ad3e..b9fb35a8271a15b811d4ba4ba4403cb124299876 100644
--- a/app/Entities/Podcast.php
+++ b/app/Entities/Podcast.php
@@ -495,7 +495,7 @@ class Podcast extends Entity
     {
         if ($this->description === null) {
             $this->description = trim(
-                (string) preg_replace('~\s+~', ' ', strip_tags($this->attributes['description_html'])),
+                (string) preg_replace('~\s+~', ' ', strip_tags((string) $this->attributes['description_html'])),
             );
         }
 
@@ -658,7 +658,7 @@ class Podcast extends Entity
             'elements' => $this->custom_rss,
         ], $xmlNode);
 
-        return (string) str_replace(['<channel>', '</channel>'], '', $xmlNode->asXML());
+        return str_replace(['<channel>', '</channel>'], '', (string) $xmlNode->asXML());
     }
 
     /**
diff --git a/app/Helpers/form_helper.php b/app/Helpers/form_helper.php
index d0ab8d3a7f93f17220cce6373276a48a12b54307..85808f64e73ebb348f854b5036eb8500317e77bf 100644
--- a/app/Helpers/form_helper.php
+++ b/app/Helpers/form_helper.php
@@ -70,7 +70,7 @@ if (! function_exists('parse_form_attributes')) {
 
         foreach ($default as $key => $val) {
             if (! is_bool($val)) {
-                if ($key === 'name' && ! strlen($default['name'])) {
+                if ($key === 'name' && ! strlen((string) $default['name'])) {
                     continue;
                 }
 
diff --git a/app/Helpers/media_helper.php b/app/Helpers/media_helper.php
index f77d8ef917edbbe00c5196aae7fc33c185905d86..e523f296acb1117ea8ddafba445c68a3357c8845 100644
--- a/app/Helpers/media_helper.php
+++ b/app/Helpers/media_helper.php
@@ -130,7 +130,7 @@ if (! function_exists('media_base_url')) {
         $appConfig = config('App');
         $mediaBaseUrl = $appConfig->mediaBaseURL === '' ? $appConfig->baseURL : $appConfig->mediaBaseURL;
 
-        return rtrim($mediaBaseUrl, '/') .
+        return rtrim((string) $mediaBaseUrl, '/') .
             '/' .
             $appConfig->mediaRoot .
             '/' .
diff --git a/app/Libraries/MediaClipper/VideoClipper.php b/app/Libraries/MediaClipper/VideoClipper.php
index 1c97f7cc3b2e1b74d7e731412d1d6d82ddfbad34..7bf7e2807698ad5557666bfa8e05c92f7cd4ce55 100644
--- a/app/Libraries/MediaClipper/VideoClipper.php
+++ b/app/Libraries/MediaClipper/VideoClipper.php
@@ -23,7 +23,7 @@ class VideoClipper
     /**
      * @var array<string, string>
      */
-    public const FONTS = [
+    final public const FONTS = [
         'episodeTitle' => 'Rubik-Bold.ttf',
         'podcastTitle' => 'Inter-Regular.otf',
         'subtitles' => 'Inter-SemiBold',
diff --git a/app/Libraries/Router.php b/app/Libraries/Router.php
index dc7609072f5861cd8cf0a66ab9177b1c61d1506e..9eb9fa516ddb34a1b1c4d6079117537fdab1d1b1 100644
--- a/app/Libraries/Router.php
+++ b/app/Libraries/Router.php
@@ -159,17 +159,17 @@ class Router extends CodeIgniterRouter
                 // Support resource route when function with subdirectory
                 // ex: $routes->resource('Admin/Admins');
                 if (
-                    str_contains($val, '$') &&
+                    str_contains((string) $val, '$') &&
                     str_contains($routeKey, '(') &&
                     str_contains($routeKey, '/')
                 ) {
                     $replacekey = str_replace('/(.*)', '', $routeKey);
                     $val = preg_replace('#^' . $routeKey . '$#u', $val, $uri);
                     $val = str_replace($replacekey, str_replace('/', '\\', $replacekey), $val);
-                } elseif (str_contains($val, '$') && str_contains($routeKey, '(')) {
+                } elseif (str_contains((string) $val, '$') && str_contains($routeKey, '(')) {
                     $val = preg_replace('#^' . $routeKey . '$#u', $val, $uri);
-                } elseif (str_contains($val, '/')) {
-                    [$controller, $method] = explode('::', $val);
+                } elseif (str_contains((string) $val, '/')) {
+                    [$controller, $method] = explode('::', (string) $val);
 
                     // Only replace slashes in the controller, not in the method.
                     $controller = str_replace('/', '\\', $controller);
@@ -177,7 +177,7 @@ class Router extends CodeIgniterRouter
                     $val = $controller . '::' . $method;
                 }
 
-                $this->setRequest(explode('/', $val));
+                $this->setRequest(explode('/', (string) $val));
 
                 $this->matchedRoute = [$matchedKey, $val];
 
diff --git a/app/Models/EpisodeCommentModel.php b/app/Models/EpisodeCommentModel.php
index af096172e6dd0109b2a0f8782d96282efebc135a..2c35b0c7fef2a7f11e89f27b3a44b73b4125883c 100644
--- a/app/Models/EpisodeCommentModel.php
+++ b/app/Models/EpisodeCommentModel.php
@@ -73,7 +73,7 @@ class EpisodeCommentModel extends UuidModel
         return $found;
     }
 
-    public function addComment(EpisodeComment $comment, bool $registerActivity = true): string | false
+    public function addComment(EpisodeComment $comment, bool $registerActivity = true): bool|int|object|string
     {
         $this->db->transStart();
 
diff --git a/app/Models/PlatformModel.php b/app/Models/PlatformModel.php
index 990f4f5956e19305c1140bcc4840cd853c247954..29c7259fc095727a761097ce81efe2655f1f6ef4 100644
--- a/app/Models/PlatformModel.php
+++ b/app/Models/PlatformModel.php
@@ -53,7 +53,7 @@ class PlatformModel extends Model
     public function getPlatforms(): array
     {
         if (! ($found = cache('platforms'))) {
-            $baseUrl = rtrim(config('app')->baseURL, '/');
+            $baseUrl = rtrim((string) config('app')->baseURL, '/');
             $found = $this->select(
                 "*, CONCAT('{$baseUrl}/assets/images/platforms/',`type`,'/',`slug`,'.svg') as icon",
             )->findAll();
diff --git a/app/Views/Components/DropdownMenu.php b/app/Views/Components/DropdownMenu.php
index bed2220f91c006f0326712296a678d32ec22166e..8c062311b33d243fd51e1e429e36c05d090c8bc7 100644
--- a/app/Views/Components/DropdownMenu.php
+++ b/app/Views/Components/DropdownMenu.php
@@ -41,7 +41,7 @@ class DropdownMenu extends Component
                     ]);
                     break;
                 case 'html':
-                    $menuItems .= htmlspecialchars_decode($item['content']);
+                    $menuItems .= htmlspecialchars_decode((string) $item['content']);
                     break;
                 case 'separator':
                     $menuItems .= '<hr class="my-2 border border-subtle">';
diff --git a/builds b/builds
index cc2ca0851ac774fe6c48458503bf811de92bd8c0..75b9d96651a20a8b277b6425b3dea91925cee90d 100644
--- a/builds
+++ b/builds
@@ -38,7 +38,7 @@ if (is_file($file)) {
         if (is_array($array)) {
             if ($dev) {
                 $array['minimum-stability'] = 'dev';
-                $array['prefer-stable']     = true;
+                $array['prefer-stable'] = true;
                 $array['repositories'] ??= [];
 
                 $found = false;
@@ -53,7 +53,7 @@ if (is_file($file)) {
                 if (! $found) {
                     $array['repositories'][] = [
                         'type' => 'vcs',
-                        'url'  => GITHUB_URL,
+                        'url' => GITHUB_URL,
                     ];
                 }
 
diff --git a/composer.json b/composer.json
index 1519add37a14c078c0cdbf30d95a7ff267d731c9..7b06b0d86b7cb7e8b55ba4f311370dc1cd30e2af 100644
--- a/composer.json
+++ b/composer.json
@@ -6,7 +6,7 @@
   "homepage": "https://castopod.org",
   "license": "AGPL-3.0-or-later",
   "require": {
-    "php": "^8.0",
+    "php": "^8.1",
     "codeigniter4/framework": "v4.2.7",
     "james-heinrich/getid3": "^2.0.x-dev",
     "whichbrowser/parser": "^v2.1.7",
@@ -47,8 +47,8 @@
   "scripts": {
     "test": "vendor/bin/phpunit",
     "analyse": "vendor/bin/phpstan analyse --ansi",
-    "rector": "vendor/bin/rector process --dry-run --ansi --memory-limit=1G",
-    "rector:fix": "vendor/bin/rector process --ansi --memory-limit=1G",
+    "rector": "vendor/bin/rector process --dry-run --ansi --memory-limit=2G",
+    "rector:fix": "vendor/bin/rector process --ansi --memory-limit=2G",
     "style": "vendor/bin/ecs check --ansi",
     "style:fix": "vendor/bin/ecs check --fix --ansi",
     "post-install-cmd": [
diff --git a/composer.lock b/composer.lock
index 253d0e0827712e49353fbc658b740f0f612157d4..13285f3374e30648887238c7f461a5fad763c20d 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
     "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
     "This file is @generated automatically"
   ],
-  "content-hash": "51482dcb24c719550a1f0aa7e7580dfc",
+  "content-hash": "c6dd2c4c4588bd654fd4973c5b574606",
   "packages": [
     {
       "name": "adaures/ipcat-php",
@@ -2411,16 +2411,16 @@
     },
     {
       "name": "vlucas/phpdotenv",
-      "version": "v5.4.1",
+      "version": "v5.5.0",
       "source": {
         "type": "git",
         "url": "https://github.com/vlucas/phpdotenv.git",
-        "reference": "264dce589e7ce37a7ba99cb901eed8249fbec92f"
+        "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/264dce589e7ce37a7ba99cb901eed8249fbec92f",
-        "reference": "264dce589e7ce37a7ba99cb901eed8249fbec92f",
+        "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7",
+        "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7",
         "shasum": ""
       },
       "require": {
@@ -2435,15 +2435,19 @@
       "require-dev": {
         "bamarni/composer-bin-plugin": "^1.4.1",
         "ext-filter": "*",
-        "phpunit/phpunit": "^7.5.20 || ^8.5.21 || ^9.5.10"
+        "phpunit/phpunit": "^7.5.20 || ^8.5.30 || ^9.5.25"
       },
       "suggest": {
         "ext-filter": "Required to use the boolean validator."
       },
       "type": "library",
       "extra": {
+        "bamarni-bin": {
+          "bin-links": true,
+          "forward-command": true
+        },
         "branch-alias": {
-          "dev-master": "5.4-dev"
+          "dev-master": "5.5-dev"
         }
       },
       "autoload": {
@@ -2469,7 +2473,7 @@
       "keywords": ["dotenv", "env", "environment"],
       "support": {
         "issues": "https://github.com/vlucas/phpdotenv/issues",
-        "source": "https://github.com/vlucas/phpdotenv/tree/v5.4.1"
+        "source": "https://github.com/vlucas/phpdotenv/tree/v5.5.0"
       },
       "funding": [
         {
@@ -2481,7 +2485,7 @@
           "type": "tidelift"
         }
       ],
-      "time": "2021-12-12T23:22:04+00:00"
+      "time": "2022-10-16T01:01:54+00:00"
     },
     {
       "name": "whichbrowser/parser",
@@ -3829,25 +3833,25 @@
     },
     {
       "name": "rector/rector",
-      "version": "0.14.5",
+      "version": "0.14.6",
       "source": {
         "type": "git",
         "url": "https://github.com/rectorphp/rector.git",
-        "reference": "f7fd87b2435835f481e6a94ee28e09af412bd3cc"
+        "reference": "e61574288661334155de6e5f0f45497285abad5d"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/rectorphp/rector/zipball/f7fd87b2435835f481e6a94ee28e09af412bd3cc",
-        "reference": "f7fd87b2435835f481e6a94ee28e09af412bd3cc",
+        "url": "https://api.github.com/repos/rectorphp/rector/zipball/e61574288661334155de6e5f0f45497285abad5d",
+        "reference": "e61574288661334155de6e5f0f45497285abad5d",
         "shasum": ""
       },
       "require": {
         "php": "^7.2|^8.0",
-        "phpstan/phpstan": "^1.8.6"
+        "phpstan/phpstan": "^1.8.7"
       },
       "conflict": {
-        "rector/rector-cakephp": "*",
         "rector/rector-doctrine": "*",
+        "rector/rector-downgrade-php": "*",
         "rector/rector-laravel": "*",
         "rector/rector-php-parser": "*",
         "rector/rector-phpoffice": "*",
@@ -3869,7 +3873,7 @@
       "description": "Instant Upgrade and Automated Refactoring of any PHP code",
       "support": {
         "issues": "https://github.com/rectorphp/rector/issues",
-        "source": "https://github.com/rectorphp/rector/tree/0.14.5"
+        "source": "https://github.com/rectorphp/rector/tree/0.14.6"
       },
       "funding": [
         {
@@ -3877,7 +3881,7 @@
           "type": "github"
         }
       ],
-      "time": "2022-09-29T11:05:42+00:00"
+      "time": "2022-10-15T22:58:22+00:00"
     },
     {
       "name": "sebastian/cli-parser",
@@ -6687,7 +6691,7 @@
   "prefer-stable": true,
   "prefer-lowest": false,
   "platform": {
-    "php": "^8.0"
+    "php": "^8.1"
   },
   "platform-dev": [],
   "plugin-api-version": "2.3.0"
diff --git a/docker/production/app/Dockerfile b/docker/production/app/Dockerfile
index 6ac15b24ccc8eddb04524153eb880f4903cca2a0..bf281d0519c3cc5c27cd8336646e410844d763fe 100644
--- a/docker/production/app/Dockerfile
+++ b/docker/production/app/Dockerfile
@@ -1,11 +1,11 @@
-FROM docker.io/alpine:3.13 AS ffmpeg-downloader
+FROM docker.io/alpine:3.16 AS ffmpeg-downloader
 
 RUN apk add --no-cache curl && \
     curl https://johnvansickle.com/ffmpeg/releases/ffmpeg-5.1.1-amd64-static.tar.xz -o ffmpeg.tar.xz && \
     mkdir ffmpeg && \
     tar -xJf ffmpeg.tar.xz -C ffmpeg --strip-components 1
 
-FROM docker.io/php:8.0-fpm-alpine3.13
+FROM docker.io/php:8.1-fpm-alpine3.16
 
 COPY docker/production/app/entrypoint.sh /entrypoint.sh
 
diff --git a/docs/src/ar/getting-started/install.md b/docs/src/ar/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/ar/getting-started/install.md
+++ b/docs/src/ar/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/br/getting-started/install.md b/docs/src/br/getting-started/install.md
index dac8517e9106a1f88c02ff0d01f71edab98a1c8b..9e7a1744a0d92da8873e6ecd44077184f8a9274c 100644
--- a/docs/src/br/getting-started/install.md
+++ b/docs/src/br/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/ca/getting-started/install.md b/docs/src/ca/getting-started/install.md
index 86a47cfd5cf7363d38d3291e8086228de6804c21..e6516f14a71cd5909f401849d97f015ef5c1016e 100644
--- a/docs/src/ca/getting-started/install.md
+++ b/docs/src/ca/getting-started/install.md
@@ -20,13 +20,13 @@ Si preferiu utilitzar Docker, podeu ometre això i anar directament a la
 
 ## Requisits
 
-- PHP v8.0 o superior
+- PHP v8.1 o superior
 - MySQL versió 5.7 o superior o MariaDB versió 10.2 o superior
 - Support d'HTTPS
 
-### PHP v8.0 o superior
+### PHP v8.1 o superior
 
-Es requereix PHP versió 8.0 o superior, amb les extensions següents
+Es requereix PHP versió 8.1 o superior, amb les extensions següents
 instal·lades:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
diff --git a/docs/src/de/getting-started/install.md b/docs/src/de/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/de/getting-started/install.md
+++ b/docs/src/de/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/el/getting-started/install.md b/docs/src/el/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/el/getting-started/install.md
+++ b/docs/src/el/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/es/getting-started/install.md b/docs/src/es/getting-started/install.md
index d3fd3b03c52e97df80acf2e5b2b809a5a6156743..b7febe866eb877868757a3398103a9b494dc99d8 100644
--- a/docs/src/es/getting-started/install.md
+++ b/docs/src/es/getting-started/install.md
@@ -20,13 +20,13 @@ Si prefieres usar Docker, puedes saltarte esto e ir directamente a la
 
 ## Requisitos
 
-- PHP v8.0 o superior
+- PHP v8.1 o superior
 - MySQL versión 5.7 o superior o MariaDB versión 10.2 o superior
 - Soporte HTTPS
 
-### PHP v8.0 o superior
+### PHP v8.1 o superior
 
-Se requiere PHP versión 8.0 o superior con las siguientes extensiones
+Se requiere PHP versión 8.1 o superior con las siguientes extensiones
 instaladas:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
diff --git a/docs/src/fa/getting-started/install.md b/docs/src/fa/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/fa/getting-started/install.md
+++ b/docs/src/fa/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/fr/getting-started/install.md b/docs/src/fr/getting-started/install.md
index f3e19c3e7133ada2f59a6671c0289b415ae53292..71b41bdebcbf6c4ee9d0bc4f5aee2713365ac2c5 100644
--- a/docs/src/fr/getting-started/install.md
+++ b/docs/src/fr/getting-started/install.md
@@ -20,13 +20,13 @@ directement à la [documentation Docker](./docker.md) pour Castopod.
 
 ## Prérequis
 
-- PHP v8.0 ou supérieure
+- PHP v8.1 ou supérieure
 - MySQL version 5.7 ou supérieure ou MariaDB version 10.2 ou supérieure
 - Prise en charge HTTPS
 
-### PHP v8.0 ou supérieure
+### PHP v8.1 ou supérieure
 
-PHP version 8.0 ou supérieure est requise, avec les extensions suivantes
+PHP version 8.1 ou supérieure est requise, avec les extensions suivantes
 installées :
 
 - [intl](https://www.php.net/manual/fr/intl.requirements.php)
diff --git a/docs/src/gd/getting-started/install.md b/docs/src/gd/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/gd/getting-started/install.md
+++ b/docs/src/gd/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/getting-started/install.md b/docs/src/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/getting-started/install.md
+++ b/docs/src/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/gl/getting-started/install.md b/docs/src/gl/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/gl/getting-started/install.md
+++ b/docs/src/gl/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/id/getting-started/install.md b/docs/src/id/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/id/getting-started/install.md
+++ b/docs/src/id/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/it/getting-started/install.md b/docs/src/it/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/it/getting-started/install.md
+++ b/docs/src/it/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/nl/getting-started/install.md b/docs/src/nl/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/nl/getting-started/install.md
+++ b/docs/src/nl/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/nn-NO/getting-started/install.md b/docs/src/nn-NO/getting-started/install.md
index fe65ac104f2bccd6690961332c62cc3c13cdbeca..fdd2a81717010b402027bb12297c32e31e20674d 100644
--- a/docs/src/nn-NO/getting-started/install.md
+++ b/docs/src/nn-NO/getting-started/install.md
@@ -20,13 +20,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Krav
 
-- PHP v8.0 eller nyare
+- PHP v8.1 eller nyare
 - MySQL versjon 5.7 eller nyare, eller MariaDB versjon 10.2 eller nyare
 - Støtte for HTTPS
 
-### PHP v8.0 eller nyare
+### PHP v8.1 eller nyare
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/oc/getting-started/install.md b/docs/src/oc/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/oc/getting-started/install.md
+++ b/docs/src/oc/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/pl/getting-started/install.md b/docs/src/pl/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/pl/getting-started/install.md
+++ b/docs/src/pl/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/pt-BR/getting-started/install.md b/docs/src/pt-BR/getting-started/install.md
index 41c0a4a289f2a62097c6919bd0af43181c1987d6..d27d6c59f5bab95c69210bb01d03452365f28a16 100644
--- a/docs/src/pt-BR/getting-started/install.md
+++ b/docs/src/pt-BR/getting-started/install.md
@@ -20,13 +20,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requisitos
 
-- PHP v8.0 ou superior
+- PHP v8.1 ou superior
 - MySQL versão 5.7 ou superior ou MariaDB versão 10.2 ou superior
 - Suporte a HTTPS
 
-### PHP v8.0 ou superior
+### PHP v8.1 ou superior
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/pt/getting-started/install.md b/docs/src/pt/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/pt/getting-started/install.md
+++ b/docs/src/pt/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/ru/getting-started/install.md b/docs/src/ru/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/ru/getting-started/install.md
+++ b/docs/src/ru/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/sk/getting-started/install.md b/docs/src/sk/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/sk/getting-started/install.md
+++ b/docs/src/sk/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/sv/getting-started/install.md b/docs/src/sv/getting-started/install.md
index 3d73187d08bb71d54328fe484c8ef775281e45b1..c68be846b213c4f6f8ad5370eb8efcbdc0a2c8b8 100644
--- a/docs/src/sv/getting-started/install.md
+++ b/docs/src/sv/getting-started/install.md
@@ -19,13 +19,13 @@ If you prefer using Docker, you may skip this and go straight to the
 
 ## Requirements
 
-- PHP v8.0 or higher
+- PHP v8.1 or higher
 - MySQL version 5.7 or higher or MariaDB version 10.2 or higher
 - HTTPS support
 
-### PHP v8.0 or higher
+### PHP v8.1 or higher
 
-PHP version 8.0 or higher is required, with the following extensions installed:
+PHP version 8.1 or higher is required, with the following extensions installed:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/docs/src/zh-Hans/getting-started/install.md b/docs/src/zh-Hans/getting-started/install.md
index 9a4ead833e53537c22a473984896f03d66f031fa..169609067904efe3bd04429264f7d3035ef7f4f9 100644
--- a/docs/src/zh-Hans/getting-started/install.md
+++ b/docs/src/zh-Hans/getting-started/install.md
@@ -19,13 +19,13 @@ Castopod 的安装非常简单。 你能在大多数兼容的 PHP-MySQL 的服
 
 ## 要求
 
-- PHP 8.0 或更高版本
+- PHP 8.1 或更高版本
 - MySQL 5.7 或更高版本与 MariaDB 10.2 或更高版本
 - HTTPS 支持
 
-### PHP 8.0 或更高版本
+### PHP 8.1 或更高版本
 
-需要 PHP 8.0 或更高版本,并安装以下扩展:
+需要 PHP 8.1 或更高版本,并安装以下扩展:
 
 - [intl](https://php.net/manual/en/intl.requirements.php)
 - [libcurl](https://php.net/manual/en/curl.requirements.php)
diff --git a/ecs.php b/ecs.php
index 8e2da3b116a22b7d4750a7587cccf4ec0b2c6945..5e33e87072f1d3b1c6eb3ef311b112578e2639b2 100644
--- a/ecs.php
+++ b/ecs.php
@@ -1,12 +1,14 @@
 <?php
 
-use PhpCsFixer\Fixer\Whitespace\IndentationTypeFixer;
-use Symplify\CodingStandard\Fixer\Naming\StandardizeHereNowDocKeywordFixer;
-use Symplify\EasyCodingStandard\ValueObject\Set\SetList;
-use Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer;
+declare(strict_types=1);
+
 use PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\AssignmentInConditionSniff;
 use PhpCsFixer\Fixer\StringNotation\SingleQuoteFixer;
+use PhpCsFixer\Fixer\Whitespace\IndentationTypeFixer;
+use Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer;
+use Symplify\CodingStandard\Fixer\Naming\StandardizeHereNowDocKeywordFixer;
 use Symplify\EasyCodingStandard\Config\ECSConfig;
+use Symplify\EasyCodingStandard\ValueObject\Set\SetList;
 
 return static function (ECSConfig $ecsConfig): void {
     // alternative to CLI arguments, easier to maintain and extend
@@ -16,9 +18,14 @@ return static function (ECSConfig $ecsConfig): void {
         __DIR__ . '/themes',
         __DIR__ . '/tests',
         __DIR__ . '/public',
+        __DIR__ . '/builds',
+        __DIR__ . '/ecs.php',
+        __DIR__ . '/preload.php',
+        __DIR__ . '/rector.php',
+        __DIR__ . '/spark',
     ]);
 
-    $ecsConfig->skip([        
+    $ecsConfig->skip([
         // skip specific generated files
         __DIR__ . '/modules/Admin/Language/*/PersonsTaxonomy.php',
 
@@ -26,7 +33,7 @@ return static function (ECSConfig $ecsConfig): void {
             __DIR__ . '/app/Views/Components/*',
             __DIR__ . '/modules/**/Views/Components/*',
             __DIR__ . '/themes/**/Views/Components/*',
-            __DIR__ . '/app/Helpers/components_helper.php'
+            __DIR__ . '/app/Helpers/components_helper.php',
         ],
 
         LineLengthFixer::class => [
@@ -43,18 +50,10 @@ return static function (ECSConfig $ecsConfig): void {
 
         // crowdin enforces its own style for translation files
         // remove SingleQuoteFixer for Language files to prevent conflicts
-        SingleQuoteFixer::class => [
-            __DIR__ . '/app/Language/*',
-            __DIR__ . '/modules/**/Language/*'
-        ],
+        SingleQuoteFixer::class => [__DIR__ . '/app/Language/*', __DIR__ . '/modules/**/Language/*'],
 
         AssignmentInConditionSniff::class,
     ]);
 
-    $ecsConfig->sets([
-        SetList::PSR_12,
-        SetList::SYMPLIFY,
-        SetList::COMMON,
-        SetList::CLEAN_CODE
-    ]);
+    $ecsConfig->sets([SetList::PSR_12, SetList::SYMPLIFY, SetList::COMMON, SetList::CLEAN_CODE]);
 };
diff --git a/modules/Admin/Controllers/SettingsController.php b/modules/Admin/Controllers/SettingsController.php
index 8fd936f4b9d531d8aa693b97f411e28f26342e5e..abd4413a5d0b6dba20f89c7691d1c7ae7080c24c 100644
--- a/modules/Admin/Controllers/SettingsController.php
+++ b/modules/Admin/Controllers/SettingsController.php
@@ -214,18 +214,18 @@ class SettingsController extends BaseController
 
             $allImages = (new MediaModel('image'))->getAllOfType();
             foreach ($allImages as $image) {
-                if (str_starts_with($image->file_path, 'podcasts')) {
-                    if (str_ends_with($image->file_path, 'banner.jpg') || str_ends_with(
-                        $image->file_path,
+                if (str_starts_with((string) $image->file_path, 'podcasts')) {
+                    if (str_ends_with((string) $image->file_path, 'banner.jpg') || str_ends_with(
+                        (string) $image->file_path,
                         'banner.png'
-                    ) || str_ends_with($image->file_path, 'banner.jpeg')) {
+                    ) || str_ends_with((string) $image->file_path, 'banner.jpeg')) {
                         $image->sizes = config('Images')
                             ->podcastBannerSizes;
                     } else {
                         $image->sizes = config('Images')
                             ->podcastCoverSizes;
                     }
-                } elseif (str_starts_with($image->file_path, 'persons')) {
+                } elseif (str_starts_with((string) $image->file_path, 'persons')) {
                     $image->sizes = config('Images')
                         ->personAvatarSizes;
                 } else {
diff --git a/modules/Analytics/AnalyticsTrait.php b/modules/Analytics/AnalyticsTrait.php
index 7d1680b4bfda5ecdb40ba2102834502c72e520d0..12cdde883c3c35c5243a2a03d19e3e2cd2af2adb 100644
--- a/modules/Analytics/AnalyticsTrait.php
+++ b/modules/Analytics/AnalyticsTrait.php
@@ -31,10 +31,10 @@ trait AnalyticsTrait
 
             $referer = $session->get('referer');
             $domain =
-                parse_url($referer, PHP_URL_HOST) === null
+                parse_url((string) $referer, PHP_URL_HOST) === null
                     ? '- Direct -'
-                    : parse_url($referer, PHP_URL_HOST);
-            parse_str((string) parse_url($referer, PHP_URL_QUERY), $queries);
+                    : parse_url((string) $referer, PHP_URL_HOST);
+            parse_str((string) parse_url((string) $referer, PHP_URL_QUERY), $queries);
             $keywords = $queries['q'] ?? null;
 
             $procedureName = $db->prefixTable('analytics_website');
diff --git a/modules/Analytics/Controllers/EpisodeAnalyticsController.php b/modules/Analytics/Controllers/EpisodeAnalyticsController.php
index e1244d5194a8466ac0b323709b97e39d1b3d39fd..8631af4b3e59419a36123021fe9f23d78ee5d2c5 100644
--- a/modules/Analytics/Controllers/EpisodeAnalyticsController.php
+++ b/modules/Analytics/Controllers/EpisodeAnalyticsController.php
@@ -63,7 +63,7 @@ class EpisodeAnalyticsController extends Controller
         } elseif ($session->get('embed_domain') !== null) {
             $serviceName = $session->get('embed_domain');
         } elseif ($session->get('referer') !== null && $session->get('referer') !== '- Direct -') {
-            $serviceName = parse_url($session->get('referer'), PHP_URL_HOST);
+            $serviceName = parse_url((string) $session->get('referer'), PHP_URL_HOST);
         }
 
         $episodeData = unpack(
diff --git a/modules/Analytics/Helpers/analytics_helper.php b/modules/Analytics/Helpers/analytics_helper.php
index 351c8da77bf7887fbb7f7ffb7cad294bd0d9f3f5..f5ef255a8c0ecfc9269f2d5a16df4c6a39af6e2a 100644
--- a/modules/Analytics/Helpers/analytics_helper.php
+++ b/modules/Analytics/Helpers/analytics_helper.php
@@ -212,7 +212,7 @@ if (! function_exists('set_user_session_referer')) {
             ? $_SERVER['HTTP_REFERER']
             : '- Direct -';
         $newreferer =
-            parse_url($newreferer, PHP_URL_HOST) ===
+            parse_url((string) $newreferer, PHP_URL_HOST) ===
             parse_url(current_url(false), PHP_URL_HOST)
                 ? '- Direct -'
                 : $newreferer;
@@ -311,7 +311,7 @@ if (! function_exists('podcast_hit')) {
                     // [0-1] bytes range requests are used (by Apple) to check that file exists and that 206 partial content is working.
                     // We don't count these requests.
                     // We calculate how many bytes are being downloaded based on HTTP_RANGE values:
-                    $ranges = explode(',', substr($httpRange, 6));
+                    $ranges = explode(',', substr((string) $httpRange, 6));
                     foreach ($ranges as $range) {
                         $parts = explode('-', $range);
                         $downloadedBytes += array_key_exists(1, $parts)
diff --git a/modules/Auth/Commands/RolesDoc.php b/modules/Auth/Commands/RolesDoc.php
index 5326c2b127f9a53f2ffc178a0d00ca16e3270ca7..fdd8833ef286063d52e5e98564faec84c77a1307 100644
--- a/modules/Auth/Commands/RolesDoc.php
+++ b/modules/Auth/Commands/RolesDoc.php
@@ -173,7 +173,11 @@ class RolesDoc extends BaseCommand
 
     private function detectLocaleFromPath($filePath): string
     {
-        preg_match('~docs\/src\/(?:([a-z]{2}(?:-[A-Za-z]{2,})?)\/)getting-started\/auth\.md~', $filePath, $match);
+        preg_match(
+            '~docs\/src\/(?:([a-z]{2}(?:-[A-Za-z]{2,})?)\/)getting-started\/auth\.md~',
+            (string) $filePath,
+            $match
+        );
 
         if ($match === []) {
             return 'en';
diff --git a/modules/Auth/Helpers/auth_helper.php b/modules/Auth/Helpers/auth_helper.php
index f382e3f48db281231823c57e458801389aba513f..a87ac811d5cee4deac27e54b1f48f6d605768fbe 100644
--- a/modules/Auth/Helpers/auth_helper.php
+++ b/modules/Auth/Helpers/auth_helper.php
@@ -155,7 +155,7 @@ if (! function_exists('get_podcast_group')) {
         }
 
         // strip the `podcast#{id}.` prefix when returning group
-        return substr($podcastGroup, strlen('podcast#' . $podcastId . '-'));
+        return substr((string) $podcastGroup, strlen('podcast#' . $podcastId . '-'));
     }
 }
 
@@ -183,7 +183,7 @@ if (! function_exists('get_podcast_groups')) {
         $userPodcastIds = [];
         // extract all podcast ids from groups
         foreach ($podcastGroups as $podcastGroup) {
-            $userPodcastIds[] = substr($podcastGroup, strpos($podcastGroup, '#') + 1, 1);
+            $userPodcastIds[] = substr((string) $podcastGroup, strpos((string) $podcastGroup, '#') + 1, 1);
         }
 
         return $userPodcastIds;
diff --git a/modules/Fediverse/Controllers/ActorController.php b/modules/Fediverse/Controllers/ActorController.php
index 44b0dc3a126a25c3fe68905721728766b10c8816..bf232890234fac50e854e80b1343ad544ba22b4d 100644
--- a/modules/Fediverse/Controllers/ActorController.php
+++ b/modules/Fediverse/Controllers/ActorController.php
@@ -334,7 +334,7 @@ class ActorController extends Controller
             ->setBody($followersCollection->toJSON());
     }
 
-    public function attemptFollow(): RedirectResponse | ResponseInterface
+    public function attemptFollow(): RedirectResponse
     {
         $rules = [
             'handle' =>
@@ -382,7 +382,7 @@ class ActorController extends Controller
         }
 
         return redirect()->to(
-            str_replace('{uri}', urlencode($this->actor->uri), $data->links[$ostatusKey]->template),
+            str_replace('{uri}', urlencode($this->actor->uri), (string) $data->links[$ostatusKey]->template),
         );
     }
 
diff --git a/modules/Fediverse/Controllers/PostController.php b/modules/Fediverse/Controllers/PostController.php
index 7eb5f47e2855af6ffbc25b67c5af8f7acc4852cd..a00efb83b340dbd8f11aada29f6114a263c7133b 100644
--- a/modules/Fediverse/Controllers/PostController.php
+++ b/modules/Fediverse/Controllers/PostController.php
@@ -259,7 +259,7 @@ class PostController extends Controller
         }
 
         return redirect()->to(
-            str_replace('{uri}', urlencode($this->post->uri), $data->links[$ostatusKey]->template),
+            str_replace('{uri}', urlencode($this->post->uri), (string) $data->links[$ostatusKey]->template),
         );
     }
 
diff --git a/modules/Fediverse/Models/PostModel.php b/modules/Fediverse/Models/PostModel.php
index 94f2130c9d9099c92fdf68738be88c399d72aeed..3497e85b9e2875908106454650c8d579947227c3 100644
--- a/modules/Fediverse/Models/PostModel.php
+++ b/modules/Fediverse/Models/PostModel.php
@@ -11,7 +11,6 @@ declare(strict_types=1);
 namespace Modules\Fediverse\Models;
 
 use CodeIgniter\Database\BaseResult;
-use CodeIgniter\Database\Query;
 use CodeIgniter\Events\Events;
 use CodeIgniter\HTTP\URI;
 use CodeIgniter\I18n\Time;
@@ -230,7 +229,7 @@ class PostModel extends BaseUuidModel
         return $found;
     }
 
-    public function addPreviewCard(string $postId, int $previewCardId): Query | bool
+    public function addPreviewCard(string $postId, int $previewCardId): bool
     {
         return $this->db->table(config('Fediverse')->tablesPrefix . 'posts_preview_cards')
             ->insert([
@@ -249,7 +248,7 @@ class PostModel extends BaseUuidModel
         Post $post,
         bool $createPreviewCard = true,
         bool $registerActivity = true
-    ): string | false {
+    ): bool|int|object|string {
         helper('fediverse');
 
         $this->db->transStart();
diff --git a/package-lock.json b/package-lock.json
index 1831f5ab20e258fd6d892f320d6fe5341698cd6b..f50893859efe2f8b2f18327eddf427fe65a766d2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -42,7 +42,7 @@
         "@tailwindcss/forms": "^0.5.3",
         "@tailwindcss/line-clamp": "^0.4.2",
         "@tailwindcss/typography": "^0.5.7",
-        "@types/leaflet": "^1.8.0",
+        "@types/leaflet": "^1.9.0",
         "@types/marked": "^4.0.7",
         "@types/wavesurfer.js": "^6.0.3",
         "@typescript-eslint/eslint-plugin": "^5.40.0",
@@ -64,8 +64,8 @@
         "prettier": "2.7.1",
         "prettier-plugin-organize-imports": "^3.1.1",
         "semantic-release": "^19.0.5",
-        "stylelint": "^14.13.0",
-        "stylelint-config-standard": "^28.0.0",
+        "stylelint": "^14.14.0",
+        "stylelint-config-standard": "^29.0.0",
         "svgo": "^2.8.0",
         "tailwindcss": "^3.1.8",
         "typescript": "^4.8.4",
@@ -2460,6 +2460,22 @@
         "postcss-selector-parser": "^6.0.10"
       }
     },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz",
+      "integrity": "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/@eslint/eslintrc": {
       "version": "1.3.3",
       "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz",
@@ -3508,9 +3524,9 @@
       }
     },
     "node_modules/@types/leaflet": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.8.0.tgz",
-      "integrity": "sha512-+sXFmiJTFdhaXXIGFlV5re9AdqtAODoXbGAvxx02e5SHXL3ir7ClP5J7pahO8VmzKY3dth4RUS1nf2BTT+DW1A==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.0.tgz",
+      "integrity": "sha512-7LeOSj7EloC5UcyOMo+1kc3S1UT3MjJxwqsMT1d2PTyvQz53w0Y0oSSk9nwZnOZubCmBvpSNGceucxiq+ZPEUw==",
       "dev": true,
       "dependencies": {
         "@types/geojson": "*"
@@ -6305,9 +6321,9 @@
       }
     },
     "node_modules/esbuild": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.48.tgz",
-      "integrity": "sha512-w6N1Yn5MtqK2U1/WZTX9ZqUVb8IOLZkZ5AdHkT6x3cHDMVsYWC7WPdiLmx19w3i4Rwzy5LqsEMtVihG3e4rFzA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.54.tgz",
+      "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==",
       "dev": true,
       "hasInstallScript": true,
       "bin": {
@@ -6317,32 +6333,33 @@
         "node": ">=12"
       },
       "optionalDependencies": {
-        "esbuild-android-64": "0.14.48",
-        "esbuild-android-arm64": "0.14.48",
-        "esbuild-darwin-64": "0.14.48",
-        "esbuild-darwin-arm64": "0.14.48",
-        "esbuild-freebsd-64": "0.14.48",
-        "esbuild-freebsd-arm64": "0.14.48",
-        "esbuild-linux-32": "0.14.48",
-        "esbuild-linux-64": "0.14.48",
-        "esbuild-linux-arm": "0.14.48",
-        "esbuild-linux-arm64": "0.14.48",
-        "esbuild-linux-mips64le": "0.14.48",
-        "esbuild-linux-ppc64le": "0.14.48",
-        "esbuild-linux-riscv64": "0.14.48",
-        "esbuild-linux-s390x": "0.14.48",
-        "esbuild-netbsd-64": "0.14.48",
-        "esbuild-openbsd-64": "0.14.48",
-        "esbuild-sunos-64": "0.14.48",
-        "esbuild-windows-32": "0.14.48",
-        "esbuild-windows-64": "0.14.48",
-        "esbuild-windows-arm64": "0.14.48"
+        "@esbuild/linux-loong64": "0.14.54",
+        "esbuild-android-64": "0.14.54",
+        "esbuild-android-arm64": "0.14.54",
+        "esbuild-darwin-64": "0.14.54",
+        "esbuild-darwin-arm64": "0.14.54",
+        "esbuild-freebsd-64": "0.14.54",
+        "esbuild-freebsd-arm64": "0.14.54",
+        "esbuild-linux-32": "0.14.54",
+        "esbuild-linux-64": "0.14.54",
+        "esbuild-linux-arm": "0.14.54",
+        "esbuild-linux-arm64": "0.14.54",
+        "esbuild-linux-mips64le": "0.14.54",
+        "esbuild-linux-ppc64le": "0.14.54",
+        "esbuild-linux-riscv64": "0.14.54",
+        "esbuild-linux-s390x": "0.14.54",
+        "esbuild-netbsd-64": "0.14.54",
+        "esbuild-openbsd-64": "0.14.54",
+        "esbuild-sunos-64": "0.14.54",
+        "esbuild-windows-32": "0.14.54",
+        "esbuild-windows-64": "0.14.54",
+        "esbuild-windows-arm64": "0.14.54"
       }
     },
     "node_modules/esbuild-android-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.48.tgz",
-      "integrity": "sha512-3aMjboap/kqwCUpGWIjsk20TtxVoKck8/4Tu19rubh7t5Ra0Yrpg30Mt1QXXlipOazrEceGeWurXKeFJgkPOUg==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz",
+      "integrity": "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==",
       "cpu": [
         "x64"
       ],
@@ -6356,9 +6373,9 @@
       }
     },
     "node_modules/esbuild-android-arm64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.48.tgz",
-      "integrity": "sha512-vptI3K0wGALiDq+EvRuZotZrJqkYkN5282iAfcffjI5lmGG9G1ta/CIVauhY42MBXwEgDJkweiDcDMRLzBZC4g==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz",
+      "integrity": "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==",
       "cpu": [
         "arm64"
       ],
@@ -6372,9 +6389,9 @@
       }
     },
     "node_modules/esbuild-darwin-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.48.tgz",
-      "integrity": "sha512-gGQZa4+hab2Va/Zww94YbshLuWteyKGD3+EsVon8EWTWhnHFRm5N9NbALNbwi/7hQ/hM1Zm4FuHg+k6BLsl5UA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz",
+      "integrity": "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==",
       "cpu": [
         "x64"
       ],
@@ -6388,9 +6405,9 @@
       }
     },
     "node_modules/esbuild-darwin-arm64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.48.tgz",
-      "integrity": "sha512-bFjnNEXjhZT+IZ8RvRGNJthLWNHV5JkCtuOFOnjvo5pC0sk2/QVk0Qc06g2PV3J0TcU6kaPC3RN9yy9w2PSLEA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz",
+      "integrity": "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==",
       "cpu": [
         "arm64"
       ],
@@ -6404,9 +6421,9 @@
       }
     },
     "node_modules/esbuild-freebsd-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.48.tgz",
-      "integrity": "sha512-1NOlwRxmOsnPcWOGTB10JKAkYSb2nue0oM1AfHWunW/mv3wERfJmnYlGzL3UAOIUXZqW8GeA2mv+QGwq7DToqA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz",
+      "integrity": "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==",
       "cpu": [
         "x64"
       ],
@@ -6420,9 +6437,9 @@
       }
     },
     "node_modules/esbuild-freebsd-arm64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.48.tgz",
-      "integrity": "sha512-gXqKdO8wabVcYtluAbikDH2jhXp+Klq5oCD5qbVyUG6tFiGhrC9oczKq3vIrrtwcxDQqK6+HDYK8Zrd4bCA9Gw==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz",
+      "integrity": "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==",
       "cpu": [
         "arm64"
       ],
@@ -6436,9 +6453,9 @@
       }
     },
     "node_modules/esbuild-linux-32": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.48.tgz",
-      "integrity": "sha512-ghGyDfS289z/LReZQUuuKq9KlTiTspxL8SITBFQFAFRA/IkIvDpnZnCAKTCjGXAmUqroMQfKJXMxyjJA69c/nQ==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz",
+      "integrity": "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==",
       "cpu": [
         "ia32"
       ],
@@ -6452,9 +6469,9 @@
       }
     },
     "node_modules/esbuild-linux-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.48.tgz",
-      "integrity": "sha512-vni3p/gppLMVZLghI7oMqbOZdGmLbbKR23XFARKnszCIBpEMEDxOMNIKPmMItQrmH/iJrL1z8Jt2nynY0bE1ug==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz",
+      "integrity": "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==",
       "cpu": [
         "x64"
       ],
@@ -6468,9 +6485,9 @@
       }
     },
     "node_modules/esbuild-linux-arm": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.48.tgz",
-      "integrity": "sha512-+VfSV7Akh1XUiDNXgqgY1cUP1i2vjI+BmlyXRfVz5AfV3jbpde8JTs5Q9sYgaoq5cWfuKfoZB/QkGOI+QcL1Tw==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz",
+      "integrity": "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==",
       "cpu": [
         "arm"
       ],
@@ -6484,9 +6501,9 @@
       }
     },
     "node_modules/esbuild-linux-arm64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.48.tgz",
-      "integrity": "sha512-3CFsOlpoxlKPRevEHq8aAntgYGYkE1N9yRYAcPyng/p4Wyx0tPR5SBYsxLKcgPB9mR8chHEhtWYz6EZ+H199Zw==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz",
+      "integrity": "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==",
       "cpu": [
         "arm64"
       ],
@@ -6500,9 +6517,9 @@
       }
     },
     "node_modules/esbuild-linux-mips64le": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.48.tgz",
-      "integrity": "sha512-cs0uOiRlPp6ymknDnjajCgvDMSsLw5mST2UXh+ZIrXTj2Ifyf2aAP3Iw4DiqgnyYLV2O/v/yWBJx+WfmKEpNLA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz",
+      "integrity": "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==",
       "cpu": [
         "mips64el"
       ],
@@ -6516,9 +6533,9 @@
       }
     },
     "node_modules/esbuild-linux-ppc64le": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.48.tgz",
-      "integrity": "sha512-+2F0vJMkuI0Wie/wcSPDCqXvSFEELH7Jubxb7mpWrA/4NpT+/byjxDz0gG6R1WJoeDefcrMfpBx4GFNN1JQorQ==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz",
+      "integrity": "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==",
       "cpu": [
         "ppc64"
       ],
@@ -6532,9 +6549,9 @@
       }
     },
     "node_modules/esbuild-linux-riscv64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.48.tgz",
-      "integrity": "sha512-BmaK/GfEE+5F2/QDrIXteFGKnVHGxlnK9MjdVKMTfvtmudjY3k2t8NtlY4qemKSizc+QwyombGWTBDc76rxePA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz",
+      "integrity": "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==",
       "cpu": [
         "riscv64"
       ],
@@ -6548,9 +6565,9 @@
       }
     },
     "node_modules/esbuild-linux-s390x": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.48.tgz",
-      "integrity": "sha512-tndw/0B9jiCL+KWKo0TSMaUm5UWBLsfCKVdbfMlb3d5LeV9WbijZ8Ordia8SAYv38VSJWOEt6eDCdOx8LqkC4g==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz",
+      "integrity": "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==",
       "cpu": [
         "s390x"
       ],
@@ -6564,9 +6581,9 @@
       }
     },
     "node_modules/esbuild-netbsd-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.48.tgz",
-      "integrity": "sha512-V9hgXfwf/T901Lr1wkOfoevtyNkrxmMcRHyticybBUHookznipMOHoF41Al68QBsqBxnITCEpjjd4yAos7z9Tw==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz",
+      "integrity": "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==",
       "cpu": [
         "x64"
       ],
@@ -6580,9 +6597,9 @@
       }
     },
     "node_modules/esbuild-openbsd-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.48.tgz",
-      "integrity": "sha512-+IHf4JcbnnBl4T52egorXMatil/za0awqzg2Vy6FBgPcBpisDWT2sVz/tNdrK9kAqj+GZG/jZdrOkj7wsrNTKA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz",
+      "integrity": "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==",
       "cpu": [
         "x64"
       ],
@@ -6596,9 +6613,9 @@
       }
     },
     "node_modules/esbuild-sunos-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.48.tgz",
-      "integrity": "sha512-77m8bsr5wOpOWbGi9KSqDphcq6dFeJyun8TA+12JW/GAjyfTwVtOnN8DOt6DSPUfEV+ltVMNqtXUeTeMAxl5KA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz",
+      "integrity": "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==",
       "cpu": [
         "x64"
       ],
@@ -6612,9 +6629,9 @@
       }
     },
     "node_modules/esbuild-windows-32": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.48.tgz",
-      "integrity": "sha512-EPgRuTPP8vK9maxpTGDe5lSoIBHGKO/AuxDncg5O3NkrPeLNdvvK8oywB0zGaAZXxYWfNNSHskvvDgmfVTguhg==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz",
+      "integrity": "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==",
       "cpu": [
         "ia32"
       ],
@@ -6628,9 +6645,9 @@
       }
     },
     "node_modules/esbuild-windows-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.48.tgz",
-      "integrity": "sha512-YmpXjdT1q0b8ictSdGwH3M8VCoqPpK1/UArze3X199w6u8hUx3V8BhAi1WjbsfDYRBanVVtduAhh2sirImtAvA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz",
+      "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==",
       "cpu": [
         "x64"
       ],
@@ -6644,9 +6661,9 @@
       }
     },
     "node_modules/esbuild-windows-arm64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.48.tgz",
-      "integrity": "sha512-HHaOMCsCXp0rz5BT2crTka6MPWVno121NKApsGs/OIW5QC0ggC69YMGs1aJct9/9FSUF4A1xNE/cLvgB5svR4g==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz",
+      "integrity": "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==",
       "cpu": [
         "arm64"
       ],
@@ -12993,9 +13010,9 @@
       }
     },
     "node_modules/postcss": {
-      "version": "8.4.16",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz",
-      "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==",
+      "version": "8.4.18",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz",
+      "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==",
       "funding": [
         {
           "type": "opencollective",
@@ -14686,9 +14703,9 @@
       }
     },
     "node_modules/rollup": {
-      "version": "2.75.7",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.75.7.tgz",
-      "integrity": "sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ==",
+      "version": "2.79.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
+      "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
       "dev": true,
       "bin": {
         "rollup": "dist/bin/rollup"
@@ -15524,9 +15541,9 @@
       }
     },
     "node_modules/stylelint": {
-      "version": "14.13.0",
-      "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.13.0.tgz",
-      "integrity": "sha512-NJSAdloiAB/jgVJKxMR90mWlctvmeBFGFVUvyKngi9+j/qPSJ5ZB+u8jOmGbLTnS7OHrII9NFGehPRyar8U5vg==",
+      "version": "14.14.0",
+      "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.14.0.tgz",
+      "integrity": "sha512-yUI+4xXfPHVnueYddSQ/e1GuEA/2wVhWQbGj16AmWLtQJtn28lVxfS4b0CsWyVRPgd3Auzi0NXOthIEUhtQmmA==",
       "dev": true,
       "dependencies": {
         "@csstools/selector-specificity": "^2.0.2",
@@ -15552,7 +15569,7 @@
         "micromatch": "^4.0.5",
         "normalize-path": "^3.0.0",
         "picocolors": "^1.0.0",
-        "postcss": "^8.4.16",
+        "postcss": "^8.4.17",
         "postcss-media-query-parser": "^0.2.3",
         "postcss-resolve-nested-selector": "^0.1.1",
         "postcss-safe-parser": "^6.0.0",
@@ -15589,15 +15606,15 @@
       }
     },
     "node_modules/stylelint-config-standard": {
-      "version": "28.0.0",
-      "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-28.0.0.tgz",
-      "integrity": "sha512-q/StuowDdDmFCravzGHAwgS9pjX0bdOQUEBBDIkIWsQuYGgYz/xsO8CM6eepmIQ1fc5bKdDVimlJZ6MoOUcJ5Q==",
+      "version": "29.0.0",
+      "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-29.0.0.tgz",
+      "integrity": "sha512-uy8tZLbfq6ZrXy4JKu3W+7lYLgRQBxYTUUB88vPgQ+ZzAxdrvcaSUW9hOMNLYBnwH+9Kkj19M2DHdZ4gKwI7tg==",
       "dev": true,
       "dependencies": {
         "stylelint-config-recommended": "^9.0.0"
       },
       "peerDependencies": {
-        "stylelint": "^14.11.0"
+        "stylelint": "^14.14.0"
       }
     },
     "node_modules/stylelint/node_modules/balanced-match": {
@@ -18856,6 +18873,13 @@
       "dev": true,
       "requires": {}
     },
+    "@esbuild/linux-loong64": {
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz",
+      "integrity": "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==",
+      "dev": true,
+      "optional": true
+    },
     "@eslint/eslintrc": {
       "version": "1.3.3",
       "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz",
@@ -19647,9 +19671,9 @@
       }
     },
     "@types/leaflet": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.8.0.tgz",
-      "integrity": "sha512-+sXFmiJTFdhaXXIGFlV5re9AdqtAODoXbGAvxx02e5SHXL3ir7ClP5J7pahO8VmzKY3dth4RUS1nf2BTT+DW1A==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.0.tgz",
+      "integrity": "sha512-7LeOSj7EloC5UcyOMo+1kc3S1UT3MjJxwqsMT1d2PTyvQz53w0Y0oSSk9nwZnOZubCmBvpSNGceucxiq+ZPEUw==",
       "dev": true,
       "requires": {
         "@types/geojson": "*"
@@ -21577,170 +21601,171 @@
       }
     },
     "esbuild": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.48.tgz",
-      "integrity": "sha512-w6N1Yn5MtqK2U1/WZTX9ZqUVb8IOLZkZ5AdHkT6x3cHDMVsYWC7WPdiLmx19w3i4Rwzy5LqsEMtVihG3e4rFzA==",
-      "dev": true,
-      "requires": {
-        "esbuild-android-64": "0.14.48",
-        "esbuild-android-arm64": "0.14.48",
-        "esbuild-darwin-64": "0.14.48",
-        "esbuild-darwin-arm64": "0.14.48",
-        "esbuild-freebsd-64": "0.14.48",
-        "esbuild-freebsd-arm64": "0.14.48",
-        "esbuild-linux-32": "0.14.48",
-        "esbuild-linux-64": "0.14.48",
-        "esbuild-linux-arm": "0.14.48",
-        "esbuild-linux-arm64": "0.14.48",
-        "esbuild-linux-mips64le": "0.14.48",
-        "esbuild-linux-ppc64le": "0.14.48",
-        "esbuild-linux-riscv64": "0.14.48",
-        "esbuild-linux-s390x": "0.14.48",
-        "esbuild-netbsd-64": "0.14.48",
-        "esbuild-openbsd-64": "0.14.48",
-        "esbuild-sunos-64": "0.14.48",
-        "esbuild-windows-32": "0.14.48",
-        "esbuild-windows-64": "0.14.48",
-        "esbuild-windows-arm64": "0.14.48"
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.54.tgz",
+      "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==",
+      "dev": true,
+      "requires": {
+        "@esbuild/linux-loong64": "0.14.54",
+        "esbuild-android-64": "0.14.54",
+        "esbuild-android-arm64": "0.14.54",
+        "esbuild-darwin-64": "0.14.54",
+        "esbuild-darwin-arm64": "0.14.54",
+        "esbuild-freebsd-64": "0.14.54",
+        "esbuild-freebsd-arm64": "0.14.54",
+        "esbuild-linux-32": "0.14.54",
+        "esbuild-linux-64": "0.14.54",
+        "esbuild-linux-arm": "0.14.54",
+        "esbuild-linux-arm64": "0.14.54",
+        "esbuild-linux-mips64le": "0.14.54",
+        "esbuild-linux-ppc64le": "0.14.54",
+        "esbuild-linux-riscv64": "0.14.54",
+        "esbuild-linux-s390x": "0.14.54",
+        "esbuild-netbsd-64": "0.14.54",
+        "esbuild-openbsd-64": "0.14.54",
+        "esbuild-sunos-64": "0.14.54",
+        "esbuild-windows-32": "0.14.54",
+        "esbuild-windows-64": "0.14.54",
+        "esbuild-windows-arm64": "0.14.54"
       }
     },
     "esbuild-android-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.48.tgz",
-      "integrity": "sha512-3aMjboap/kqwCUpGWIjsk20TtxVoKck8/4Tu19rubh7t5Ra0Yrpg30Mt1QXXlipOazrEceGeWurXKeFJgkPOUg==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz",
+      "integrity": "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==",
       "dev": true,
       "optional": true
     },
     "esbuild-android-arm64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.48.tgz",
-      "integrity": "sha512-vptI3K0wGALiDq+EvRuZotZrJqkYkN5282iAfcffjI5lmGG9G1ta/CIVauhY42MBXwEgDJkweiDcDMRLzBZC4g==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz",
+      "integrity": "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==",
       "dev": true,
       "optional": true
     },
     "esbuild-darwin-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.48.tgz",
-      "integrity": "sha512-gGQZa4+hab2Va/Zww94YbshLuWteyKGD3+EsVon8EWTWhnHFRm5N9NbALNbwi/7hQ/hM1Zm4FuHg+k6BLsl5UA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz",
+      "integrity": "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==",
       "dev": true,
       "optional": true
     },
     "esbuild-darwin-arm64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.48.tgz",
-      "integrity": "sha512-bFjnNEXjhZT+IZ8RvRGNJthLWNHV5JkCtuOFOnjvo5pC0sk2/QVk0Qc06g2PV3J0TcU6kaPC3RN9yy9w2PSLEA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz",
+      "integrity": "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==",
       "dev": true,
       "optional": true
     },
     "esbuild-freebsd-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.48.tgz",
-      "integrity": "sha512-1NOlwRxmOsnPcWOGTB10JKAkYSb2nue0oM1AfHWunW/mv3wERfJmnYlGzL3UAOIUXZqW8GeA2mv+QGwq7DToqA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz",
+      "integrity": "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==",
       "dev": true,
       "optional": true
     },
     "esbuild-freebsd-arm64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.48.tgz",
-      "integrity": "sha512-gXqKdO8wabVcYtluAbikDH2jhXp+Klq5oCD5qbVyUG6tFiGhrC9oczKq3vIrrtwcxDQqK6+HDYK8Zrd4bCA9Gw==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz",
+      "integrity": "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-32": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.48.tgz",
-      "integrity": "sha512-ghGyDfS289z/LReZQUuuKq9KlTiTspxL8SITBFQFAFRA/IkIvDpnZnCAKTCjGXAmUqroMQfKJXMxyjJA69c/nQ==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz",
+      "integrity": "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.48.tgz",
-      "integrity": "sha512-vni3p/gppLMVZLghI7oMqbOZdGmLbbKR23XFARKnszCIBpEMEDxOMNIKPmMItQrmH/iJrL1z8Jt2nynY0bE1ug==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz",
+      "integrity": "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-arm": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.48.tgz",
-      "integrity": "sha512-+VfSV7Akh1XUiDNXgqgY1cUP1i2vjI+BmlyXRfVz5AfV3jbpde8JTs5Q9sYgaoq5cWfuKfoZB/QkGOI+QcL1Tw==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz",
+      "integrity": "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-arm64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.48.tgz",
-      "integrity": "sha512-3CFsOlpoxlKPRevEHq8aAntgYGYkE1N9yRYAcPyng/p4Wyx0tPR5SBYsxLKcgPB9mR8chHEhtWYz6EZ+H199Zw==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz",
+      "integrity": "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-mips64le": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.48.tgz",
-      "integrity": "sha512-cs0uOiRlPp6ymknDnjajCgvDMSsLw5mST2UXh+ZIrXTj2Ifyf2aAP3Iw4DiqgnyYLV2O/v/yWBJx+WfmKEpNLA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz",
+      "integrity": "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-ppc64le": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.48.tgz",
-      "integrity": "sha512-+2F0vJMkuI0Wie/wcSPDCqXvSFEELH7Jubxb7mpWrA/4NpT+/byjxDz0gG6R1WJoeDefcrMfpBx4GFNN1JQorQ==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz",
+      "integrity": "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-riscv64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.48.tgz",
-      "integrity": "sha512-BmaK/GfEE+5F2/QDrIXteFGKnVHGxlnK9MjdVKMTfvtmudjY3k2t8NtlY4qemKSizc+QwyombGWTBDc76rxePA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz",
+      "integrity": "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==",
       "dev": true,
       "optional": true
     },
     "esbuild-linux-s390x": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.48.tgz",
-      "integrity": "sha512-tndw/0B9jiCL+KWKo0TSMaUm5UWBLsfCKVdbfMlb3d5LeV9WbijZ8Ordia8SAYv38VSJWOEt6eDCdOx8LqkC4g==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz",
+      "integrity": "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==",
       "dev": true,
       "optional": true
     },
     "esbuild-netbsd-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.48.tgz",
-      "integrity": "sha512-V9hgXfwf/T901Lr1wkOfoevtyNkrxmMcRHyticybBUHookznipMOHoF41Al68QBsqBxnITCEpjjd4yAos7z9Tw==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz",
+      "integrity": "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==",
       "dev": true,
       "optional": true
     },
     "esbuild-openbsd-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.48.tgz",
-      "integrity": "sha512-+IHf4JcbnnBl4T52egorXMatil/za0awqzg2Vy6FBgPcBpisDWT2sVz/tNdrK9kAqj+GZG/jZdrOkj7wsrNTKA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz",
+      "integrity": "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==",
       "dev": true,
       "optional": true
     },
     "esbuild-sunos-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.48.tgz",
-      "integrity": "sha512-77m8bsr5wOpOWbGi9KSqDphcq6dFeJyun8TA+12JW/GAjyfTwVtOnN8DOt6DSPUfEV+ltVMNqtXUeTeMAxl5KA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz",
+      "integrity": "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==",
       "dev": true,
       "optional": true
     },
     "esbuild-windows-32": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.48.tgz",
-      "integrity": "sha512-EPgRuTPP8vK9maxpTGDe5lSoIBHGKO/AuxDncg5O3NkrPeLNdvvK8oywB0zGaAZXxYWfNNSHskvvDgmfVTguhg==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz",
+      "integrity": "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==",
       "dev": true,
       "optional": true
     },
     "esbuild-windows-64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.48.tgz",
-      "integrity": "sha512-YmpXjdT1q0b8ictSdGwH3M8VCoqPpK1/UArze3X199w6u8hUx3V8BhAi1WjbsfDYRBanVVtduAhh2sirImtAvA==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz",
+      "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==",
       "dev": true,
       "optional": true
     },
     "esbuild-windows-arm64": {
-      "version": "0.14.48",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.48.tgz",
-      "integrity": "sha512-HHaOMCsCXp0rz5BT2crTka6MPWVno121NKApsGs/OIW5QC0ggC69YMGs1aJct9/9FSUF4A1xNE/cLvgB5svR4g==",
+      "version": "0.14.54",
+      "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz",
+      "integrity": "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==",
       "dev": true,
       "optional": true
     },
@@ -26047,9 +26072,9 @@
       }
     },
     "postcss": {
-      "version": "8.4.16",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz",
-      "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==",
+      "version": "8.4.18",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz",
+      "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==",
       "requires": {
         "nanoid": "^3.3.4",
         "picocolors": "^1.0.0",
@@ -27087,9 +27112,9 @@
       }
     },
     "rollup": {
-      "version": "2.75.7",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.75.7.tgz",
-      "integrity": "sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ==",
+      "version": "2.79.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
+      "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
       "dev": true,
       "requires": {
         "fsevents": "~2.3.2"
@@ -27687,9 +27712,9 @@
       }
     },
     "stylelint": {
-      "version": "14.13.0",
-      "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.13.0.tgz",
-      "integrity": "sha512-NJSAdloiAB/jgVJKxMR90mWlctvmeBFGFVUvyKngi9+j/qPSJ5ZB+u8jOmGbLTnS7OHrII9NFGehPRyar8U5vg==",
+      "version": "14.14.0",
+      "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.14.0.tgz",
+      "integrity": "sha512-yUI+4xXfPHVnueYddSQ/e1GuEA/2wVhWQbGj16AmWLtQJtn28lVxfS4b0CsWyVRPgd3Auzi0NXOthIEUhtQmmA==",
       "dev": true,
       "requires": {
         "@csstools/selector-specificity": "^2.0.2",
@@ -27715,7 +27740,7 @@
         "micromatch": "^4.0.5",
         "normalize-path": "^3.0.0",
         "picocolors": "^1.0.0",
-        "postcss": "^8.4.16",
+        "postcss": "^8.4.17",
         "postcss-media-query-parser": "^0.2.3",
         "postcss-resolve-nested-selector": "^0.1.1",
         "postcss-safe-parser": "^6.0.0",
@@ -27780,9 +27805,9 @@
       "requires": {}
     },
     "stylelint-config-standard": {
-      "version": "28.0.0",
-      "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-28.0.0.tgz",
-      "integrity": "sha512-q/StuowDdDmFCravzGHAwgS9pjX0bdOQUEBBDIkIWsQuYGgYz/xsO8CM6eepmIQ1fc5bKdDVimlJZ6MoOUcJ5Q==",
+      "version": "29.0.0",
+      "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-29.0.0.tgz",
+      "integrity": "sha512-uy8tZLbfq6ZrXy4JKu3W+7lYLgRQBxYTUUB88vPgQ+ZzAxdrvcaSUW9hOMNLYBnwH+9Kkj19M2DHdZ4gKwI7tg==",
       "dev": true,
       "requires": {
         "stylelint-config-recommended": "^9.0.0"
diff --git a/package.json b/package.json
index e2c2cb63d9adf11dbffab40febf5dcf85784c284..34432201cf140b76aeff44fcabdf6f056a3a7767 100644
--- a/package.json
+++ b/package.json
@@ -60,7 +60,7 @@
     "@tailwindcss/forms": "^0.5.3",
     "@tailwindcss/line-clamp": "^0.4.2",
     "@tailwindcss/typography": "^0.5.7",
-    "@types/leaflet": "^1.8.0",
+    "@types/leaflet": "^1.9.0",
     "@types/marked": "^4.0.7",
     "@types/wavesurfer.js": "^6.0.3",
     "@typescript-eslint/eslint-plugin": "^5.40.0",
@@ -82,8 +82,8 @@
     "prettier": "2.7.1",
     "prettier-plugin-organize-imports": "^3.1.1",
     "semantic-release": "^19.0.5",
-    "stylelint": "^14.13.0",
-    "stylelint-config-standard": "^28.0.0",
+    "stylelint": "^14.14.0",
+    "stylelint-config-standard": "^29.0.0",
     "svgo": "^2.8.0",
     "tailwindcss": "^3.1.8",
     "typescript": "^4.8.4",
diff --git a/preload.php b/preload.php
index 5840d8040142e0c2bb9a88c3b6928d55497aea8f..95d7f1e79b295f93dfd3f1e3d7469d8826b939e0 100644
--- a/preload.php
+++ b/preload.php
@@ -1,12 +1,14 @@
 <?php
 
+declare(strict_types=1);
+
 /**
  * This file is part of CodeIgniter 4 framework.
  *
  * (c) CodeIgniter Foundation <admin@codeigniter.com>
  *
- * For the full copyright and license information, please view
- * the LICENSE file that was distributed with this source code.
+ * For the full copyright and license information, please view the LICENSE file that was distributed with this source
+ * code.
  */
 
 /*
@@ -75,12 +77,6 @@ class preload
         $this->loadAutoloader();
     }
 
-    private function loadAutoloader(): void
-    {
-        $paths = new Config\Paths();
-        require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstrap.php';
-    }
-
     /**
      * Load PHP files.
      */
@@ -88,12 +84,8 @@ class preload
     {
         foreach ($this->paths as $path) {
             $directory = new RecursiveDirectoryIterator($path['include']);
-            $fullTree  = new RecursiveIteratorIterator($directory);
-            $phpFiles  = new RegexIterator(
-                $fullTree,
-                '/.+((?<!Test)+\.php$)/i',
-                RecursiveRegexIterator::GET_MATCH
-            );
+            $fullTree = new RecursiveIteratorIterator($directory);
+            $phpFiles = new RegexIterator($fullTree, '/.+((?<!Test)+\.php$)/i', RecursiveRegexIterator::GET_MATCH);
 
             foreach ($phpFiles as $key => $file) {
                 foreach ($path['exclude'] as $exclude) {
@@ -107,6 +99,12 @@ class preload
             }
         }
     }
+
+    private function loadAutoloader(): void
+    {
+        $paths = new Config\Paths();
+        require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstrap.php';
+    }
 }
 
 (new preload())->load();
diff --git a/public/index.php b/public/index.php
index b80d9fbf47ee5188f0c7f6ca00770535a20a529d..d8fe40cc70c1b0018521f972e609f23db1d6de66 100644
--- a/public/index.php
+++ b/public/index.php
@@ -7,7 +7,7 @@ use Config\Paths;
 use Config\Services;
 
 // Check PHP version.
-$minPhpVersion = '8.0'; // If you update this, don't forget to update `spark`.
+$minPhpVersion = '8.1'; // If you update this, don't forget to update `spark`.
 if (version_compare(PHP_VERSION, $minPhpVersion, '<')) {
     $message = sprintf(
         'Your PHP version must be %s or higher to run CodeIgniter. Current version: %s',
diff --git a/rector.php b/rector.php
index 96dad228bcd29d6766f4af7f3ab9a4577ae4ba2f..e95004884fe2a985f38d1d1420ccf02155fb4680 100644
--- a/rector.php
+++ b/rector.php
@@ -18,21 +18,14 @@ use Rector\Php71\Rector\FuncCall\RemoveExtraParametersRector;
 use Rector\Set\ValueObject\SetList;
 
 return static function (RectorConfig $rectorConfig): void {
-    // get parameters
-    $rectorConfig->paths([
-        __DIR__ . '/app',
-        __DIR__ . '/modules',
-        __DIR__ . '/tests',
-        __DIR__ . '/public',
-    ]);
+    $rectorConfig->paths([__DIR__ . '/app', __DIR__ . '/modules', __DIR__ . '/tests', __DIR__ . '/public']);
 
     // do you need to include constants, class aliases or custom autoloader? files listed will be executed
-    $rectorConfig->bootstrapFiles([
-        __DIR__ . '/vendor/codeigniter4/framework/system/Test/bootstrap.php',
-    ]);
+    $rectorConfig->bootstrapFiles([__DIR__ . '/vendor/codeigniter4/framework/system/Test/bootstrap.php']);
 
     // Define what rule sets will be applied
-    $rectorConfig->sets([SetList::PHP_80,
+    $rectorConfig->sets([
+        SetList::PHP_81,
         SetList::TYPE_DECLARATION,
         SetList::TYPE_DECLARATION_STRICT,
         SetList::CODE_QUALITY,
@@ -44,7 +37,7 @@ return static function (RectorConfig $rectorConfig): void {
     // auto import fully qualified class names
     $rectorConfig->importNames();
 
-    $rectorConfig->phpVersion(PhpVersion::PHP_80);
+    $rectorConfig->phpVersion(PhpVersion::PHP_81);
 
     $rectorConfig->skip([
         // .mp3 files were somehow processed by rector, so skip all media files
@@ -69,14 +62,9 @@ return static function (RectorConfig $rectorConfig): void {
             __DIR__ . '/app/Language/*',
             __DIR__ . '/modules/*/Language/*',
         ],
-        SymplifyQuoteEscapeRector::class => [
-            __DIR__ . '/app/Language/*',
-            __DIR__ . '/modules/*/Language/*',
-        ],
+        SymplifyQuoteEscapeRector::class => [__DIR__ . '/app/Language/*', __DIR__ . '/modules/*/Language/*'],
 
-        NewlineAfterStatementRector::class => [
-            __DIR__ . '/app/Views',
-        ]
+        NewlineAfterStatementRector::class => [__DIR__ . '/app/Views'],
     ]);
 
     // Path to phpstan with extensions, that PHPStan in Rector uses to determine types
diff --git a/spark b/spark
index 306cf95732be2a5859e9ec04e38f32a40085ded4..ceed30a1ea61b7054740d970be43548a21d1276a 100644
--- a/spark
+++ b/spark
@@ -6,8 +6,8 @@
  *
  * (c) CodeIgniter Foundation <admin@codeigniter.com>
  *
- * For the full copyright and license information, please view
- * the LICENSE file that was distributed with this source code.
+ * For the full copyright and license information, please view the LICENSE file that was distributed with this source
+ * code.
  */
 
 /*
@@ -27,7 +27,7 @@ if (strpos(PHP_SAPI, 'cgi') === 0) {
 }
 
 // Check PHP version.
-$minPhpVersion = '8.0'; // If you update this, don't forget to update `public/index.php`.
+$minPhpVersion = '8.1'; // If you update this, don't forget to update `public/index.php`.
 if (version_compare(PHP_VERSION, $minPhpVersion, '<')) {
     $message = sprintf(
         'Your PHP version must be %s or higher to run CodeIgniter. Current version: %s',
diff --git a/tests/modules/Api/Rest/V1/PodcastTest.php b/tests/modules/Api/Rest/V1/PodcastTest.php
index ba6bc019b87c081be6ed27024b9f1a4cb0801f4e..6131ad900888dea663d9f9facf9a767d3fc8df5e 100644
--- a/tests/modules/Api/Rest/V1/PodcastTest.php
+++ b/tests/modules/Api/Rest/V1/PodcastTest.php
@@ -44,7 +44,7 @@ class PodcastTest extends CIUnitTestCase
      */
     private array $podcast = [];
 
-    private string $podcastApiUrl;
+    private readonly string $podcastApiUrl;
 
     /**
      * @param array<mixed> $data