Repository: SergeWilfried/doohi
Pull request #5: Update middleware.ts
Author: login: SergeWilfried
Created: 2025-03-08T14:43:21Z | Merged: 2025-03-08T15:30:06Z



<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Enhanced security measures now safeguard protected areas, ensuring users encounter proper notifications when access is denied.
  - Introduced a new dependency for improved functionality.

- **Chores**
  - Added a new environment variable for configuration.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/.env b/.env
index 5fb7ca860..d3b3e9912 100644
--- a/.env
+++ b/.env
@@ -22,3 +22,6 @@ CLERK_SECRET_KEY=your_clerk_secret_key
 STRIPE_SECRET_KEY=your_stripe_secret_key
 STRIPE_WEBHOOK_SECRET=your_stripe_webhook_secret
 ######## [END] SENSITIVE DATA
+
+#ARCJET
+ARCJET_KEY=YOUR-KEY
diff --git a/package-lock.json b/package-lock.json
index aeedb84bc..df6102cc5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,7 @@
       "name": "saas-boilerplate",
       "version": "1.7.4",
       "dependencies": {
+        "@arcjet/next": "1.0.0-beta.3",
         "@clerk/localizations": "^3.2.1",
         "@clerk/nextjs": "^5.7.3",
         "@clerk/themes": "^2.1.36",
@@ -15,19 +16,26 @@
         "@hookform/resolvers": "^3.9.0",
         "@logtail/pino": "^0.5.2",
         "@radix-ui/react-accordion": "^1.2.1",
+        "@radix-ui/react-dialog": "^1.1.6",
         "@radix-ui/react-dropdown-menu": "^2.1.2",
         "@radix-ui/react-icons": "^1.3.0",
-        "@radix-ui/react-label": "^2.1.0",
+        "@radix-ui/react-label": "^2.1.2",
+        "@radix-ui/react-progress": "^1.1.2",
+        "@radix-ui/react-select": "^2.1.6",
         "@radix-ui/react-separator": "^1.1.0",
-        "@radix-ui/react-slot": "^1.1.0",
+        "@radix-ui/react-slot": "^1.1.2",
+        "@radix-ui/react-tabs": "^1.1.3",
         "@radix-ui/react-tooltip": "^1.1.3",
         "@sentry/nextjs": "^8.34.0",
         "@spotlightjs/spotlight": "^2.5.0",
         "@t3-oss/env-nextjs": "^0.11.1",
+        "@tailwindcss/typography": "^0.5.16",
         "@tanstack/react-table": "^8.20.5",
+        "canvas-confetti": "^1.9.3",
         "class-variance-authority": "^0.7.0",
         "clsx": "^2.1.1",
         "drizzle-orm": "^0.35.1",
+        "geist": "^1.3.1",
         "lucide-react": "^0.453.0",
         "next": "^14.2.15",
         "next-intl": "^3.21.1",
@@ -124,7 +132,6 @@
       "version": "5.2.0",
       "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
       "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">=10"
@@ -277,6 +284,131 @@
         "url": "https://github.com/sponsors/antfu"
       }
     },
+    "node_modules/@arcjet/analyze": {
+      "version": "1.0.0-beta.3",
+      "resolved": "https://registry.npmjs.org/@arcjet/analyze/-/analyze-1.0.0-beta.3.tgz",
+      "integrity": "sha512-CbdvkAOYPgQVM+pF7JsRvvusEUs09u+8P7dIGT16jUZyQGIO2v4sUViDckoNgNidFCDwcNlJFHKwHJUVZjCFyQ==",
+      "dependencies": {
+        "@arcjet/analyze-wasm": "1.0.0-beta.3",
+        "@arcjet/protocol": "1.0.0-beta.3"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@arcjet/analyze-wasm": {
+      "version": "1.0.0-beta.3",
+      "resolved": "https://registry.npmjs.org/@arcjet/analyze-wasm/-/analyze-wasm-1.0.0-beta.3.tgz",
+      "integrity": "sha512-JV4FxHnL2QnLmF5VgYhgGL0aAmWa0kP+gut20fAMuEby3jyqCdxzE/+vKfZEPNdKQLO46H5XCvjHnAx18nmOtw==",
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@arcjet/duration": {
+      "version": "1.0.0-beta.3",
+      "resolved": "https://registry.npmjs.org/@arcjet/duration/-/duration-1.0.0-beta.3.tgz",
+      "integrity": "sha512-1G5qcuz1xhxEUztYpAMQz2Jp2BPch2A9hn1aK/04hoGrpKi79z1hjoTglSftbhAJvE+wwYN764VcCFjmBK793g==",
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@arcjet/env": {
+      "version": "1.0.0-beta.3",
+      "resolved": "https://registry.npmjs.org/@arcjet/env/-/env-1.0.0-beta.3.tgz",
+      "integrity": "sha512-oUppsM8wL6I1cte9SJc/aZ3OI73hDnGDUTNXYN+Q2bfhuDVyJa0j6y/uQBG0FduPYg1Clwqy/39XS1u4MOQD8g==",
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@arcjet/headers": {
+      "version": "1.0.0-beta.3",
+      "resolved": "https://registry.npmjs.org/@arcjet/headers/-/headers-1.0.0-beta.3.tgz",
+      "integrity": "sha512-bo+0k0cf8A9ToqMJKSiyTpK4oYHY7xUsTibvM3WZkNu1QXrjM1y+P3tEwcyn9nMHSEtlRkr0TPJPerRqm3Z9fg==",
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@arcjet/ip": {
+      "version": "1.0.0-beta.3",
+      "resolved": "https://registry.npmjs.org/@arcjet/ip/-/ip-1.0.0-beta.3.tgz",
+      "integrity": "sha512-z2yAfJwZTyXXlEJJFXOypB0FYEzPaG1YXeRpHvrfrBhl1pZFTSX70PJkz1uIVM0Cq+H5FpMr3QdvjVzdFNLHBw==",
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@arcjet/logger": {
+      "version": "1.0.0-beta.3",
+      "resolved": "https://registry.npmjs.org/@arcjet/logger/-/logger-1.0.0-beta.3.tgz",
+      "integrity": "sha512-KWYsWnSn6kFNT5pS85V+bFd3gu+x0Z+UbaclpQqfCrBoS08dUAZQbt+IFU1KVazgAMXwZ+OC16llF9Z9Ne1dUQ==",
+      "dependencies": {
+        "@arcjet/sprintf": "1.0.0-beta.3"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@arcjet/next": {
+      "version": "1.0.0-beta.3",
+      "resolved": "https://registry.npmjs.org/@arcjet/next/-/next-1.0.0-beta.3.tgz",
+      "integrity": "sha512-IchLspfeIuOhy1a3z8cuvfnYzjl2ehnXNeNWoK0gx1d0URRev2U/7BsUqpPckLbYfFA/kLpfPjcL9f4yMppV0Q==",
+      "dependencies": {
+        "@arcjet/env": "1.0.0-beta.3",
+        "@arcjet/headers": "1.0.0-beta.3",
+        "@arcjet/ip": "1.0.0-beta.3",
+        "@arcjet/logger": "1.0.0-beta.3",
+        "@arcjet/protocol": "1.0.0-beta.3",
+        "@arcjet/transport": "1.0.0-beta.3",
+        "arcjet": "1.0.0-beta.3"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "peerDependencies": {
+        "next": ">=13"
+      }
+    },
+    "node_modules/@arcjet/protocol": {
+      "version": "1.0.0-beta.3",
+      "resolved": "https://registry.npmjs.org/@arcjet/protocol/-/protocol-1.0.0-beta.3.tgz",
+      "integrity": "sha512-BGMAmJszi9D6oaV6t28L/B9Cf8xcWSAQ24l2uYmoipsymBF6Ss7vjQxOzhf1++g0v7CaEZlBPf7HVV/n1Nj4aw==",
+      "dependencies": {
+        "@bufbuild/protobuf": "1.10.0",
+        "@connectrpc/connect": "1.6.1",
+        "typeid-js": "1.2.0"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@arcjet/runtime": {
+      "version": "1.0.0-beta.3",
+      "resolved": "https://registry.npmjs.org/@arcjet/runtime/-/runtime-1.0.0-beta.3.tgz",
+      "integrity": "sha512-Aw4Wj8hCUyrW4AIntd+3QEnTUGTkk8Y6OQMoKrggyDVo3T9Acdij+Bhtma4zWfgwKqFRzj8J650EkCmD9qpFrw==",
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@arcjet/sprintf": {
+      "version": "1.0.0-beta.3",
+      "resolved": "https://registry.npmjs.org/@arcjet/sprintf/-/sprintf-1.0.0-beta.3.tgz",
+      "integrity": "sha512-veWXxhLgYJBf8Jf7PJemfC0xksJrmP/LjzUzZl9qs+asjRUJ4Qrz6NO24focn9b3jCHkRznG/YzDyUDtZ0eePg==",
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@arcjet/transport": {
+      "version": "1.0.0-beta.3",
+      "resolved": "https://registry.npmjs.org/@arcjet/transport/-/transport-1.0.0-beta.3.tgz",
+      "integrity": "sha512-CRdhcEepFCBwd0BmmYMc6fxhWpcw6lQw/g4j7BVdGSPJHIE1HVTiE3pIP6CsSBedb+ihRpD45Cbi/lZD4BDFLQ==",
+      "dependencies": {
+        "@connectrpc/connect": "1.6.1",
+        "@connectrpc/connect-node": "1.6.1",
+        "@connectrpc/connect-web": "1.6.1"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
     "node_modules/@babel/code-frame": {
       "version": "7.25.7",
       "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz",
@@ -2366,6 +2498,11 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/@bufbuild/protobuf": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-1.10.0.tgz",
+      "integrity": "sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag=="
+    },
     "node_modules/@clack/core": {
       "version": "0.3.4",
       "resolved": "https://registry.npmjs.org/@clack/core/-/core-0.3.4.tgz",
@@ -2395,6 +2532,7 @@
     },
     "node_modules/@clack/prompts/node_modules/is-unicode-supported": {
       "version": "1.3.0",
+      "dev": true,
       "inBundle": true,
       "license": "MIT",
       "engines": {
@@ -2845,11 +2983,43 @@
         "node": ">=v18"
       }
     },
+    "node_modules/@connectrpc/connect": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/@connectrpc/connect/-/connect-1.6.1.tgz",
+      "integrity": "sha512-KchMDNtU4CDTdkyf0qG7ugJ6qHTOR/aI7XebYn3OTCNagaDYWiZUVKgRgwH79yeMkpNgvEUaXSK7wKjaBK9b/Q==",
+      "peerDependencies": {
+        "@bufbuild/protobuf": "^1.10.0"
+      }
+    },
+    "node_modules/@connectrpc/connect-node": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/@connectrpc/connect-node/-/connect-node-1.6.1.tgz",
+      "integrity": "sha512-DxcD1wsF/aX9GegjAtl7VbpiZNjVJozy87VbaFoN6AF0Ln1Q757r5dgV59Gz0wmlk5f17txUsrEr1f2inlnnAg==",
+      "dependencies": {
+        "undici": "^5.28.4"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "@bufbuild/protobuf": "^1.10.0",
+        "@connectrpc/connect": "1.6.1"
+      }
+    },
+    "node_modules/@connectrpc/connect-web": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/@connectrpc/connect-web/-/connect-web-1.6.1.tgz",
+      "integrity": "sha512-GVfxQOmt3TtgTaKeXLS/EA2IHa3nHxwe2BCHT7X0Q/0hohM+nP5DDnIItGEjGrGdt3LTTqWqE4s70N4h+qIMlQ==",
+      "peerDependencies": {
+        "@bufbuild/protobuf": "^1.10.0",
+        "@connectrpc/connect": "1.6.1"
+      }
+    },
     "node_modules/@cspotcode/source-map-support": {
       "version": "0.8.1",
       "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
       "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT",
       "dependencies": {
         "@jridgewell/trace-mapping": "0.3.9"
@@ -2862,7 +3032,7 @@
       "version": "0.3.9",
       "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
       "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT",
       "dependencies": {
         "@jridgewell/resolve-uri": "^3.0.3",
@@ -4174,6 +4344,14 @@
         "npm": ">=9.0.0"
       }
     },
+    "node_modules/@fastify/busboy": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
+      "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
+      "engines": {
+        "node": ">=14"
+      }
+    },
     "node_modules/@floating-ui/core": {
       "version": "1.6.8",
       "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz",
@@ -5812,7 +5990,6 @@
       "version": "2.1.5",
       "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
       "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "@nodelib/fs.stat": "2.0.5",
@@ -5826,7 +6003,6 @@
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
       "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">= 8"
@@ -5836,7 +6012,6 @@
       "version": "1.2.8",
       "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
       "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "@nodelib/fs.scandir": "2.1.5",
@@ -7637,6 +7812,11 @@
         "@opentelemetry/api": "^1.3.0"
       }
     },
+    "node_modules/@radix-ui/number": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz",
+      "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ=="
+    },
     "node_modules/@radix-ui/primitive": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz",
@@ -7768,6 +7948,23 @@
         }
       }
     },
