diff --git a/aleksis/core/frontend/components/calendar/BaseCalendarFeedDetails.vue b/aleksis/core/frontend/components/calendar/BaseCalendarFeedDetails.vue
index 2db52ae5ef86ecf4534aee70ffd7d9939dffe453..a9dc64fdb9bfd5713d68d2ebf926b78ad255ea51 100644
--- a/aleksis/core/frontend/components/calendar/BaseCalendarFeedDetails.vue
+++ b/aleksis/core/frontend/components/calendar/BaseCalendarFeedDetails.vue
@@ -6,7 +6,7 @@
     offset-x
   >
     <v-card min-width="350px" flat>
-      <v-toolbar :color="selectedEvent.color" dark dense>
+      <v-toolbar :color="color || selectedEvent.color" dark dense>
         <v-toolbar-title>
           <slot name="title" :selected-event="selectedEvent">{{
             selectedEvent.name
@@ -14,41 +14,42 @@
         </v-toolbar-title>
         <v-spacer></v-spacer>
         <slot name="badge" :selected-event="selectedEvent">
-          <v-chip
+          <cancelled-calendar-status-chip
             v-if="selectedEvent.status === 'CANCELLED' && !withoutBadge"
-            color="error"
-            label
-          >
-            <v-avatar left>
-              <v-icon>mdi-cancel</v-icon>
-            </v-avatar>
-            {{ $t("calendar.cancelled") }}
-          </v-chip>
+          />
         </slot>
       </v-toolbar>
       <slot name="time" :selected-event="selectedEvent">
-        <v-card-text v-if="!withoutTime">
-          <v-icon left>mdi-calendar-today-outline</v-icon>
-          <span v-if="selectedEvent.start !== selectedEvent.end">
-            {{ $d(selectedEvent.start, "shortDateTime") }} –
-            {{ $d(selectedEvent.end, "shortDateTime") }}
-          </span>
-          <span v-else> {{ $d(selectedEvent.start, "shortDateTime") }}</span>
-        </v-card-text>
+        <v-list-item v-if="!withoutTime">
+          <v-list-item-icon>
+            <v-icon color="primary">mdi-calendar-today-outline</v-icon>
+          </v-list-item-icon>
+          <v-list-item-content>
+            <v-list-item-title>
+              <span v-if="selectedEvent.start !== selectedEvent.end">
+                {{ $d(selectedEvent.start, "shortDateTime") }} –
+                {{ $d(selectedEvent.end, "shortDateTime") }}
+              </span>
+              <span v-else>
+                {{ $d(selectedEvent.start, "shortDateTime") }}</span
+              >
+            </v-list-item-title>
+          </v-list-item-content>
+        </v-list-item>
       </slot>
       <slot name="description" :selected-event="selectedEvent">
-        <v-divider v-if="selectedEvent.description && !withoutDescription" />
-        <v-card-text
-          class="d-flex"
+        <v-divider
+          inset
           v-if="selectedEvent.description && !withoutDescription"
-        >
-          <div>
-            <v-icon left>mdi-card-text-outline</v-icon>
-          </div>
-          <div style="white-space: pre-line">
+        />
+        <v-list-item v-if="selectedEvent.description && !withoutDescription">
+          <v-list-item-icon>
+            <v-icon color="primary">mdi-card-text-outline</v-icon>
+          </v-list-item-icon>
+          <v-list-item-content style="white-space: pre-line">
             {{ selectedEvent.description }}
-          </div>
-        </v-card-text>
+          </v-list-item-content>
+        </v-list-item>
       </slot>
     </v-card>
   </v-menu>
@@ -56,9 +57,11 @@
 
 <script>
 import calendarFeedDetailsMixin from "../../mixins/calendarFeedDetails.js";
+import CancelledCalendarStatusChip from "./CancelledCalendarStatusChip.vue";
 
 export default {
   name: "BaseCalendarFeedDetails",
+  components: { CancelledCalendarStatusChip },
   mixins: [calendarFeedDetailsMixin],
 };
 </script>
diff --git a/aleksis/core/frontend/components/calendar/BaseCalendarFeedEventBar.vue b/aleksis/core/frontend/components/calendar/BaseCalendarFeedEventBar.vue
index 510e2af17160f6d2cbcacbf3d640cb18d1f9df5c..205cbb13a1c150555bec1e222244c2b361d31053 100644
--- a/aleksis/core/frontend/components/calendar/BaseCalendarFeedEventBar.vue
+++ b/aleksis/core/frontend/components/calendar/BaseCalendarFeedEventBar.vue
@@ -1,9 +1,8 @@
 <template>
   <div
-    class="mx-1 text-truncate"
-    :style="
-      event.status === 'CANCELLED' ? 'text-decoration: line-through;' : ''
-    "
+    class="text-truncate"
+    :class="{ 'text-decoration-line-through': event.status === 'CANCELLED', 'mx-1': withPadding }"
+    :style="{ height: '100%' }"
   >
     <slot name="time" v-bind="$props">
       <span
@@ -32,5 +31,22 @@ import calendarFeedEventBarMixin from "../../mixins/calendarFeedEventBar.js";
 export default {
   name: "BaseCalendarFeedEventBar",
   mixins: [calendarFeedEventBarMixin],
+    props: {
+      withPadding: {
+        required: false,
+        type: Boolean,
+        default: true,
+    },
+            icon: {
+      required: false,
+      type: String,
+      default: "",
+    },
+    withoutTime: {
+      required: false,
+      type: Boolean,
+      default: false,
+    },
+    }
 };
 </script>
diff --git a/aleksis/core/frontend/components/calendar/CalendarOverview.vue b/aleksis/core/frontend/components/calendar/CalendarOverview.vue
index 575475db559c39a24d8ffebf645b17d666594e91..db9d10a0ab8dfc30bcb68862646b1875a050f9a0 100644
--- a/aleksis/core/frontend/components/calendar/CalendarOverview.vue
+++ b/aleksis/core/frontend/components/calendar/CalendarOverview.vue
@@ -195,6 +195,7 @@ export default {
             end: new Date(event.end),
             color: event.color ? event.color : cf.color,
             timed: !event.allDay,
+            meta: JSON.parse(event.meta),
           }))
         );
     },
