diff --git a/.dev-js/package.json b/.dev-js/package.json
index f1a3b8b143115ffb8f0fee2d452ec2830cd888a3..99b0989e1dde9b0f71fdc229bac3aef501c06398 100644
--- a/.dev-js/package.json
+++ b/.dev-js/package.json
@@ -6,7 +6,7 @@
     "eslint": "^8.26.0",
     "eslint-config-prettier": "^9.0.0",
     "eslint-plugin-vue": "^9.7.0",
-    "prettier": "^3.0.0",
+    "prettier": "^3.4.0",
     "stylelint": "^15.0.0",
     "stylelint-config-prettier": "^9.0.3",
     "stylelint-config-standard": "^34.0.0"
diff --git a/README.rst b/README.rst
index 6e4c646ff977dd48c7f01dd2bbce56d6889d8e5a..0020cd7a098b4519723e3b72de46726b92409b2c 100644
--- a/README.rst
+++ b/README.rst
@@ -1,5 +1,5 @@
-AlekSIS (School Information System) — App Lesrooster (Manage lessons in a timetable schema)
-==================================================================================================
+AlekSIS (School Information System) — App Lesrooster (Timetable Management Using Time Grids)
+============================================================================================
 
 AlekSIS
 -------
@@ -9,14 +9,21 @@ This is an application for use with the `AlekSIS®`_ platform.
 Features
 --------
 
-The author of this app did not describe it yet.
+* Manage validity ranges for timetables.
+* Manage different timetable grids for different validity ranges and groups (with slots and breaks).
+* Do lesson distribution using course planning raster.
+* Plan timetables using magnet board.
+* Manage supervisions for breaks.
 
 Licence
 -------
 
 ::
 
-  Copyright © 2023 Jonathan Weth <dev@jonathanweth.de>
+  Copyright © 2023, 2024 Julian Leucker <julian.leucker@teckids.org>
+  Copyright © 2023, 2024 Jonathan Weth <jonathan.weth@teckids.org>
+  Copyright © 2023, 2024 Hangzhi Yu <hangzhi.yu@teckids.org>
+  Copyright © 2024 magicfelix <felix@felix-zauberer.de>
 
   Licenced under the EUPL, version 1.2 or later
 
diff --git a/aleksis/apps/lesrooster/apps.py b/aleksis/apps/lesrooster/apps.py
index 68ee1b18309c2834eaf27ed1749dd90d14fb0936..4188f6faadcc7bb19279c15bc078f117538653f8 100644
--- a/aleksis/apps/lesrooster/apps.py
+++ b/aleksis/apps/lesrooster/apps.py
@@ -3,11 +3,17 @@ from aleksis.core.util.apps import AppConfig
 
 class DefaultConfig(AppConfig):
     name = "aleksis.apps.lesrooster"
-    verbose_name = "AlekSIS — Lesrooster"
+    verbose_name = "AlekSIS — Lesrooster (Timetable Management Using Time Grids)"
     dist_name = "AlekSIS-App-Lesrooster"
 
     urls = {
-        "Repository": "https://edugit.org/AlekSIS/onboarding//AlekSIS-App-Lesrooster",
+        "Repository": "https://edugit.org/AlekSIS/onboarding/AlekSIS-App-Lesrooster",
     }
     licence = "EUPL-1.2+"
-    copyright_info = (([2023], "Jonathan Weth", "dev@jonathanweth.de"),)
+
+    copyright_info = (
+        ([2023, 2024], "Julian Leucker", "julian.leucker@teckids.org"),
+        ([2023, 2024], "Jonathan Weth", "jonathan.weth@teckids.org"),
+        ([2023, 2024], "Hangzhi Yu", "hangzhi.yu@teckids.org"),
+        ([2024], "magicfelix", "felix@felix-zauberer.de"),
+    )
diff --git a/aleksis/apps/lesrooster/tests/test_validity_range.py b/aleksis/apps/lesrooster/tests/test_validity_range.py
index 22723116a2b9ef044f6a2b253ed5c214f070ef8b..aad9393c64526356fb6a1cf29356b111a69689bb 100644
--- a/aleksis/apps/lesrooster/tests/test_validity_range.py
+++ b/aleksis/apps/lesrooster/tests/test_validity_range.py
@@ -205,7 +205,8 @@ def test_change_published_validity_range():
         validity_range.date_end = validity_range.date_end - timedelta(days=4)
         with pytest.raises(
             ValidationError,
-            match=r".*To avoid data loss, the validity range can be only shortened until the current day.*",
+            match=r".*To avoid data loss, the validity range "
+            r"can be only shortened until the current day.*",
         ):
             validity_range.full_clean()
 