+    "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
+      "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.0"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/@radix-ui/react-compose-refs": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz",
@@ -7798,6 +7995,202 @@
         }
       }
     },
+    "node_modules/@radix-ui/react-dialog": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.6.tgz",
+      "integrity": "sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw==",
+      "dependencies": {
+        "@radix-ui/primitive": "1.1.1",
+        "@radix-ui/react-compose-refs": "1.1.1",
+        "@radix-ui/react-context": "1.1.1",
+        "@radix-ui/react-dismissable-layer": "1.1.5",
+        "@radix-ui/react-focus-guards": "1.1.1",
+        "@radix-ui/react-focus-scope": "1.1.2",
+        "@radix-ui/react-id": "1.1.0",
+        "@radix-ui/react-portal": "1.1.4",
+        "@radix-ui/react-presence": "1.1.2",
+        "@radix-ui/react-primitive": "2.0.2",
+        "@radix-ui/react-slot": "1.1.2",
+        "@radix-ui/react-use-controllable-state": "1.1.0",
+        "aria-hidden": "^1.2.4",
+        "react-remove-scroll": "^2.6.3"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/primitive": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
+      "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="
+    },
+    "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-compose-refs": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
+      "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz",
+      "integrity": "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==",
+      "dependencies": {
+        "@radix-ui/primitive": "1.1.1",
+        "@radix-ui/react-compose-refs": "1.1.1",
+        "@radix-ui/react-primitive": "2.0.2",
+        "@radix-ui/react-use-callback-ref": "1.1.0",
+        "@radix-ui/react-use-escape-keydown": "1.1.0"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-scope": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz",
+      "integrity": "sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.1",
+        "@radix-ui/react-primitive": "2.0.2",
+        "@radix-ui/react-use-callback-ref": "1.1.0"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.4.tgz",
+      "integrity": "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==",
+      "dependencies": {
+        "@radix-ui/react-primitive": "2.0.2",
+        "@radix-ui/react-use-layout-effect": "1.1.0"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-presence": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz",
+      "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.1",
+        "@radix-ui/react-use-layout-effect": "1.1.0"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-primitive": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz",
+      "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==",
+      "dependencies": {
+        "@radix-ui/react-slot": "1.1.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz",
+      "integrity": "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==",
+      "dependencies": {
+        "react-remove-scroll-bar": "^2.3.7",
+        "react-style-singleton": "^2.2.3",
+        "tslib": "^2.1.0",
+        "use-callback-ref": "^1.3.3",
+        "use-sidecar": "^1.1.3"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/@radix-ui/react-direction": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz",
@@ -7937,12 +8330,33 @@
       }
     },
     "node_modules/@radix-ui/react-label": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.0.tgz",
-      "integrity": "sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==",
-      "license": "MIT",
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.2.tgz",
+      "integrity": "sha512-zo1uGMTaNlHehDyFQcDZXRJhUPDuukcnHz0/jnrup0JA6qL+AFpAnty+7VKa9esuU5xTblAZzTGYJKSKaBxBhw==",
       "dependencies": {
-        "@radix-ui/react-primitive": "2.0.0"
+        "@radix-ui/react-primitive": "2.0.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz",
+      "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==",
+      "dependencies": {
+        "@radix-ui/react-slot": "1.1.2"
       },
       "peerDependencies": {
         "@types/react": "*",
@@ -7999,6 +8413,23 @@
         }
       }
     },
+    "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
+      "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.0"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/@radix-ui/react-popper": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz",
@@ -8117,6 +8548,68 @@
         }
       }
     },
+    "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
+      "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.0"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-progress": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.2.tgz",
+      "integrity": "sha512-u1IgJFQ4zNAUTjGdDL5dcl/U8ntOR6jsnhxKb5RKp5Ozwl88xKR9EqRZOe/Mk8tnx0x5tNUe2F+MzsyjqMg0MA==",
+      "dependencies": {
+        "@radix-ui/react-context": "1.1.1",
+        "@radix-ui/react-primitive": "2.0.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-primitive": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz",
+      "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==",
+      "dependencies": {
+        "@radix-ui/react-slot": "1.1.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/@radix-ui/react-roving-focus": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz",
@@ -8163,6 +8656,286 @@
         }
       }
     },