diff --git a/aleksis/core/frontend/components/calendar/CalendarStatusChip.vue b/aleksis/core/frontend/components/calendar/CalendarStatusChip.vue
new file mode 100644
index 0000000000000000000000000000000000000000..679749135dd12e302f18a797af4d8fb169a44470
--- /dev/null
+++ b/aleksis/core/frontend/components/calendar/CalendarStatusChip.vue
@@ -0,0 +1,24 @@
+<script>
+export default {
+  name: "CalendarStatusChip",
+  props: {
+    color: {
+      type: String,
+      required: true,
+    },
+    icon: {
+      type: String,
+      required: true,
+    },
+  },
+};
+</script>
+
+<template>
+  <v-chip :color="color" label>
+    <v-avatar left>
+      <v-icon>{{ icon }}</v-icon>
+    </v-avatar>
+    <slot></slot>
+  </v-chip>
+</template>
diff --git a/aleksis/core/frontend/components/calendar/CancelledCalendarStatusChip.vue b/aleksis/core/frontend/components/calendar/CancelledCalendarStatusChip.vue
new file mode 100644
index 0000000000000000000000000000000000000000..00b816943654453690f32da1db95e14f57b7dce7
--- /dev/null
+++ b/aleksis/core/frontend/components/calendar/CancelledCalendarStatusChip.vue
@@ -0,0 +1,14 @@
+<script>
+import CalendarStatusChip from "./CalendarStatusChip.vue";
+
+export default {
+  name: "CancelledCalendarStatusChip",
+  components: { CalendarStatusChip },
+};
+</script>
+
+<template>
+  <calendar-status-chip icon="mdi-cancel" color="error">
+    {{ $t("calendar.cancelled") }}
+  </calendar-status-chip>
+</template>
diff --git a/aleksis/core/frontend/components/calendar/calendarOverview.graphql b/aleksis/core/frontend/components/calendar/calendarOverview.graphql
index 061ab3872572d3c8e98ac1e75bc236f664f62000..777d2f5253ab24e7c07378eaf57e033f5bee874d 100644
--- a/aleksis/core/frontend/components/calendar/calendarOverview.graphql
+++ b/aleksis/core/frontend/components/calendar/calendarOverview.graphql
@@ -15,6 +15,7 @@ query ($start: Date, $end: Date) {
         uid
         allDay
         status
+        meta
       }
     }
   }
diff --git a/aleksis/core/frontend/mixins/calendarFeedDetails.js b/aleksis/core/frontend/mixins/calendarFeedDetails.js
index ef874b5c5600d487472ca73b957b4ed3fad801bc..4d3e9beda841af3b84eadbcb8fab910525ca518c 100644
--- a/aleksis/core/frontend/mixins/calendarFeedDetails.js
+++ b/aleksis/core/frontend/mixins/calendarFeedDetails.js
@@ -13,20 +13,25 @@ const calendarFeedDetailsMixin = {
     },
     value: { type: Boolean, required: true },
     withoutTime: {
-      required: true,
+      required: false,
       type: Boolean,
       default: false,
     },
     withoutDescription: {
-      required: true,
+      required: false,
       type: Boolean,
       default: false,
     },
     withoutBadge: {
-      required: true,
+      required: false,
       type: Boolean,
       default: false,
     },
