diff --git a/pdm.lock b/pdm.lock
index 58ead28a30d4e7f10561ecaa48d2a74c33ad95a2..d74b5f1625891e6aeb84ad493db5a3a54ce25a8b 100644
--- a/pdm.lock
+++ b/pdm.lock
@@ -2,10 +2,10 @@
 # It is not intended for manual editing.
 
 [metadata]
-groups = ["default", "dev", "lint", "local"]
+groups = ["default", "dev", "lint", "local", "typing"]
 strategy = ["inherit_metadata"]
 lock_version = "4.5.0"
-content_hash = "sha256:a7320608dc0e3c00f197dee7ada9261e62bd35dd235e56b9532d22126d225946"
+content_hash = "sha256:1a9697a08aa14dbec10f593156b8222ce9b548a907c96e9d60c8874dadcccb5c"
 
 [[metadata.targets]]
 requires_python = "==3.13.*"
@@ -32,7 +32,7 @@ name = "asgiref"
 version = "3.8.1"
 requires_python = ">=3.8"
 summary = "ASGI specs, helper code, and adapters"
-groups = ["default"]
+groups = ["default", "typing"]
 dependencies = [
     "typing-extensions>=4; python_version < \"3.11\"",
 ]
@@ -393,7 +393,7 @@ name = "django"
 version = "5.1.2"
 requires_python = ">=3.10"
 summary = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