+    "node_modules/@radix-ui/react-select": {
+      "version": "2.1.6",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.6.tgz",
+      "integrity": "sha512-T6ajELxRvTuAMWH0YmRJ1qez+x4/7Nq7QIx7zJ0VK3qaEWdnWpNbEDnmWldG1zBDwqrLy5aLMUWcoGirVj5kMg==",
+      "dependencies": {
+        "@radix-ui/number": "1.1.0",
+        "@radix-ui/primitive": "1.1.1",
+        "@radix-ui/react-collection": "1.1.2",
+        "@radix-ui/react-compose-refs": "1.1.1",
+        "@radix-ui/react-context": "1.1.1",
+        "@radix-ui/react-direction": "1.1.0",
+        "@radix-ui/react-dismissable-layer": "1.1.5",
+        "@radix-ui/react-focus-guards": "1.1.1",
+        "@radix-ui/react-focus-scope": "1.1.2",
+        "@radix-ui/react-id": "1.1.0",
+        "@radix-ui/react-popper": "1.2.2",
+        "@radix-ui/react-portal": "1.1.4",
+        "@radix-ui/react-primitive": "2.0.2",
+        "@radix-ui/react-slot": "1.1.2",
+        "@radix-ui/react-use-callback-ref": "1.1.0",
+        "@radix-ui/react-use-controllable-state": "1.1.0",
+        "@radix-ui/react-use-layout-effect": "1.1.0",
+        "@radix-ui/react-use-previous": "1.1.0",
+        "@radix-ui/react-visually-hidden": "1.1.2",
+        "aria-hidden": "^1.2.4",
+        "react-remove-scroll": "^2.6.3"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-select/node_modules/@radix-ui/primitive": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
+      "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="
+    },
+    "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-collection": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.2.tgz",
+      "integrity": "sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.1",
+        "@radix-ui/react-context": "1.1.1",
+        "@radix-ui/react-primitive": "2.0.2",
+        "@radix-ui/react-slot": "1.1.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-compose-refs": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
+      "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-dismissable-layer": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz",
+      "integrity": "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==",
+      "dependencies": {
+        "@radix-ui/primitive": "1.1.1",
+        "@radix-ui/react-compose-refs": "1.1.1",
+        "@radix-ui/react-primitive": "2.0.2",
+        "@radix-ui/react-use-callback-ref": "1.1.0",
+        "@radix-ui/react-use-escape-keydown": "1.1.0"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-focus-scope": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz",
+      "integrity": "sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.1",
+        "@radix-ui/react-primitive": "2.0.2",
+        "@radix-ui/react-use-callback-ref": "1.1.0"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-popper": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.2.tgz",
+      "integrity": "sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA==",
+      "dependencies": {
+        "@floating-ui/react-dom": "^2.0.0",
+        "@radix-ui/react-arrow": "1.1.2",
+        "@radix-ui/react-compose-refs": "1.1.1",
+        "@radix-ui/react-context": "1.1.1",
+        "@radix-ui/react-primitive": "2.0.2",
+        "@radix-ui/react-use-callback-ref": "1.1.0",
+        "@radix-ui/react-use-layout-effect": "1.1.0",
+        "@radix-ui/react-use-rect": "1.1.0",
+        "@radix-ui/react-use-size": "1.1.0",
+        "@radix-ui/rect": "1.1.0"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-arrow": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.2.tgz",
+      "integrity": "sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg==",
+      "dependencies": {
+        "@radix-ui/react-primitive": "2.0.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-portal": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.4.tgz",
+      "integrity": "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==",
+      "dependencies": {
+        "@radix-ui/react-primitive": "2.0.2",
+        "@radix-ui/react-use-layout-effect": "1.1.0"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-primitive": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz",
+      "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==",
+      "dependencies": {
+        "@radix-ui/react-slot": "1.1.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-visually-hidden": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.2.tgz",
+      "integrity": "sha512-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q==",
+      "dependencies": {
+        "@radix-ui/react-primitive": "2.0.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-select/node_modules/react-remove-scroll": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz",
+      "integrity": "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==",
+      "dependencies": {
+        "react-remove-scroll-bar": "^2.3.7",
+        "react-style-singleton": "^2.2.3",
+        "tslib": "^2.1.0",
+        "use-callback-ref": "^1.3.3",
+        "use-sidecar": "^1.1.3"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/@radix-ui/react-separator": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.0.tgz",
@@ -8187,13 +8960,74 @@
       }
     },
     "node_modules/@radix-ui/react-slot": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
-      "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
-      "license": "MIT",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz",
+      "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==",
       "dependencies": {
-        "@radix-ui/react-compose-refs": "1.1.0"
+        "@radix-ui/react-compose-refs": "1.1.1"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-slot/node_modules/@radix-ui/react-compose-refs": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
+      "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-tabs": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.3.tgz",
+      "integrity": "sha512-9mFyI30cuRDImbmFF6O2KUJdgEOsGh9Vmx9x/Dh9tOhL7BngmQPQfwW4aejKm5OHpfWIdmeV6ySyuxoOGjtNng==",
+      "dependencies": {
+        "@radix-ui/primitive": "1.1.1",
+        "@radix-ui/react-context": "1.1.1",
+        "@radix-ui/react-direction": "1.1.0",
+        "@radix-ui/react-id": "1.1.0",
+        "@radix-ui/react-presence": "1.1.2",
+        "@radix-ui/react-primitive": "2.0.2",
+        "@radix-ui/react-roving-focus": "1.1.2",
+        "@radix-ui/react-use-controllable-state": "1.1.0"
       },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/primitive": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
+      "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="
+    },
+    "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-compose-refs": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
+      "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
       "peerDependencies": {
         "@types/react": "*",
         "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
@@ -8204,6 +9038,106 @@
         }
       }
     },
+    "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-presence": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz",
+      "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.1",
+        "@radix-ui/react-use-layout-effect": "1.1.0"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-primitive": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz",
+      "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==",
+      "dependencies": {
+        "@radix-ui/react-slot": "1.1.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-roving-focus": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.2.tgz",
+      "integrity": "sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw==",
+      "dependencies": {
+        "@radix-ui/primitive": "1.1.1",
+        "@radix-ui/react-collection": "1.1.2",
+        "@radix-ui/react-compose-refs": "1.1.1",
+        "@radix-ui/react-context": "1.1.1",
+        "@radix-ui/react-direction": "1.1.0",
+        "@radix-ui/react-id": "1.1.0",
+        "@radix-ui/react-primitive": "2.0.2",
+        "@radix-ui/react-use-callback-ref": "1.1.0",
+        "@radix-ui/react-use-controllable-state": "1.1.0"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-collection": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.2.tgz",
+      "integrity": "sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.1",
+        "@radix-ui/react-context": "1.1.1",
+        "@radix-ui/react-primitive": "2.0.2",
+        "@radix-ui/react-slot": "1.1.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/@radix-ui/react-tooltip": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.3.tgz",
@@ -8238,6 +9172,23 @@
         }
       }
     },
+    "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
+      "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.0"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/@radix-ui/react-use-callback-ref": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz",
@@ -8304,6 +9255,20 @@
         }
       }
     },
+    "node_modules/@radix-ui/react-use-previous": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz",
+      "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==",
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/@radix-ui/react-use-rect": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz",
@@ -11215,7 +12180,7 @@
       "version": "1.7.36",
       "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.36.tgz",
       "integrity": "sha512-bu7ymMX+LCJOSSrKank25Jaq66ymLVA9fOUuy4ck3/6rbXdLw+pIJPnIDKQ9uNcxww8KDxOuJk9Ui9pqR+aGFw==",
