diff --git a/resources/assets/stylesheets/scss/courseware.scss b/resources/assets/stylesheets/scss/courseware.scss
index ad7337257637e795b101c867d5674f2a13448711..09a3a7e5e2b57dee144b82f464354adce598c8fe 100644
--- a/resources/assets/stylesheets/scss/courseware.scss
+++ b/resources/assets/stylesheets/scss/courseware.scss
@@ -27,7 +27,7 @@ $element-icons: (
 $tree-item-flag-icons: (
     date: date,
     write: edit,
-    cant-read: lock-locked2
+    cant-read: lock-locked2,
 );
 
 $tile-colors: (
@@ -383,6 +383,10 @@ $consum_ribbon_width: calc(100% - 58px);
                         }
                     }
 
+                    img {
+                        vertical-align: text-top;
+                    }
+
                     &.cw-ribbon-breadcrumb-item-current {
                         flex-shrink: 1;
                     }
@@ -1388,7 +1392,7 @@ label[for="cw-keypoint-color"] {
                                         display: inline-block;
                                         border-bottom: none;
                                         font-size: 14px;
-                                        width: calc(100% - 14px);
+                                        width: calc(100% - 20px);
                                         background-repeat: no-repeat;
                                         padding-left: 18px;
                                         margin-left: 4px;
@@ -1456,6 +1460,22 @@ label[for="cw-keypoint-color"] {
             }
         }
     }
+    .cw-tree-item-sequential {
+        display: inline-block;
+        position: absolute;
+        right: 8px;
+
+        &.cw-tree-item-sequential-complete {
+            width: 16px;
+            height: 16px;
+            vertical-align: top;
+            @include background-icon(accept, info, 16);
+        }
+        &.cw-tree-item-sequential-percentage {
+            color: $black;
+            font-size: 14px;
+        }
+    }
 
     .cw-tree-item-ghost {
         opacity: 0.6;
diff --git a/resources/vue/components/courseware/CoursewareProgressCircle.vue b/resources/vue/components/courseware/CoursewareProgressCircle.vue
index 729d707705755ed983b5f47206fc4cdb548e5141..e14559026834136506a4bf77cdc8727bdee2a855 100644
--- a/resources/vue/components/courseware/CoursewareProgressCircle.vue
+++ b/resources/vue/components/courseware/CoursewareProgressCircle.vue
@@ -1,6 +1,6 @@
 <template>
     <div class="cw-progress-circle" :class="['p' + value, value > 50 ? 'over50' : '']">
-        <span>{{ value }}%</span>
+        <span>{{ value }} %</span>
         <div class="left-half-clipper">
             <div class="first50-bar"></div>
             <div class="value-bar"></div>
diff --git a/resources/vue/components/courseware/CoursewareStructuralElement.vue b/resources/vue/components/courseware/CoursewareStructuralElement.vue
index ccc4cb11a9b5992d8507010af28485666b9e149e..e472ee0aa057b51a52356f5d60c467379f143cef 100644
--- a/resources/vue/components/courseware/CoursewareStructuralElement.vue
+++ b/resources/vue/components/courseware/CoursewareStructuralElement.vue
@@ -35,6 +35,23 @@
                             >
                                 <span>{{ structuralElement.attributes.title || "–" }}</span>
                                 <span v-if="isTask">[ {{ solverName }} ]</span>
+                                <template v-if="!userIsTeacher && inCourse">
+                                    <studip-icon
+                                        v-if="complete"
+                                        shape="accept"
+                                        role="info"   
+                                        :title="$gettext('Diese Seite wurde von Ihnen vollständig bearbeitet')"
+                                    />
+                                    <span
+                                        v-else
+                                        :title="$gettextInterpolate(
+                                                    $gettext('Fortschritt: %{progress} %'),
+                                                    {progress: elementProgress}
+                                                )"
+                                    >
+                                        ({{ elementProgress }} %)
+                                    </span>
+                                </template>
                             </li>
                         </template>
                         <template #breadcrumbFallback>
@@ -831,6 +848,7 @@ export default {
             isLink: 'currentElementisLink',
 
             templates: 'courseware-templates/all',
+            progressData: 'progresses',
         }),
 
         currentId() {
@@ -1218,6 +1236,19 @@ export default {
                 return template.attributes.purpose === this.newChapterPurpose
             });
         },