diff --git a/pyproject.toml b/pyproject.toml
index 14c21b0cf6a5d012fb2ed25c5af8129ee53c5b96..dcac57116e64a7baf60008c0e15ddb467befb73a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -11,18 +11,23 @@ include = [
     { path = "tox.ini", format = "sdist" }
 ]
 
-description = "AlekSIS (School Information System) — App Lesrooster (Manage lessons in a timetable schema)"
-authors = ["Jonathan Weth <dev@jonathanweth.de>"]
+description = "AlekSIS (School Information System) — App Lesrooster (Timetable Management Using Time Grids)"
+authors = [
+    "Julian Leucker <julian.leucker@teckids.org>",
+    "magicfelix <felix@felix-zauberer.de>",
+    "Jonathan Weth <dev@jonathanweth.de>",
+    "Hangzhi Yu <hangzhi.yu@teckids.org>",
+]
 license = "EUPL-1.2-or-later"
 homepage = "https://aleksis.org"
-repository = "https://edugit.org/AlekSIS/onboarding//AlekSIS-App-Lesrooster"
+repository = "https://edugit.org/AlekSIS/onboarding/AlekSIS-App-Lesrooster"
 documentation = "https://aleksis.org/official/AlekSIS/docs/html/"
 classifiers = [
     "Environment :: Web Environment",
     "Intended Audience :: Education",
     "Topic :: Education"
 ]
-maintainers = ["Jonathan Weth <dev@jonathanweth.de>", "Dominik George <dominik.george@teckids.org>"]
+maintainers = ["Jonathan Weth <jonathan.weth@teckids.org>", "Dominik George <dominik.george@teckids.org>"]
 
 [[tool.poetry.source]]
 name = "PyPI"
@@ -32,7 +37,6 @@ priority = "primary"
 name = "gitlab"
 url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
 priority = "supplemental"
-
 [tool.poetry.dependencies]
 python = "^3.10"
 AlekSIS-Core = "^4.0.0.dev11"
@@ -43,23 +47,20 @@ django-recurrence = "^1.11.1"
 [tool.poetry.plugins."aleksis.app"]
 lesrooster = "aleksis.apps.lesrooster.apps:DefaultConfig"
 
-
 [tool.poetry.group.dev.dependencies]
 django-stubs = "^4.2"
 safety = "^2.3.5"
 
-ruff = "^0.1.5"
-
-curlylint = "^0.13.0"
+ruff = "^0.8.2"
 
 [tool.poetry.group.test.dependencies]
-pytest = "^7.2"
-pytest-django = "^4.1"
+pytest = "^8.3"
+pytest-django = "^4.9"
 pytest-django-testing-postgresql = "^0.2"
-pytest-cov = "^4.0.0"
-pytest-sugar = "^0.9.2"
-selenium = "<4.10.0"
-freezegun = "^1.1.0"
+pytest-cov = "^6.0.0"
+pytest-sugar = "^1.0.0"
+selenium = "^4.27.0"
+freezegun = "^1.5.0"
 pytest-mock = "^3.14.0"
 
 [tool.poetry.group.docs]
@@ -71,7 +72,6 @@ sphinxcontrib-django = "^2.3.0"
 sphinxcontrib-svg2pdfconverter = "^1.1.1"
 sphinx-autodoc-typehints = "^1.7"
 sphinx_material = "^0.0.35"
-
 [tool.curlylint]
 include = '\.html'
 
@@ -84,20 +84,20 @@ meta_viewport = true
 no_autofocus = true
 tabindex_no_positive = true
 
-
 [tool.ruff]
-exclude = ["migrations", "tests"]
+exclude = ["migrations"]
 line-length = 100
 
 [tool.ruff.lint]
 select = ["E", "F", "UP", "B", "SIM", "I", "DJ", "A", "S"]
 ignore = ["UP034", "UP015", "B028"]
-
-[tool.ruff.isort]
+[tool.ruff.lint.extend-per-file-ignores]
+"**/*/tests/**/*.py" = ["S101", "ARG", "FBT", "PLR2004", "S311", "S105"]
+[tool.ruff.lint.isort]
 known-first-party = ["aleksis"]
 section-order = ["future", "standard-library", "django", "third-party", "first-party", "local-folder"]
 
-[tool.ruff.isort.sections]
+[tool.ruff.lint.isort.sections]
 django = ["django"]
 [build-system]
 requires = ["poetry-core>=1.0.0"]
diff --git a/tox.ini b/tox.ini
index 294e65bc96d4e06262b67e3e6b8a987307b226e4..92f26b55d9ebd6f5b3db425cab8d151bde0c0c69 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,7 @@
 [tox]
 skipsdist = True
 skip_missing_interpreters = true
-envlist = py39,py310,py311
+envlist = py310,py311,py312
 
 [testenv]
 allowlist_externals =