diff --git a/aleksis/apps/chronos/frontend/components/Substitutions.vue b/aleksis/apps/chronos/frontend/components/Substitutions.vue
new file mode 100644
index 0000000000000000000000000000000000000000..25239443bf611cb04dc6fb1ab8eca26a64431845
--- /dev/null
+++ b/aleksis/apps/chronos/frontend/components/Substitutions.vue
@@ -0,0 +1,49 @@
+<script setup>
+import CRUDList from "aleksis.core/components/generic/CRUDList.vue";
+</script>
+
+<template>
+  <c-r-u-d-list
+    headers="headers"
+    show-select="false"
+    enable-create="false"
+    enable-edit="false"
+  />
+  </c-r-u-d-list>
+</template>
+
+<script>
+export default {
+  name: "Substitutions",
+  data() {
+    return {
+      headers: [
+        {
+          text:
+          value:
+        },
+        {
+          text:
+          value:
+        },
+        {
+          text:
+          value:
+        },
+        {
+          text:
+          value:
+        },
+        {
+          text:
+          value:
+        },
+        {
+          text:
+          value:
+        },
+      ],
+    };
+},
+}
+</script>
diff --git a/aleksis/apps/chronos/frontend/components/substitutions.graphql b/aleksis/apps/chronos/frontend/components/substitutions.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..4e372b2c3b308703240033e83df61c6249052343
--- /dev/null
+++ b/aleksis/apps/chronos/frontend/components/substitutions.graphql
@@ -0,0 +1,25 @@
+query substitutionsForDate ($date: Date!) {
+  substitutionsForDate(date: $date) {
+    affectedTeachers {
+    }
+    affectedGroups {
+    }
+    substitutions {
+      groups {
+      }
+      period {
+      
+      }
+      teachers {
+      }
+      subject {
+      }
+      rooms {
+      }
+      badge {
+      }
+      comment {
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/aleksis/apps/chronos/frontend/index.js b/aleksis/apps/chronos/frontend/index.js
index b0a6a97fbe9357bc45cc26dac0784162774aacdf..70f4064a69e8eb57fe8bcbd7b7eecc13ff961017 100644
--- a/aleksis/apps/chronos/frontend/index.js
+++ b/aleksis/apps/chronos/frontend/index.js
@@ -1,5 +1,6 @@
 import { hasPersonValidator } from "aleksis.core/routeValidators";
 import Timetable from "./components/Timetable.vue";
+import Substitutions from "./components/Substitutions.vue";
 
 export default {
   meta: {
@@ -46,7 +47,7 @@ export default {
     {
       path: "substitutions/print/",
       component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
-      name: "chronos.substitutions",
+      name: "chronos.printsubstitutions",
       props: {
         byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
       },
@@ -54,10 +55,23 @@ export default {
     {
       path: "substitutions/print/:date/",
       component: () => import("aleksis.core/components/LegacyBaseTemplate.vue"),
-      name: "chronos.substitutionsByDate",
+      name: "chronos.printSubstitutionsForDate",
       props: {
         byTheGreatnessOfTheAlmightyAleksolotlISwearIAmWorthyOfUsingTheLegacyBaseTemplate: true,
       },
     },
+    {
+      path: "substitutions/:date/",
+      component: Substitutions,
+      name: "chronos.listSubstitutionsForDate",
+      meta: {
+        inMenu: true,
+        titleKey: "chronos.substitutions.menu_title",
+        toolbarTitle: "chronos.substitutions.menu_title",
+        icon: "mdi-grid",
+        permission: "chronos.view_substitutions_rule",
+        fullWidth: true,
+      },
+    },
   ],
 };
diff --git a/aleksis/apps/chronos/schema/__init__.py b/aleksis/apps/chronos/schema/__init__.py
index d9194e6718112025b4e41713cd00ff5d043bebf6..acb8f791dd88d55f34a7bc31650c2dc3d23ff3cc 100644
--- a/aleksis/apps/chronos/schema/__init__.py
+++ b/aleksis/apps/chronos/schema/__init__.py
@@ -7,9 +7,12 @@ from aleksis.core.schema.base import (
     BaseBatchDeleteMutation,
     BaseBatchPatchMutation,
 )
+from aleksis.core.schema.person import PersonType
+from aleksis.core.schema.group import GroupType
 
 from ..models import LessonEvent
-from ..util.chronos_helpers import get_groups, get_rooms, get_teachers
+from ..util.chronos_helpers import get_groups, get_rooms, get_teachers, get_next_relevant_day
+from ..util.build import build_substitutions_list
 
 
 class TimetablePersonType(DjangoObjectType):
@@ -122,11 +125,20 @@ class TimetableObjectType(graphene.ObjectType):
         return f"{root.type.value}-{root.id}"
 
 
+class SubstitutionsForDateType(graphene.ObjectType):
+    affected_teachers = graphene.List(PersonType)
+    affected_groups = graphene.List(GroupType)
+    substitutions = graphene.List(LessonEventType)
+
 class Query(graphene.ObjectType):
     timetable_teachers = graphene.List(TimetablePersonType)
     timetable_groups = graphene.List(TimetableGroupType)
     timetable_rooms = graphene.List(TimetableRoomType)
     available_timetables = graphene.List(TimetableObjectType)
+    substitutions_for_date = graphene.List(
+        SubstitutionsForDateType,
+        date=graphene.Date,
+    )
 
     def resolve_timetable_teachers(self, info, **kwargs):
         return get_teachers(info.context.user)
@@ -168,6 +180,13 @@ class Query(graphene.ObjectType):
 
         return all_timetables
 
+    def resolve_substitutions_for_date(root, info, date):
+        substitutions, affected_teachers, affected_groups = build_substitutions_list(get_next_relevant_day(date))
+        SubstitutionsForDateType(
+            affected_teachers=affected_teachers,
+            affected_groups=affected_groups,
+            substitutions=[sub['el']['REFERENCE_OBJECT'] for sub in substitutions]
+        )
 
 class Mutation(graphene.ObjectType):
     create_amend_lessons = AmendLessonBatchCreateMutation.Field()