-groups = ["default"]
+groups = ["default", "typing"]
 dependencies = [
     "asgiref<4,>=3.8.1",
     "sqlparse>=0.3.1",
@@ -530,6 +530,55 @@ files = [
     {file = "django_storages-1.14.4-py3-none-any.whl", hash = "sha256:d61930acb4a25e3aebebc6addaf946a3b1df31c803a6bf1af2f31c9047febaa3"},
 ]
 
+[[package]]
+name = "django-stubs"
+version = "5.1.1"
+requires_python = ">=3.8"
+summary = "Mypy stubs for Django"
+groups = ["typing"]
+dependencies = [
+    "asgiref",
+    "django",
+    "django-stubs-ext>=5.1.1",
+    "tomli; python_version < \"3.11\"",
+    "types-PyYAML",
+    "typing-extensions>=4.11.0",
+]
+files = [
+    {file = "django_stubs-5.1.1-py3-none-any.whl", hash = "sha256:c4dc64260bd72e6d32b9e536e8dd0d9247922f0271f82d1d5132a18f24b388ac"},
+    {file = "django_stubs-5.1.1.tar.gz", hash = "sha256:126d354bbdff4906c4e93e6361197f6fbfb6231c3df6def85a291dae6f9f577b"},
+]
+
+[[package]]
+name = "django-stubs-ext"
+version = "5.1.1"
+requires_python = ">=3.8"
+summary = "Monkey-patching and extensions for django-stubs"
+groups = ["typing"]
+dependencies = [
+    "django",
+    "typing-extensions",
+]
+files = [
+    {file = "django_stubs_ext-5.1.1-py3-none-any.whl", hash = "sha256:3907f99e178c93323e2ce908aef8352adb8c047605161f8d9e5e7b4efb5a6a9c"},
+    {file = "django_stubs_ext-5.1.1.tar.gz", hash = "sha256:db7364e4f50ae7e5360993dbd58a3a57ea4b2e7e5bab0fbd525ccdb3e7975d1c"},
+]
+
+[[package]]
+name = "django-stubs"
+version = "5.1.1"
+extras = ["mypy-compatible"]
+requires_python = ">=3.8"
+summary = "Mypy stubs for Django"
+groups = ["typing"]
+dependencies = [
+    "django-stubs==5.1.1",
+]
+files = [
+    {file = "django_stubs-5.1.1-py3-none-any.whl", hash = "sha256:c4dc64260bd72e6d32b9e536e8dd0d9247922f0271f82d1d5132a18f24b388ac"},
+    {file = "django_stubs-5.1.1.tar.gz", hash = "sha256:126d354bbdff4906c4e93e6361197f6fbfb6231c3df6def85a291dae6f9f577b"},
+]
+
 [[package]]
 name = "django-timezone-field"
 version = "7.0"
@@ -1698,7 +1747,7 @@ name = "sqlparse"
 version = "0.5.1"
 requires_python = ">=3.8"
 summary = "A non-validating SQL parser."
-groups = ["default"]
+groups = ["default", "typing"]
 files = [
     {file = "sqlparse-0.5.1-py3-none-any.whl", hash = "sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4"},
     {file = "sqlparse-0.5.1.tar.gz", hash = "sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e"},
@@ -1780,12 +1829,23 @@ files = [
     {file = "truststore-0.9.2.tar.gz", hash = "sha256:a1dee0d0575ff22d2875476343783a5d64575419974e228f3248772613c3d993"},
 ]
 
+[[package]]
+name = "types-pyyaml"
+version = "6.0.12.20240917"
+requires_python = ">=3.8"
+summary = "Typing stubs for PyYAML"
+groups = ["typing"]
+files = [
+    {file = "types-PyYAML-6.0.12.20240917.tar.gz", hash = "sha256:d1405a86f9576682234ef83bcb4e6fff7c9305c8b1fbad5e0bcd4f7dbdc9c587"},
+    {file = "types_PyYAML-6.0.12.20240917-py3-none-any.whl", hash = "sha256:392b267f1c0fe6022952462bf5d6523f31e37f6cea49b14cee7ad634b6301570"},
+]
+
 [[package]]
 name = "typing-extensions"
 version = "4.12.2"
 requires_python = ">=3.8"
 summary = "Backported and Experimental Type Hints for Python 3.8+"
-groups = ["default"]
+groups = ["default", "typing"]
 files = [
     {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
     {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
@@ -1796,7 +1856,7 @@ name = "tzdata"
 version = "2024.2"
 requires_python = ">=2"
 summary = "Provider of IANA time zone data"
-groups = ["default"]
+groups = ["default", "typing"]
 files = [
     {file = "tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd"},
     {file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"},
diff --git a/pyproject.toml b/pyproject.toml
index ce737d4e3f11d3e6ef3c777d2a38263fbf0c1762..48ea6537b9ebe084c687ad6d9fb95178edd0fc25 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -70,6 +70,9 @@ dev = [
     "pre-commit>=3.6.0",
     "docutils>=0.21.2",
 ]
+typing = [
+    "django-stubs[mypy-compatible]>=5.1.1",
+]
 
 [tool.pdm.scripts]
 # Generic scripts
@@ -107,3 +110,10 @@ output = ".tools/coverage/coverage.xml"
 
 [tool.coverage.html]
 directory = ".tools/coverage/html_report"
+
+
+[tool.mypy]
+plugins=["mypy_django_plugin.main"]
+
+[tool.django-stubs]
+django_settings_module="hub.settings.base"
diff --git a/requirements.dev.txt b/requirements.dev.txt
index da13333eeabfcc34a0ea3697db434cabd74c7543..8f0630377cc004f2a709cfaeed831b082c3b7a50 100644
--- a/requirements.dev.txt
+++ b/requirements.dev.txt
@@ -35,6 +35,8 @@ django-oauth-toolkit==3.0.1
 django-ratelimit==4.1.0
 django-redis==5.4.0
 django-storages==1.14.4
+django-stubs-ext==5.1.1
+django-stubs[mypy-compatible]==5.1.1
 django-timezone-field==7.0
 django-widget-tweaks==1.5.0
 djangorestframework==3.15.2
@@ -117,6 +119,7 @@ tox==4.23.0
 tox-pdm==0.7.2
 tqdm==4.66.5
 truststore==0.9.2; python_version >= "3.10"
+types-pyyaml==6.0.12.20240917
 typing-extensions==4.12.2
 tzdata==2024.2
 unearth==0.17.2