+        complete() {
+            return this.elementProgress === 100;
+        },
+        elementProgress() {
+            if (this.structuralElementLoaded) {
+                return this.progressData?.[this.structuralElement.id].progress.self;
+            }
+            
+            return 0;
+        },
+        progressTitle() {
+            return '';
+        }
     },
 
     methods: {
@@ -1250,6 +1281,7 @@ export default {
             loadStructuralElement: 'loadStructuralElement',
             createLink: 'createLink',
             setCurrentElementId: 'coursewareCurrentElement',
+            loadProgresses: 'loadProgresses'
         }),
 
         initCurrent() {
@@ -1735,6 +1767,10 @@ export default {
             if (this.isLink) {
                 this.loadStructuralElement(this.structuralElement.attributes['target-id']);
             }
+
+            if (this.inCourse && this.courseware.attributes['sequential-progression'] && !this.userIsTeacher) {
+               this.loadProgresses();
+            }
         },
         containers() {
             this.containerList = this.containers;
diff --git a/resources/vue/components/courseware/CoursewareTreeItem.vue b/resources/vue/components/courseware/CoursewareTreeItem.vue
index 0a5ead52b4f238dd9f57562a7ec25d42de738bf3..d2d69af90b0acff2bbbe7e00ca8742915d93ee97 100644
--- a/resources/vue/components/courseware/CoursewareTreeItem.vue
+++ b/resources/vue/components/courseware/CoursewareTreeItem.vue
@@ -39,6 +39,24 @@
                     class="cw-tree-item-flag-cant-read"
                     :title="$gettext('Diese Seite kann von Teilnehmenden nicht gesehen werden')"
                 ></span>
+                <template v-if="!userIsTeacher && inCourse">
+                    <span
+                        v-if="complete"
+                        class="cw-tree-item-sequential cw-tree-item-sequential-complete"
+                        :title="$gettext('Diese Seite wurde von Ihnen vollständig bearbeitet')"
+                    >
+                    </span>
+                    <span
+                        v-else
+                        class="cw-tree-item-sequential cw-tree-item-sequential-percentage"
+                        :title="$gettextInterpolate(
+                                    $gettext('Fortschritt: %{progress}%'),
+                                    {progress: itemProgress}
+                                )"
+                    >
+                        {{ itemProgress }} %
+                    </span>
+            </template>
             </router-link>
         </div>
         <ol
@@ -141,6 +159,9 @@ export default {
             userById: 'users/byId',
             groupById: 'status-groups/byId',
             viewMode: 'viewMode',
+            courseware: 'courseware',
+            progressData: 'progresses',
+            userIsTeacher: 'userIsTeacher',
         }),
         draggableData() {
             return {
@@ -269,7 +290,19 @@ export default {
         },
         canEdit() {
             return this.element.attributes['can-edit'];
-        }
+        },
+        inCourse() {
+            return this.context.type === 'courses';
+        },
+        progress() {
+            return this.progressData?.[this.element.id];
+        },
+        itemProgress() {
+            return this.progress?.progress?.self ?? 0;
+        },
+        complete() {
+            return this.itemProgress === 100;
+        },
     },
     methods: {
         ...mapActions({
diff --git a/resources/vue/courseware-index-app.js b/resources/vue/courseware-index-app.js
index 337b56f83b11e8738e67a3f610affdb288e7c799..5b66ef7d1954897069fc8623193dc436b5dcf65a 100644
--- a/resources/vue/courseware-index-app.js
+++ b/resources/vue/courseware-index-app.js
@@ -136,6 +136,7 @@ const mountApp = async (STUDIP, createApp, element) => {
 
     if (entry_type === 'courses') {
         await store.dispatch('loadTeacherStatus', STUDIP.USER_ID);
+        store.dispatch('loadProgresses');
     }
 
     store.dispatch('coursewareCurrentElement', elem_id);
diff --git a/resources/vue/store/courseware/courseware.module.js b/resources/vue/store/courseware/courseware.module.js
index 5c408b9c3f01dd08a9dd7124473dec72f807e2db..fc688f015ea882ccd75e69497e41adb848ef89a8 100644
--- a/resources/vue/store/courseware/courseware.module.js
+++ b/resources/vue/store/courseware/courseware.module.js
@@ -60,7 +60,8 @@ const getDefaultState = () => {
         showSearchResults: false,
         searchResults: [],
 
-        assistiveLiveContents: ''
+        assistiveLiveContents: '',
+        progresses: null
     };
 };
 
@@ -254,6 +255,9 @@ const getters = {
     },
     assistiveLiveContents(state) {
         return state.assistiveLiveContents;
+    },
+    progresses(state) {
+        return state.progresses;
     }
 };
 
@@ -1339,6 +1343,18 @@ export const actions = {
             options,
         });
     },
+    async loadUnitProgresses({ getters }, { unitId }) {
+        const response = await state.httpClient.get(`courseware-units/${unitId}/courseware-user-progresses`);
+        if (response.status === 200) {
+           return response.data;
+        } else {
+           return null;
+        }
+    },
+    async loadProgresses({ dispatch, commit, getters }) {
+        const progresses = await dispatch('loadUnitProgresses', { unitId: getters.context.unit });
+        commit('setProgresses', progresses);
+    }
 };
 
 /* eslint no-param-reassign: ["error", { "props": false }] */
@@ -1526,6 +1542,9 @@ export const mutations = {
     },
     setAssistiveLiveContents(state, text) {
         state.assistiveLiveContents = text;
+    },
+    setProgresses(state, data) {
+        state.progresses = data;
     }
 };