-      "dev": true,
+      "devOptional": true,
       "hasInstallScript": true,
       "license": "Apache-2.0",
       "dependencies": {
@@ -11257,7 +12222,6 @@
       "cpu": [
         "arm64"
       ],
-      "dev": true,
       "license": "Apache-2.0 AND MIT",
       "optional": true,
       "os": [
@@ -11274,7 +12238,6 @@
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "license": "Apache-2.0 AND MIT",
       "optional": true,
       "os": [
@@ -11291,7 +12254,6 @@
       "cpu": [
         "arm"
       ],
-      "dev": true,
       "license": "Apache-2.0",
       "optional": true,
       "os": [
@@ -11308,7 +12270,6 @@
       "cpu": [
         "arm64"
       ],
-      "dev": true,
       "license": "Apache-2.0 AND MIT",
       "optional": true,
       "os": [
@@ -11325,7 +12286,6 @@
       "cpu": [
         "arm64"
       ],
-      "dev": true,
       "license": "Apache-2.0 AND MIT",
       "optional": true,
       "os": [
@@ -11342,7 +12302,6 @@
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "license": "Apache-2.0 AND MIT",
       "optional": true,
       "os": [
@@ -11359,7 +12318,6 @@
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "license": "Apache-2.0 AND MIT",
       "optional": true,
       "os": [
@@ -11376,7 +12334,6 @@
       "cpu": [
         "arm64"
       ],
-      "dev": true,
       "license": "Apache-2.0 AND MIT",
       "optional": true,
       "os": [
@@ -11393,7 +12350,6 @@
       "cpu": [
         "ia32"
       ],
-      "dev": true,
       "license": "Apache-2.0 AND MIT",
       "optional": true,
       "os": [
@@ -11410,7 +12366,6 @@
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "license": "Apache-2.0 AND MIT",
       "optional": true,
       "os": [
@@ -11458,7 +12413,7 @@
       "version": "0.1.13",
       "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.13.tgz",
       "integrity": "sha512-JL7eeCk6zWCbiYQg2xQSdLXQJl8Qoc9rXmG2cEKvHe3CKwMHwHGpfOb8frzNLmbycOo6I51qxnLnn9ESf4I20Q==",
-      "dev": true,
+      "devOptional": true,
       "license": "Apache-2.0",
       "dependencies": {
         "@swc/counter": "^0.1.3"
@@ -11497,6 +12452,32 @@
         }
       }
     },
+    "node_modules/@tailwindcss/typography": {
+      "version": "0.5.16",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz",
+      "integrity": "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==",
+      "dependencies": {
+        "lodash.castarray": "^4.4.0",
+        "lodash.isplainobject": "^4.0.6",
+        "lodash.merge": "^4.6.2",
+        "postcss-selector-parser": "6.0.10"
+      },
+      "peerDependencies": {
+        "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1"
+      }
+    },
+    "node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": {
+      "version": "6.0.10",
+      "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
+      "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
+      "dependencies": {
+        "cssesc": "^3.0.0",
+        "util-deprecate": "^1.0.2"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
     "node_modules/@tanstack/react-table": {
       "version": "8.20.5",
       "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.20.5.tgz",
@@ -11691,28 +12672,28 @@
       "version": "1.0.11",
       "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
       "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT"
     },
     "node_modules/@tsconfig/node12": {
       "version": "1.0.11",
       "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
       "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT"
     },
     "node_modules/@tsconfig/node14": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
       "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT"
     },
     "node_modules/@tsconfig/node16": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
       "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT"
     },
     "node_modules/@types/aria-query": {
@@ -13074,7 +14055,6 @@
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
       "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
-      "dev": true,
       "license": "MIT"
     },
     "node_modules/anymatch": {
@@ -13122,6 +14102,21 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/arcjet": {
+      "version": "1.0.0-beta.3",
+      "resolved": "https://registry.npmjs.org/arcjet/-/arcjet-1.0.0-beta.3.tgz",
+      "integrity": "sha512-60pL1+vzRZOEb83lbV041TXd/C3KPjWjb1W3Kml7DBhFHDgfK/g1Vl63pPswzHKDu9Tr3N84pU2HfXMe2qoelw==",
+      "dependencies": {
+        "@arcjet/analyze": "1.0.0-beta.3",
+        "@arcjet/duration": "1.0.0-beta.3",
+        "@arcjet/headers": "1.0.0-beta.3",
+        "@arcjet/protocol": "1.0.0-beta.3",
+        "@arcjet/runtime": "1.0.0-beta.3"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
     "node_modules/are-docs-informative": {
       "version": "0.0.2",
       "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz",
@@ -13136,7 +14131,6 @@
       "version": "5.0.2",
       "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
       "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
-      "dev": true,
       "license": "MIT"
     },
     "node_modules/argparse": {
@@ -14426,7 +15420,6 @@
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
       "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">= 6"
@@ -14465,6 +15458,15 @@
       ],
       "license": "CC-BY-4.0"
     },
+    "node_modules/canvas-confetti": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.3.tgz",
+      "integrity": "sha512-rFfTURMvmVEX1gyXFgn5QMn81bYk70qa0HLzcIOSVEyl57n6o9ItHeBtUSWdvKAPY0xlvBHno4/v3QPrT83q9g==",
+      "funding": {
+        "type": "donate",
+        "url": "https://www.paypal.me/kirilvatev"
+      }
+    },
     "node_modules/cardinal": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz",
@@ -16119,7 +17121,7 @@
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
       "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT"
     },
     "node_modules/cross-env": {
@@ -16395,7 +17397,6 @@
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
       "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
-      "dev": true,
       "license": "MIT",
       "bin": {
         "cssesc": "bin/cssesc"
@@ -17057,14 +18058,13 @@
       "version": "1.2.2",
       "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
       "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
-      "dev": true,
       "license": "Apache-2.0"
     },
     "node_modules/diff": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
       "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
-      "dev": true,
+      "devOptional": true,
       "license": "BSD-3-Clause",
       "engines": {
         "node": ">=0.3.1"
@@ -17126,7 +18126,6 @@
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
       "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
-      "dev": true,
       "license": "MIT"
     },
     "node_modules/doctrine": {
@@ -20045,7 +21044,6 @@
       "version": "3.3.2",
       "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
       "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "@nodelib/fs.stat": "^2.0.2",
@@ -20062,7 +21060,6 @@
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
       "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-      "dev": true,
       "license": "ISC",
       "dependencies": {
         "is-glob": "^4.0.1"
@@ -20130,7 +21127,6 @@
       "version": "1.17.1",
       "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
       "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
-      "dev": true,
       "license": "ISC",
       "dependencies": {
         "reusify": "^1.0.4"
@@ -21101,6 +22097,14 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/geist": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/geist/-/geist-1.3.1.tgz",
+      "integrity": "sha512-Q4gC1pBVPN+D579pBaz0TRRnGA4p9UK6elDY/xizXdFk/g4EKR5g0I+4p/Kj6gM0SajDBZ/0FvDV9ey9ud7BWw==",
+      "peerDependencies": {
+        "next": ">=13.2.0"
+      }
+    },
     "node_modules/gensync": {
       "version": "1.0.0-beta.2",
       "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@@ -21279,7 +22283,6 @@
       "version": "10.3.10",
       "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
       "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
-      "dev": true,
       "license": "ISC",
       "dependencies": {
         "foreground-child": "^3.1.0",
@@ -21302,7 +22305,6 @@
       "version": "6.0.2",
       "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
       "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
-      "dev": true,
       "license": "ISC",
       "dependencies": {
         "is-glob": "^4.0.3"
@@ -22498,15 +23500,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/invariant": {
-      "version": "2.2.4",
-      "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
-      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
-      "license": "MIT",
-      "dependencies": {
-        "loose-envify": "^1.0.0"
-      }
-    },
     "node_modules/ipaddr.js": {
       "version": "1.9.1",
       "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -23508,7 +24501,6 @@
       "version": "2.3.6",
       "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
       "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
-      "dev": true,
       "license": "BlueOak-1.0.0",
       "dependencies": {
         "@isaacs/cliui": "^8.0.2"
@@ -25336,7 +26328,6 @@
       "version": "1.21.6",
       "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
       "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
-      "dev": true,
       "license": "MIT",
       "bin": {
         "jiti": "bin/jiti.js"
@@ -25817,7 +26808,6 @@
       "version": "3.1.2",
       "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
       "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">=14"
@@ -25830,7 +26820,6 @@
       "version": "1.2.4",
       "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
       "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
-      "dev": true,
       "license": "MIT"
     },
     "node_modules/lint-staged": {
@@ -26229,6 +27218,11 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/lodash.castarray": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
+      "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q=="
+    },
     "node_modules/lodash.debounce": {
       "version": "4.0.8",
       "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -26254,7 +27248,6 @@
       "version": "4.0.6",
       "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
       "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
-      "dev": true,
       "license": "MIT"
     },
     "node_modules/lodash.isstring": {
@@ -26289,7 +27282,6 @@
       "version": "4.6.2",
       "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
       "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
-      "dev": true,
       "license": "MIT"
     },
     "node_modules/lodash.mergewith": {
@@ -26662,7 +27654,7 @@
       "version": "1.3.6",
       "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
       "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
-      "dev": true,
+      "devOptional": true,
       "license": "ISC"
     },
     "node_modules/makeerror": {
@@ -26923,7 +27915,6 @@
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
       "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">= 8"
@@ -26964,7 +27955,6 @@
       "version": "4.0.8",
       "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
       "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "braces": "^3.0.3",
@@ -26978,7 +27968,6 @@
       "version": "2.3.1",
       "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
       "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">=8.6"
@@ -27296,7 +28285,6 @@
       "version": "2.7.0",
       "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
       "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "any-promise": "^1.0.0",
@@ -31510,7 +32498,6 @@
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
       "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">=0.10.0"
@@ -31520,7 +32507,6 @@
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
       "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">= 6"
@@ -32775,7 +33761,6 @@
       "version": "4.0.6",
       "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
       "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">= 6"
@@ -33183,7 +34168,6 @@
       "version": "8.4.47",
       "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
       "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
-      "dev": true,
       "funding": [
         {
           "type": "opencollective",
@@ -33320,7 +34304,6 @@
       "version": "15.1.0",
       "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
       "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "postcss-value-parser": "^4.0.0",
@@ -33338,7 +34321,6 @@
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
       "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "camelcase-css": "^2.0.1"
@@ -33358,7 +34340,6 @@
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
       "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
-      "dev": true,
       "funding": [
         {
           "type": "opencollective",
@@ -33594,7 +34575,6 @@
       "version": "6.2.0",
       "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
       "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
-      "dev": true,
       "funding": [
         {
           "type": "opencollective",
@@ -33812,7 +34792,6 @@
       "version": "6.1.2",
       "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
       "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "cssesc": "^3.0.0",
@@ -33859,7 +34838,6 @@
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
       "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
-      "dev": true,
       "license": "MIT"
     },
     "node_modules/postgres-array": {
@@ -34237,7 +35215,6 @@
       "version": "1.2.3",
       "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
       "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
-      "dev": true,
       "funding": [
         {
           "type": "github",
@@ -34520,20 +35497,19 @@
       }
     },
     "node_modules/react-remove-scroll-bar": {
-      "version": "2.3.6",
-      "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz",
-      "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==",
-      "license": "MIT",
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
+      "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
       "dependencies": {
-        "react-style-singleton": "^2.2.1",
+        "react-style-singleton": "^2.2.2",
         "tslib": "^2.0.0"
       },
       "engines": {
         "node": ">=10"
       },
       "peerDependencies": {
-        "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
-        "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+        "@types/react": "*",
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
       },
       "peerDependenciesMeta": {
         "@types/react": {
@@ -34542,21 +35518,19 @@
       }
     },
     "node_modules/react-style-singleton": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz",
-      "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==",
-      "license": "MIT",
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
+      "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
       "dependencies": {
         "get-nonce": "^1.0.0",
-        "invariant": "^2.2.4",
         "tslib": "^2.0.0"
       },
       "engines": {
         "node": ">=10"
       },
       "peerDependencies": {
-        "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
-        "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+        "@types/react": "*",
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
       },
       "peerDependenciesMeta": {
         "@types/react": {
@@ -34568,7 +35542,6 @@
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
       "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "pify": "^2.3.0"
@@ -34578,7 +35551,6 @@
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
       "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">=0.10.0"
@@ -35511,7 +36483,6 @@
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
       "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "iojs": ">=1.0.0",
@@ -35677,7 +36648,6 @@
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
       "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
-      "dev": true,
       "funding": [
         {
           "type": "github",
@@ -37604,7 +38574,6 @@
       "version": "3.35.0",
       "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
       "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "@jridgewell/gen-mapping": "^0.3.2",
@@ -37627,7 +38596,6 @@
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
       "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">= 6"
@@ -37874,7 +38842,6 @@
       "version": "3.4.14",
       "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz",
       "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "@alloc/quick-lru": "^5.2.0",
@@ -37922,7 +38889,6 @@
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
       "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">=10"
@@ -38198,7 +39164,6 @@
       "version": "3.3.1",
       "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
       "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "any-promise": "^1.0.0"
@@ -38208,7 +39173,6 @@
       "version": "1.6.0",
       "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
       "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "thenify": ">= 3.1.0 < 4"
@@ -38579,14 +39543,13 @@
       "version": "0.1.13",
       "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
       "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
-      "dev": true,
       "license": "Apache-2.0"
     },
     "node_modules/ts-node": {
       "version": "10.9.2",
       "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
       "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT",
       "dependencies": {
         "@cspotcode/source-map-support": "^0.8.0",
@@ -38630,7 +39593,7 @@
       "version": "8.13.0",
       "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz",
       "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT",
       "bin": {
         "acorn": "bin/acorn"
@@ -38643,7 +39606,7 @@
       "version": "8.3.4",
       "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
       "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT",
       "dependencies": {
         "acorn": "^8.11.0"
@@ -38656,7 +39619,7 @@
       "version": "4.1.3",
       "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
       "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT"
     },
     "node_modules/ts-pattern": {
@@ -39432,6 +40395,26 @@
         "is-typedarray": "^1.0.0"
       }
     },
+    "node_modules/typeid-js": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/typeid-js/-/typeid-js-1.2.0.tgz",
+      "integrity": "sha512-t76ZucAnvGC60ea/HjVsB0TSoB0cw9yjnfurUgtInXQWUI/VcrlZGpO23KN3iSe8yOGUgb1zr7W7uEzJ3hSljA==",
+      "dependencies": {
+        "uuid": "^10.0.0"
+      }
+    },
+    "node_modules/typeid-js/node_modules/uuid": {
+      "version": "10.0.0",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
+      "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
+      "funding": [
+        "https://github.com/sponsors/broofa",
+        "https://github.com/sponsors/ctavan"
+      ],
+      "bin": {
+        "uuid": "dist/bin/uuid"
+      }
+    },
     "node_modules/typescript": {
       "version": "5.6.3",
       "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
@@ -39483,6 +40466,17 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/undici": {
+      "version": "5.28.5",
+      "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
+      "integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
+      "dependencies": {
+        "@fastify/busboy": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=14.0"
+      }
+    },
     "node_modules/undici-types": {
       "version": "6.19.8",
       "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
@@ -39789,10 +40783,9 @@
       "license": "MIT"
     },
     "node_modules/use-callback-ref": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz",
-      "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==",
-      "license": "MIT",
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
+      "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
       "dependencies": {
         "tslib": "^2.0.0"
       },
@@ -39800,8 +40793,8 @@
         "node": ">=10"
       },
       "peerDependencies": {
-        "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
-        "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+        "@types/react": "*",
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
       },
       "peerDependenciesMeta": {
         "@types/react": {
@@ -39823,10 +40816,9 @@
       }
     },
     "node_modules/use-sidecar": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz",
-      "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==",
-      "license": "MIT",
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
+      "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
       "dependencies": {
         "detect-node-es": "^1.1.0",
         "tslib": "^2.0.0"
@@ -39835,8 +40827,8 @@
         "node": ">=10"
       },
       "peerDependencies": {
-        "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0",
-        "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+        "@types/react": "*",
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
       },
       "peerDependenciesMeta": {
         "@types/react": {
@@ -39871,7 +40863,6 @@
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
       "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
-      "dev": true,
       "license": "MIT"
     },
     "node_modules/utila": {
@@ -39908,7 +40899,7 @@
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
       "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT"
     },
     "node_modules/v8-to-istanbul": {
@@ -41507,7 +42498,6 @@
       "version": "2.6.0",
       "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz",
       "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==",
-      "dev": true,
       "license": "ISC",
       "bin": {
         "yaml": "bin.mjs"
@@ -41606,7 +42596,7 @@
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
       "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
-      "dev": true,
+      "devOptional": true,
       "license": "MIT",
       "engines": {
         "node": ">=6"
diff --git a/package.json b/package.json
index 7a3d8067c..51845da9b 100644
--- a/package.json
+++ b/package.json
@@ -26,6 +26,7 @@
     "prepare": "husky"
   },
   "dependencies": {
+    "@arcjet/next": "1.0.0-beta.3",
     "@clerk/localizations": "^3.2.1",
     "@clerk/nextjs": "^5.7.3",
     "@clerk/themes": "^2.1.36",
diff --git a/src/libs/Env.ts b/src/libs/Env.ts
index 44098967a..2410aa048 100644
--- a/src/libs/Env.ts
+++ b/src/libs/Env.ts
@@ -6,6 +6,7 @@ export const Env = createEnv({
     CLERK_SECRET_KEY: z.string().min(1),
     DATABASE_URL: z.string().optional(),
     LOGTAIL_SOURCE_TOKEN: z.string().optional(),
+    ARCJET_KEY: z.string().optional(),
     STRIPE_SECRET_KEY: z.string().min(1),
     STRIPE_WEBHOOK_SECRET: z.string().min(1),
     BILLING_PLAN_ENV: z.enum(['dev', 'test', 'prod']),
@@ -23,6 +24,7 @@ export const Env = createEnv({
   runtimeEnv: {
     CLERK_SECRET_KEY: process.env.CLERK_SECRET_KEY,
     DATABASE_URL: process.env.DATABASE_URL,
+    ARCJET_KEY: process.env.ARCJET_KEY,
     LOGTAIL_SOURCE_TOKEN: process.env.LOGTAIL_SOURCE_TOKEN,
     STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
     STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET,
diff --git a/src/middleware.ts b/src/middleware.ts
index 4ae363a61..1d2b4d87e 100644
--- a/src/middleware.ts
+++ b/src/middleware.ts
@@ -1,3 +1,4 @@
+import arcjet, { shield } from "@arcjet/next";
 import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
 import {
   type NextFetchEvent,
@@ -7,6 +8,7 @@ import {
 import createMiddleware from 'next-intl/middleware';
 
 import { AllLocales, AppConfig } from './utils/AppConfig';
+import { Env } from "./libs/Env";
 
 const intlMiddleware = createMiddleware({
   locales: AllLocales,
@@ -14,6 +16,20 @@ const intlMiddleware = createMiddleware({
   defaultLocale: AppConfig.defaultLocale,
 });
 
+
+const aj = arcjet({
+  // Get your site key from https://app.arcjet.com
+  // and set it as an environment variable rather than hard coding.
+  // See: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
+  key: Env.ARCJET_KEY!,
+  rules: [
+    // Protect against common attacks with Arcjet Shield
+    shield({
+      mode: "DRY_RUN", // will block requests. Use "DRY_RUN" to log only
+    }),
+  ],
+});
+
 const isProtectedRoute = createRouteMatcher([
   '/dashboard(.*)',
   '/:locale/dashboard(.*)',
@@ -32,9 +48,13 @@ export default function middleware(
     || request.nextUrl.pathname.includes('/sign-up')
     || isProtectedRoute(request)
   ) {
-    return clerkMiddleware((auth, req) => {
+    return clerkMiddleware(async (auth, req) => {
       const authObj = auth();
+      const decision = await aj.protect(req);
 
+      if (decision.isDenied()) {
+        return NextResponse.json({ error: "Forbidden" }, { status: 403 });
+      }
       if (isProtectedRoute(req)) {
         const locale
           = req.nextUrl.pathname.match(/(\/.*)\/dashboard/)?.at(1) ?? '';


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>🧹 Nitpick comments (4)</summary><blockquote>

<details>
<summary>src/middleware.ts (4)</summary><blockquote>

`1-1`: **Use consistent quote style**

The import statement uses double quotes, but the project's ESLint configuration prefers single quotes.

```diff
-import arcjet, { shield } from "@arcjet/next";
+import arcjet, { shield } from '@arcjet/next';
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 1-1: Strings must use singlequote.

(style/quotes)

</details>

</details>

---

`18-19`: **Remove extra blank lines**

There are more than one consecutive blank lines here, which violates the style guidelines.

```diff
-

+
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 18-19: More than 1 blank line not allowed.

(style/no-multiple-empty-lines)

</details>

</details>

---

`50-56`: **Add error logging and consider custom error responses**

When a request is denied by Arcjet, a generic 403 error is returned. Consider adding logging to track these events and providing more specific error messages to help with debugging.

```diff
     return clerkMiddleware(async (auth, req) => {
       const authObj = auth();
       const decision = await aj.protect(req);
 
       if (decision.isDenied()) {
-        return NextResponse.json({ error: "Forbidden" }, { status: 403 });
+        console.error(`Request denied by Arcjet: ${req.url} - ${decision.reason}`);
+        return NextResponse.json({ error: 'Forbidden', reason: decision.reason }, { status: 403 });
       }
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 55-55: Strings must use singlequote.

(style/quotes)

</details>

</details>

---

`19-30`: **Document Arcjet implementation details for the team**

The Arcjet implementation adds a new security layer that blocks requests. Consider adding documentation about how this works, what types of attacks it protects against, and how to troubleshoot issues when legitimate requests are blocked.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 27-27: Strings must use singlequote.

(style/quotes)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 87dc2b86f0ac8759ebb14026f5fa0dbc103dcafb and 28649af2f5d139edae0586e6853cd944193aa54d.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `package.json` (1 hunks)
* `src/middleware.ts` (3 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 ESLint</summary>

<details>
<summary>src/middleware.ts</summary>

[error] 1-1: Strings must use singlequote.

(style/quotes)

---

[error] 18-19: More than 1 blank line not allowed.

(style/no-multiple-empty-lines)

---

[error] 27-27: Strings must use singlequote.

(style/quotes)

---

[error] 55-55: Strings must use singlequote.

(style/quotes)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (1)</summary><blockquote>

<details>
<summary>package.json (1)</summary>

`29-29`: <details>
<summary>✅ Verification successful</summary>

**Consider using a stable version instead of beta**

The package `@arcjet/next` is being added with version `1.0.0-beta.3`, which is a beta version. Beta versions may have stability issues or incomplete features that could impact production systems.

---

🌐 Web query:

```web
What is the latest stable version of @arcjet/next?
```

💡 Result:

The latest stable version of `@arcjet/next` is **1.0.0-beta.3**, released on March 5, 2025[9][10]. This version supports Next.js 15.x and includes performance improvements, bot detection enhancements, and compatibility with server actions introduced in Next.js 15[4][8]. 

Key details:
- Maintains backward compatibility with Next.js 14.x[8]
- Requires Node.js 18+/20+/22+ LTS versions[8]
- Uses ESM modules exclusively (no CommonJS support)[8]
- Includes features like rate limiting, bot detection, and security headers via Nosecone[5][9]

While labeled as "beta," this is the current production-ready version recommended by Arcjet. The SDK follows semantic versioning, with beta status indicating ongoing feature development rather than instability[10]. Developers are advised to monitor GitHub releases for updates, as the team actively maintains compatibility with Next.js versions[1][5].

Citations:

- 1: https://github.com/arcjet/arcjet-js/releases
- 2: https://dev.to/llxd/for-engineers-in-a-hurry-a-guide-for-implementing-security-1o8m
- 3: https://www.youtube.com/watch?v=OAyQ3Wyyzfg
- 4: https://blog.arcjet.com/new-sdk-release-for-next-js-15/
- 5: https://github.com/arcjet/arcjet-js
- 6: https://arc.aiaa.org/doi/10.2514/1.A34546
- 7: https://dev.to/envitab/how-to-build-a-secure-nextjs-blog-with-flyio-and-arcjet-5b29
- 8: https://docs.arcjet.com/reference/nextjs/
- 9: https://ntrs.nasa.gov/api/citations/19870012565/downloads/19870012565.pdf
- 10: https://www.npmjs.com/package/@arcjet/next
- 11: https://www.nasa.gov/ames/arcjet-complex/
- 12: https://github.com/ixartz/Next-js-Boilerplate
- 13: https://www.nasa.gov/ames/arc-jet-complex-operations/
- 14: https://www.youtube.com/watch?v=eOIbe_7ZlpM
- 15: https://arcjet.com
- 16: https://nextjs.org/conf
- 17: https://docs.arcjet.com/integrations/authjs/
- 18: https://silvasweden.com/en/products/arc-jet
- 19: https://www.npmjs.com/package/@arcjet/next?activeTab=versions

---



</details>

**@arcjet/next Dependency Version Update**

The version `"1.0.0-beta.3"` is indeed the latest stable release and is recommended for production use despite the beta label. According to recent release notes, this version is production-ready—with full support for Next.js 15.x, performance improvements, and enhanced security features. No change is necessary as the beta status reflects ongoing feature development rather than instability.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-08T14:50:27Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>♻️ Duplicate comments (1)</summary><blockquote>

<details>
<summary>src/middleware.ts (1)</summary><blockquote>

`20-31`: _⚠️ Potential issue_

**Add validation for ARCJET_KEY and configure shield mode based on environment**

The current implementation has two issues:
1. It uses a non-null assertion (`!`) which could cause runtime errors if the key is missing
2. Shield mode is set to "LIVE" which will block requests. For safety, consider using "DRY_RUN" in development environments.



```diff
 const aj = arcjet({
   // Get your site key from https://app.arcjet.com
   // and set it as an environment variable rather than hard coding.
   // See: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
-  key: Env.ARCJET_KEY!,
+  key: Env.ARCJET_KEY || (() => { throw new Error('ARCJET_KEY environment variable is required'); })(),
   rules: [
     // Protect against common attacks with Arcjet Shield
     shield({
-      mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
+      mode: process.env.NODE_ENV === 'production' ? 'LIVE' : 'DRY_RUN', // Use DRY_RUN in development, LIVE in production
     }),
   ],
 });
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 28-28: Strings must use singlequote.

(style/quotes)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (4)</summary><blockquote>

<details>
<summary>src/middleware.ts (4)</summary><blockquote>

`1-1`: **Fix import style for consistency**

Use single quotes instead of double quotes to be consistent with the rest of the codebase.


```diff
-import arcjet, { shield } from "@arcjet/next";
+import arcjet, { shield } from '@arcjet/next';
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 1-11: Run autofix to sort these imports!

(simple-import-sort/imports)

---

[error] 1-1: Strings must use singlequote.

(style/quotes)

</details>

</details>

---

`11-11`: **Fix import style for consistency**

Use single quotes instead of double quotes.


```diff
-import { Env } from "./libs/Env";
+import { Env } from './libs/Env';
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 1-11: Run autofix to sort these imports!

(simple-import-sort/imports)

---

[error] 11-11: Strings must use singlequote.

(style/quotes)

</details>

</details>

---

`19-20`: **Remove extra empty lines**

There should be only one empty line between code blocks.


```diff
 });

-

 const aj = arcjet({
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 19-20: More than 1 blank line not allowed.

(style/no-multiple-empty-lines)

</details>

</details>

---

`51-57`: **Use single quotes for string literals**

Maintain consistent string quoting throughout the codebase.


```diff
-        return NextResponse.json({ error: "Forbidden" }, { status: 403 });
+        return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 56-56: Strings must use singlequote.

(style/quotes)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 28649af2f5d139edae0586e6853cd944193aa54d and 65fa60f0d5976a4a2bcefd2863bba5b8bd0c31b1.

</details>

<details>
<summary>📒 Files selected for processing (3)</summary>

* `.env` (1 hunks)
* `src/libs/Env.ts` (2 hunks)
* `src/middleware.ts` (3 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 ESLint</summary>

<details>
<summary>src/middleware.ts</summary>

[error] 1-11: Run autofix to sort these imports!

(simple-import-sort/imports)

---

[error] 1-1: Strings must use singlequote.

(style/quotes)

---

[error] 11-11: Strings must use singlequote.

(style/quotes)

---

[error] 19-20: More than 1 blank line not allowed.

(style/no-multiple-empty-lines)

---

[error] 28-28: Strings must use singlequote.

(style/quotes)

---

[error] 56-56: Strings must use singlequote.

(style/quotes)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>src/libs/Env.ts (2)</summary>

`9-9`: **LGTM! Environment variable properly added to server configuration**

The ARCJET_KEY is correctly added as an optional string in the server configuration.

---

`27-27`: **LGTM! Environment variable properly mapped in runtimeEnv**

The ARCJET_KEY is correctly mapped in the runtimeEnv object.

</details>
<details>
<summary>src/middleware.ts (1)</summary>

`51-85`: **LGTM! Protect incoming requests with Arcjet middleware**

The implementation to check requests with Arcjet before proceeding with Clerk authentication looks good. This adds an extra layer of security to protected routes.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 56-56: Strings must use singlequote.

(style/quotes)

</details>

</details>

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-08T14:58:54Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>♻️ Duplicate comments (1)</summary><blockquote>

<details>
<summary>src/middleware.ts (1)</summary><blockquote>

`20-31`: _🛠️ Refactor suggestion_

**Validate ARCJET_KEY and use environment-specific modes.**

The current implementation has two issues that were pointed out in the previous review:
1. No validation for the ARCJET_KEY environment variable
2. Fixed "DRY_RUN" mode instead of environment-specific configuration




Apply the suggested changes to validate the key and use appropriate modes:

```diff
 const aj = arcjet({
   // Get your site key from https://app.arcjet.com
   // and set it as an environment variable rather than hard coding.
   // See: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
-  key: Env.ARCJET_KEY!,
+  key: Env.ARCJET_KEY || (() => { throw new Error('ARCJET_KEY environment variable is required'); })(),
   rules: [
     // Protect against common attacks with Arcjet Shield
     shield({
-      mode: "DRY_RUN", // will block requests. Use "DRY_RUN" to log only
+      mode: process.env.NODE_ENV === 'production' ? 'LIVE' : 'DRY_RUN', // Use DRY_RUN in development, LIVE in production
     }),
   ],
 });
```

This approach provides better error handling and automatically adjusts the protection mode based on the environment.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 28-28: Strings must use singlequote.

(style/quotes)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (4)</summary><blockquote>

<details>
<summary>src/middleware.ts (4)</summary><blockquote>

`55-57`: **Fix string quote style in error message.**

The error message is using double quotes instead of single quotes, which is inconsistent with the project's style guidelines.


```diff
      if (decision.isDenied()) {
-        return NextResponse.json({ error: "Forbidden" }, { status: 403 });
+        return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
      }
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 56-56: Strings must use singlequote.

(style/quotes)

</details>

</details>

---

`51-57`: **Consider adding more detailed error information.**

The current implementation returns a generic "Forbidden" error when a request is denied by Arcjet. This might not provide enough context for troubleshooting.


Consider including more information from the decision object if available:

```diff
      const decision = await aj.protect(req);

      if (decision.isDenied()) {
-        return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
+        return NextResponse.json({ 
+          error: 'Forbidden', 
+          reason: decision.reason || 'Request denied by security rules',
+          requestId: decision.requestId
+        }, { status: 403 });
      }
```

This would help with debugging and provide more context to clients about why their request was denied.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 56-56: Strings must use singlequote.

(style/quotes)

</details>

</details>

---

`19-20`: **Fix multiple empty lines.**

There are multiple empty lines before the arcjet configuration block, which is against the project's style guidelines.


```diff
 });

-
 const aj = arcjet({
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 19-20: More than 1 blank line not allowed.

(style/no-multiple-empty-lines)

</details>

</details>

---

`20-31`: **Document the Arcjet integration in the codebase.**

The Arcjet integration is a critical security feature that's being added, but there's minimal documentation about what it does and how it works.


Consider adding a brief comment block before the arcjet configuration explaining:
1. What Arcjet does for the application
2. What types of attacks it protects against
3. How to troubleshoot if legitimate requests are being blocked

```diff
 });

+/**
+ * Arcjet Security Integration
+ * 
+ * Protects the application against common attacks including:
+ * - Rate limiting to prevent brute force attempts
+ * - Bot detection to block malicious automation
+ * - IP reputation checks
+ * 
+ * In development, runs in DRY_RUN mode which logs but doesn't block.
+ * In production, runs in LIVE mode and will return 403 errors for suspicious requests.
+ * 
+ * @see https://docs.arcjet.com for more details
+ */
 const aj = arcjet({
   // Get your site key from https://app.arcjet.com
   // and set it as an environment variable rather than hard coding.
   // See: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 28-28: Strings must use singlequote.

(style/quotes)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 65fa60f0d5976a4a2bcefd2863bba5b8bd0c31b1 and e92bceb9f72f8385ba56c827b2e8b94dff1299ea.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `src/middleware.ts` (3 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 ESLint</summary>

<details>
<summary>src/middleware.ts</summary>

[error] 1-11: Run autofix to sort these imports!

(simple-import-sort/imports)

---

[error] 1-1: Strings must use singlequote.

(style/quotes)

---

[error] 11-11: Strings must use singlequote.

(style/quotes)

---

[error] 19-20: More than 1 blank line not allowed.

(style/no-multiple-empty-lines)

---

[error] 28-28: Strings must use singlequote.

(style/quotes)

---

[error] 56-56: Strings must use singlequote.

(style/quotes)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (1)</summary><blockquote>

<details>
<summary>src/middleware.ts (1)</summary>

`1-1`: **Fix import style issues.**

The imports for `arcjet` and `Env` are using double quotes instead of single quotes, which is inconsistent with the project's style guidelines.



Consider running the ESLint autofix to sort imports and convert double quotes to single quotes:

```diff
-import arcjet, { shield } from "@arcjet/next";
+import arcjet, { shield } from '@arcjet/next';
 import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
 import {
   type NextFetchEvent,
   type NextRequest,
   NextResponse,
 } from 'next/server';
 import createMiddleware from 'next-intl/middleware';

 import { AllLocales, AppConfig } from './utils/AppConfig';
-import { Env } from "./libs/Env";
+import { Env } from './libs/Env';
```


Also applies to: 11-11

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 1-11: Run autofix to sort these imports!

(simple-import-sort/imports)

---

[error] 1-1: Strings must use singlequote.

(style/quotes)

</details>

</details>

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-08T15:02:43Z

Review comments:
diff_hunk: @@ -14,6 +15,20 @@ const intlMiddleware = createMiddleware({
   defaultLocale: AppConfig.defaultLocale,
 });
 
+
+const aj = arcjet({
+  // Get your site key from https://app.arcjet.com
+  // and set it as an environment variable rather than hard coding.
+  // See: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
+  key: process.env.ARCJET_KEY!,
+  rules: [
+    // Protect against common attacks with Arcjet Shield
+    shield({
+      mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
+    }),
+  ],
+});
path: src/middleware.ts
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Validate environment variables and consider using DRY_RUN mode first**

The implementation creates an arcjet instance with a hard dependency on the environment variable. Consider adding validation for the environment variable and starting with DRY_RUN mode before moving to LIVE to avoid accidentally blocking legitimate traffic.
 
```diff
 const aj = arcjet({
   // Get your site key from https://app.arcjet.com
   // and set it as an environment variable rather than hard coding.
   // See: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
-  key: process.env.ARCJET_KEY!,
+  key: process.env.ARCJET_KEY || (()=>{throw new Error('ARCJET_KEY environment variable is required')})(),
   rules: [
     // Protect against common attacks with Arcjet Shield
     shield({
-      mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
+      mode: process.env.NODE_ENV === 'production' ? 'LIVE' : 'DRY_RUN', // DRY_RUN in development, LIVE in production
     }),
   ],
 });
```

Run the following script to verify if the ARCJET_KEY is properly set in your environment:

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if ARCJET_KEY is set in .env files or environment
grep -q 'ARCJET_KEY' .env* 2>/dev/null || echo "Warning: ARCJET_KEY not found in any .env file"
grep -q 'ARCJET_KEY' .env.example 2>/dev/null || echo "Warning: ARCJET_KEY not found in .env.example"
```

Length of output: 279

---



</details>

**Attention: Mandatory Environment Variable Validation and Correct Shield Mode Configuration**

The script output confirms that `ARCJET_KEY` is missing from your environment configuration files. To prevent runtime errors or inadvertently blocking legitimate traffic, please update the `src/middleware.ts` file as follows:

- **Validate the ARCJET_KEY:**  
  Replace the non-null assertion with an explicit runtime check so that missing keys immediately trigger an error.  
  ```diff
   const aj = arcjet({
     // Get your site key from https://app.arcjet.com
     // and set it as an environment variable rather than hard coding.
     // See: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
-  key: process.env.ARCJET_KEY!,
+  key: process.env.ARCJET_KEY || (() => { throw new Error('ARCJET_KEY environment variable is required'); })(),
     rules: [
       // Protect against common attacks with Arcjet Shield
       shield({
-        mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
+        mode: process.env.NODE_ENV === 'production' ? 'LIVE' : 'DRY_RUN', // Use DRY_RUN in development, LIVE in production
       }),
     ],
   });
  ```

- **Action Items:**
  - Ensure that `ARCJET_KEY` is properly defined in your `.env` files (and reflected in `.env.example`) to avoid configuration issues.
  - Verify that non-production builds use the `DRY_RUN` mode to prevent accidental blocking of traffic.



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
const aj = arcjet({
  // Get your site key from https://app.arcjet.com
  // and set it as an environment variable rather than hard coding.
  // See: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
  key: process.env.ARCJET_KEY || (() => { throw new Error('ARCJET_KEY environment variable is required'); })(),
  rules: [
    // Protect against common attacks with Arcjet Shield
    shield({
      mode: process.env.NODE_ENV === 'production' ? 'LIVE' : 'DRY_RUN', // DRY_RUN in development, LIVE in production
    }),
  ],
});
`````

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 27-27: Strings must use singlequote.

(style/quotes)

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-08T14:50:26Z
author_association: NONE
diff_hunk: @@ -26,6 +26,7 @@
     "prepare": "husky"
   },
   "dependencies": {
+    "@arcjet/next": "1.0.0-beta.3",
path: package.json
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Update package-lock.json and document dependency purpose**

Ensure that you've also committed the updated package-lock.json file with this change. Additionally, consider adding a comment in the README or documentation about the purpose of this security middleware for future reference.

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if package-lock.json exists and has been updated
if [ -f "package-lock.json" ]; then
  grep -q '"@arcjet/next"' package-lock.json && echo "package-lock.json contains @arcjet/next" || echo "Warning: package-lock.json might not be updated with @arcjet/next"
else
  echo "Warning: package-lock.json not found"
fi
```

Length of output: 216

---



</details>

**Action Needed: Update package-lock.json & Document Dependency Purpose**

- The package-lock.json file does not reflect the update (missing the "@arcjet/next" entry). Please update and commit the package-lock.json file so it matches the changes in package.json.
- Additionally, add a comment in the README or relevant documentation explaining the purpose of the "@arcjet/next" security middleware.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-08T14:50:27Z
author_association: NONE
diff_hunk: @@ -22,3 +22,6 @@ CLERK_SECRET_KEY=your_clerk_secret_key
 STRIPE_SECRET_KEY=your_stripe_secret_key
 STRIPE_WEBHOOK_SECRET=your_stripe_webhook_secret
 ######## [END] SENSITIVE DATA
+
+#ARCJET
+ARCJET_KEY=YOUR-KEY
path: .env
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Move ARCJET_KEY to the SENSITIVE DATA section**

Since this is a security key for Arcjet's protection service, it should be treated as sensitive data like other API keys. Consider moving this variable inside the SENSITIVE DATA section and following the same naming convention for the placeholder value.


```diff
 ######## [END] SENSITIVE DATA

-#ARCJET
-ARCJET_KEY=YOUR-KEY
+######## [BEGIN] SENSITIVE DATA ########
+# Clerk authentication
+CLERK_SECRET_KEY=your_clerk_secret_key
+
+# Stripe
+STRIPE_SECRET_KEY=your_stripe_secret_key
+STRIPE_WEBHOOK_SECRET=your_stripe_webhook_secret
+
+# Arcjet
+ARCJET_KEY=your_arcjet_key
+######## [END] SENSITIVE DATA
```


> Committable suggestion skipped: line range outside the PR's diff.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-08T14:58:53Z
author_association: NONE

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-03-08T14:43:28Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: skip review by coderabbit.ai -->

> [!IMPORTANT]
> ## Review skipped
> 
> Review was skipped due to path filters
> 
> <details>
> <summary>:no_entry: Files ignored due to path filters (1)</summary>
> 
> * `package-lock.json` is excluded by `!**/package-lock.json`
> 
> </details>
> 
> CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including `**/dist/**` will override the default block on the `dist` directory, by removing the pattern from both the lists.
> 
> You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file.

<!-- end of auto-generated comment: skip review by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
This pull request adds a new security dependency and updates middleware functionality. The `package.json` now includes the `@arcjet/next` package at version `1.0.0-beta.3`. In the middleware file, an `arcjet` instance is created using an environment-based site key, and the middleware function is modified to asynchronously check incoming requests. If a request is denied by the `aj.protect(req)` check, a 403 JSON response is returned, adding an extra layer of security to protected routes.

## Changes

| File(s)              | Change Summary |
|----------------------|----------------|
| package.json         | Added dependency `@arcjet/next` at version `1.0.0-beta.3`. |
| src/middleware.ts    | Introduced new security middleware using `arcjet`. Added import and instance creation, made the middleware asynchronous to call `aj.protect(req)`, returning a 403 JSON response if the request is denied. |
| .env                 | Added environment variable `ARCJET_KEY=YOUR-KEY`. |
| src/libs/Env.ts      | Added optional environment variable `ARCJET_KEY` in `createEnv` function and mapped it to `process.env.ARCJET_KEY`. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant C as Client
    participant M as Middleware
    participant A as Arcjet

    C->>M: Send Request
    M->>A: Call aj.protect(req)
    A-->>M: Return decision (allow/deny)
    alt Request Allowed
        M->>Protected: Forward Request
        Protected-->>M: Processed Response
        M->>C: Return Response
    else Request Denied
        M->>C: Return 403 Forbidden JSON Response
    end
```

## Poem
> I'm a rabbit leaping through lines of code,  
> With arcjet-powered hops, my route's securely bestowed.  
> Dependencies added, middleware now smarter,  
> Guarding every request like a vigilant starter.  
> Hoppy times ahead with each bug deferred!  
> 🐰💫

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- DwQgtGAEAqAWCWBnSTIEMB26CuAXA9mAOYCmGJATmriQCaQDG+Ats2bgFyQAOFk+AIwBWJBrngA3EsgEBPRvlqU0AgfFwA6NPEgQAfACgjoCEejqANiS4BVbrWolIzeLVpWA7mgokNuRAYActjMApRcAKwGNojhkADKlKQA6vAWAGYU8HRG+sbgUGT0+Ok4BMRkyjT0TKzsXLz8wqLiUjLyTEpUqupaOnkmUHCoqJhlhKTkVNUKdRickFQekIghzN7ycgpdKmqa2rpghvmmBtxoDADWaKQaQoj4GBwGAERvBgDEH5AAggCSFSmjnoq1YG34pQYsEwpACBh+kHIyyU3CKZAY8mhMhIZHQbjokAIhNgTgABii0RgGNlEKSVi14I8IcSyecrjdfPdHnT0mlfDASXilPQLPByCtUdTedIWTwLtdSJBSQABbwMES4AD05AAHrg6R51LBZVIKIhGVhSQBGDQABjtYDCuDQGgAzKSNALKE5vE4MPhIEorOJHsh8HxmIp4LyGNQLcgiSQdUhxBgiIGSKiMEoqTT+Hx8LgSXxYmJ48yi05eVYNEYjF9fhYaNNy0TKxmGBZvHHQ8yk9xwzNwzxsAJRQxIOx1DTcpAACKZykYoV0LgqtUa7VJ/WQU3mpnWu0Op0u90oS1shWch4YUmvd4GCBgIyICgMTUuNyeX1+RDPN4vJ83z/ICVQEqC6wUPIJSMNCabSGYgpQjCMpirgFCKNgDA+oiJDLJ+7h4b6kDpNgVIhhgaCirg8jYOaaayqSG4kDuooCFQUGEgGZBwdh9IMNgWQ0ZAWy8IWDIMTc2gYIguCzJGWDUM6VyIJ6CJIuesmYHxMFMW+Gp0qgDA+MCkCGkW6ArOoTiXCQ8gPIJ2H0JkLDoFgZASPAGEYGw8y7t48AqFYbk1I8vJEIJBLmcaaBKogCAkBYtB0hQ2DBbEclEi8c4AEoAJoAPo5TYgQvAANGZCBQpAFj4EQyA+AAjtg0j+GZRr4HgIm1VcYrppWzCenATgEd+PgkWRZZMqgka0NG2T0ESYToIgshUrA3mdYgFVUbVhoMeoXHoF4h3tko1L7lgLnMEqaBCBoYk0GIAAUTUAJSkhVHhVcaSjNi45DINGspNS1skrLAnVJSJTg5gtnp/KUZ2iEgFrnnNsY0MgcNUTtkAAFLxAA8oEizSAOMlONFlkACy2q6KzOrgdEhW5k4UBhEbSIgHKQC8ABi4ZqPiGAvCgDUsYJ5C0ENCDIGgbjyzVaCyJQzKloJ6ibPIvAkFI8x9ZAZFoHgkNZAAXgSFzYYgCYBo9LQEhheDSLLThJimhu1UQ8ATukw5we4hsO2ITudVjZPrGKQPzBcuAVQIXX+ssYqdtgSgJnLQrTo8VGwaIlwkcOJtFuG8Dmz2WBhP741idhdB9bWQGNs2ld27K51di2vYwf2g4EsO3CjuOk4G+ICGPpAgR4SgzADhQckK8Ka7MfHkAAN4Q9k0MAL48hhN3rvpLFbnqhmWq+76jURPi/neUDT8sTAyc6fmd76tBrs/4N3efcVvh+VwhEvC338HeACuRTgaA8v+d4DYQKTDAiCNY4IYLIXgnCYagZoylDQhhWgWEZSxQ0h5LyjxfJyQkAFIKsNRBd0rkXPgpIfg5QAML4wAKLQAKgAaQ4XlP+7YPQeR5HyWWow3A5ywPgBgAkzToHSM2WUHtZKG1iDJacUhAzUFiqWCiFVECSnmrGCwFhaLZjVsQmetQKGQBJArNWXYwhWHoKSD4LD2FcI9F6GqYofT4noKgZhbDOHcL4XlAAvHlImNgcpgHCZ9SqvtjSGJRtKJW3AuzYUhklNWVCLAtUYYxDxoTeH8O8cNcaxF/QZmDOWYcs1jFtyOio1M6ZRSAwANyynQYqB4VgzEKA0bJMMSMs4aSoVkGhHZ6EUSbvWYCTYqitgDMjTs3YKKjMnDqeeQ4+BDzHL7Ue4hx5wigAANWoWOfxy8lQlK4WUyJ0TYnxPKeeJU0CMASHAQ+J8L4AFsUQJqDhXzfywMAvAgEiDpjgRQZxNBcFYSIVhjg886FMI20shpfA3AKJ51Id5WxkzArXIqsEzxYTykVTbIKUkILvlDPCoJBhYpGLGRII4elPJJpzIFBIuaFF+CyMEjHEShZjRCNiBQU0dJMCuNSgbNgXL+KbIrIKPuC8CR0q+XSQQIgxBuzuSEh5CTxYZl5NLFallZJZAYkWagZqcV4osO89sUrTSMvgBFbuGAdrZhQHJUYFgHjODQNwVEi1VlIXDD4Qxjw5oMQJeQ9g/kpnXNdYKBV4g2Cj08oS9gnpAgBnFWrRpMZmmJmTKohixKaFhhLOhLCzNY3oFrrGlNrKzo4Pmc3H4SyfXtzWbM+ppQNV7JHIcicU5TmzkfqmklwUl6riNRSx5XBzYaBtX1Z6b0NBOotFRHdf9SSX01IC4FoKwGTznbW9N6xw2GyXZ/FdpTwkNAwjbVSHkND3MpQI95J6AXwAEEC+ld97yAUfEcE4hR/UwRLhMSoMLQpzAWEsFYcLtbbGUD0fY/RoODHkuoAqrhEAFR8J5PCdACpaQXocY4hGABMAAOAAbDTAAnGgdIjH0gRFoFaV0HG6BoBILaCIbGSCseYxEV0DBaAcZpjTK0HHXRoDQBEGm9ABgFEgKxiI6Q0CsdtOkW0tAIgcYAOysbQDTNAjGBDYXSLQFjrHXSqA0wIZjAhaC2gYK6K0AgrT0YMIRkgHGHPYQEBx9IlnePMddDJgQGnWMMGY4xyzAhGMkG84p2g6R0hWkYxx4TsU8ihd0zY4jpHyN62yB4ajRR6NAA== -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=SergeWilfried/doohi&utm_content=5):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: netlify[bot]
created_at: 2025-03-08T14:43:35Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *cdoohi* ready!


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit |  |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/cdoohi/deploys/67cc619557c214812531a60e |
|<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-5--cdoohi.netlify.app](https://deploy-preview-5--cdoohi.netlify.app) |
|<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTUtLWNkb29oaS5uZXRsaWZ5LmFwcCJ9.emeY1mTMJ5zq2UuiZ6eGrpf6pQdir9gdrg2osl2o1s0)<br /><br />_Use your smartphone camera to open QR code link._</details> |
---
<!-- [cdoohi Preview](https://deploy-preview-5--cdoohi.netlify.app) -->
_To edit notification comments on pull requests, go to your [Netlify site configuration](https://app.netlify.com/sites/cdoohi/configuration/notifications#deploy-webhooks)._
author_association: NONE