diff --git a/aleksis/apps/chronos/frontend/components/AmendLesson.vue b/aleksis/apps/chronos/frontend/components/AmendLesson.vue
index 7f06f71bbf16b7c5f55b310c13dd087d58833f11..7c73702d4edaa3115a1d48b810958bf954611964 100644
--- a/aleksis/apps/chronos/frontend/components/AmendLesson.vue
+++ b/aleksis/apps/chronos/frontend/components/AmendLesson.vue
@@ -1,5 +1,8 @@
 <template>
-  <v-card-actions v-if="checkPermission('chronos.edit_substitution_rule')">
+  <div
+    v-if="checkPermission('chronos.edit_substitution_rule')"
+    style="display: contents"
+  >
     <edit-button
       i18n-key="chronos.event.amend.edit_button"
       @click="edit = true"
@@ -84,7 +87,7 @@
         {{ $t("chronos.event.amend.delete_dialog") }}
       </template>
     </delete-dialog>
-  </v-card-actions>
+  </div>
 </template>
 
 <script>
diff --git a/aleksis/apps/chronos/frontend/components/calendar_feeds/details/LessonDetails.vue b/aleksis/apps/chronos/frontend/components/calendar_feeds/details/LessonDetails.vue
index 627dd2fe2e8395da29d8d6c4162e29b99b2f1d1e..2f014dceda872564f1d120cbccd1c6b8fe404399 100644
--- a/aleksis/apps/chronos/frontend/components/calendar_feeds/details/LessonDetails.vue
+++ b/aleksis/apps/chronos/frontend/components/calendar_feeds/details/LessonDetails.vue
@@ -100,16 +100,26 @@
           </v-list-item-title>
         </v-list-item-content>
       </v-list-item>
-      <amend-lesson
-        v-if="selectedEvent"
-        :selected-event="selectedEvent"
-        @refreshCalendar="$emit('refreshCalendar')"
-      />
+      <v-card-actions class="flex-wrap" style="gap: 0.5em">
+        <amend-lesson
+          v-if="selectedEvent"
+          :selected-event="selectedEvent"
+          @refreshCalendar="$emit('refreshCalendar')"
+        />
+
+        <component
+          v-for="action in actions"
+          :is="action.component"
+          :key="action.key"
+          :lesson="selectedEvent"
+        />
+      </v-card-actions>
     </template>
   </base-calendar-feed-details>
 </template>
 
 <script>
+import { collections } from "aleksisAppImporter";
 import calendarFeedDetailsMixin from "aleksis.core/mixins/calendarFeedDetails.js";
 import BaseCalendarFeedDetails from "aleksis.core/components/calendar/BaseCalendarFeedDetails.vue";
 import CalendarStatusChip from "aleksis.core/components/calendar/CalendarStatusChip.vue";
@@ -133,5 +143,12 @@ export default {
     AmendLesson,
   },
   mixins: [calendarFeedDetailsMixin, lessonEvent],
+  computed: {
+    actions() {
+      return collections.chronosLessonEventCalendarAdditionalActions.items.filter(
+        (action) => action.shouldDisplay.call(this, this.selectedEvent),
+      );
+    },
+  },
 };
 </script>
diff --git a/aleksis/apps/chronos/frontend/components/calendar_feeds/mixins/lessonEventAdditionalCalendarActionMixin.js b/aleksis/apps/chronos/frontend/components/calendar_feeds/mixins/lessonEventAdditionalCalendarActionMixin.js
new file mode 100644
index 0000000000000000000000000000000000000000..b08c58d1b5cd85c93dc21f25306e1872232f1929
--- /dev/null
+++ b/aleksis/apps/chronos/frontend/components/calendar_feeds/mixins/lessonEventAdditionalCalendarActionMixin.js
@@ -0,0 +1,8 @@
+export default {
+  props: {
+    lesson: {
+      type: Object,
+      required: true,
+    },
+  },
+};
diff --git a/aleksis/apps/chronos/frontend/index.js b/aleksis/apps/chronos/frontend/index.js
index 34a0380b03bc23645f765e08149cb0ce37a9a3a2..2333a2d64b36c12e60e2f9288dada8a8aa889336 100644
--- a/aleksis/apps/chronos/frontend/index.js
+++ b/aleksis/apps/chronos/frontend/index.js
@@ -3,6 +3,29 @@ import { hasPersonValidator } from "aleksis.core/routeValidators";
 import Substitutions from "./components/Substitutions.vue";
 import { DateTime } from "luxon";
 
+export const collections = [
+  /**
+   * List of components that can trigger actions for Lessons
+   * and Substitutions in the timetable/calendar.
+   *
+   * An object in this list looks like this:
+   * ```js
+   * {
+   *     component: () => import("foo.vue"),
+   *     shouldDisplay: (lessonEvent) => true || false,
+   *     key: "shouldBeUnique",
+   * }
+   * ```
+   *
+   * Please use the lessonEventAdditionalCalendarActionMixin
+   * as a base for the component.
+   */
+  {
+    name: "lessonEventCalendarAdditionalActions",
+    type: Object,
+  },
+];
+
 export default {
   meta: {
     inMenu: true,