+    color: {
+      required: false,
+      type: String,
+      default: null,
+    },
   },
   computed: {
     model: {
diff --git a/aleksis/core/frontend/mixins/calendarFeedEventBar.js b/aleksis/core/frontend/mixins/calendarFeedEventBar.js
index 5a0367c2b7590dce12f6eb5d85097e23bd1b1ced..3b6590b0f68e75090b200bd0aa0fcc747cfdef51 100644
--- a/aleksis/core/frontend/mixins/calendarFeedEventBar.js
+++ b/aleksis/core/frontend/mixins/calendarFeedEventBar.js
@@ -15,16 +15,6 @@ const calendarFeedEventBarMixin = {
       required: true,
       type: String,
     },
-    icon: {
-      required: false,
-      type: String,
-      default: "",
-    },
-    withoutTime: {
-      required: true,
-      type: Boolean,
-      default: false,
-    },
   },
 };
 
diff --git a/aleksis/core/schema/calendar.py b/aleksis/core/schema/calendar.py
index 4414249bc16259468c67256ee356732028cdaf7e..9aa2ad53227b1a3dca1f9b6ab0f0c4a629d21fe8 100644
--- a/aleksis/core/schema/calendar.py
+++ b/aleksis/core/schema/calendar.py
@@ -15,6 +15,7 @@ class CalendarEventType(ObjectType):
     uid = graphene.String()
     all_day = graphene.Boolean()
     status = graphene.String()
+    meta = graphene.String()
 
     def resolve_name(root, info, **kwargs):
         return root["SUMMARY"]
@@ -40,6 +41,9 @@ class CalendarEventType(ObjectType):
     def resolve_status(root, info, **kwargs):
         return root.get("STATUS", "")
 
+    def resolve_meta(root, info, **kwargs):
+        return root.get("X-META", {})
+
 
 class CalendarFeedType(ObjectType):
     events = graphene.List(
diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py
index 65576a76ce333b870e8eaeba2656cd92ae1c60ea..26bcd0b83521c76581be52ca1272b672c0f01696 100644
--- a/aleksis/core/util/core_helpers.py
+++ b/aleksis/core/util/core_helpers.py
@@ -1,3 +1,4 @@
+import json
 import os
 from datetime import datetime, timedelta
 from importlib import import_module, metadata
@@ -498,6 +499,7 @@ feedgenerator.FEED_FIELD_MAP = feedgenerator.FEED_FIELD_MAP + (("color", "color"
 feedgenerator.ITEM_ELEMENT_FIELD_MAP = feedgenerator.ITEM_ELEMENT_FIELD_MAP + (
     ("color", "color"),
     ("recurrence_id", "recurrence-id"),
+    ("meta", "x-meta"),
 )
 
 
@@ -507,7 +509,7 @@ class ExtendedICal20Feed(feedgenerator.ICal20Feed):
     Adds a method to return the actual calendar object.
     """
 
-    def get_calendar_object(self):
+    def get_calendar_object(self, with_meta=True):
         cal = Calendar()
         cal.add("version", "2.0")
         cal.add("calscale", "GREGORIAN")
@@ -517,28 +519,19 @@ class ExtendedICal20Feed(feedgenerator.ICal20Feed):
             if val is not None:
                 cal.add(efield, val)
 
-        self.write_items(cal)
+        self.write_items(cal, with_meta=with_meta)
 
         return cal
 
     def write(self, outfile, encoding):
-        cal = Calendar()
-        cal.add("version", "2.0")
-        cal.add("calscale", "GREGORIAN")
-
-        for ifield, efield in feedgenerator.ITEM_ELEMENT_FIELD_MAP:
-            val = self.feed.get(ifield)
-            if val is not None:
-                cal.add(efield, val)
-
-        self.write_items(cal)
+        cal = self.get_calendar_object(with_meta=False)
 
         to_ical = getattr(cal, "as_string", None)
         if not to_ical:
             to_ical = cal.to_ical
         outfile.write(to_ical())
 
-    def write_items(self, calendar):
+    def write_items(self, calendar, with_meta=True):
         for item in self.items:
             component_type = item.get("component_type")
             if component_type == "todo":
@@ -554,6 +547,9 @@ class ExtendedICal20Feed(feedgenerator.ICal20Feed):
                     elif ifield == "valarm":
                         for list_item in val:
                             element.add_component(list_item)
+                    elif ifield == "meta":
+                        if with_meta:
+                            element.add(efield, json.dumps(val))
                     else:
                         element.add(efield, val)
             calendar.add_component(element)
diff --git a/aleksis/core/vite.config.js b/aleksis/core/vite.config.js
index f1402e7702877f33967158820fda5ecf4f4141db..bc408ab344bd9d1d22da7b562a97c02a07fdf91e 100644
--- a/aleksis/core/vite.config.js
+++ b/aleksis/core/vite.config.js
@@ -122,7 +122,7 @@ function generateAppImporter(appDetails) {
     // Include calendar feed event bar components from all apps
     code += generateComponentsImportCode(
       appMeta.assetDir,
-      "/calendar_feeds/event_bas/",
+      "/calendar_feeds/event_bar/",
       appMeta.name,
       "calendarFeedEventBarComponents"
     );