diff --git a/app/controllers/contents/courseware.php b/app/controllers/contents/courseware.php
index c1ca32137bd1de4ed6293f4faa28a5c9b836fa2d..c7edcaced56a533916d8e4ae7c8bb0934ee79934 100644
--- a/app/controllers/contents/courseware.php
+++ b/app/controllers/contents/courseware.php
@@ -117,11 +117,7 @@ class Contents_CoursewareController extends AuthenticatedController
     private function setCoursewareSidebar()
     {
         $sidebar = \Sidebar::Get();
-        $actions = new TemplateWidget(
-            _('Aktionen'),
-            $this->get_template_factory()->open('course/courseware/action_widget')
-        );
-        $sidebar->addWidget($actions)->addLayoutCSSClass('courseware-action-widget');
+        $sidebar->addWidget(new VueWidget('courseware-action-widget'));
 
         $views = new TemplateWidget(
             _('Suche'),
@@ -129,17 +125,8 @@ class Contents_CoursewareController extends AuthenticatedController
         );
         $sidebar->addWidget($views)->addLayoutCSSClass('courseware-search-widget');
 
-        $views = new \TemplateWidget(
-            _('Ansichten'),
-            $this->get_template_factory()->open('course/courseware/view_widget')
-        );
-        $sidebar->addWidget($views)->addLayoutCSSClass('courseware-view-widget');
-
-        $exports = new TemplateWidget(
-            _('Export '),
-            $this->get_template_factory()->open('course/courseware/export_widget')
-        );
-        $sidebar->addWidget($exports)->addLayoutCSSClass('courseware-export-widget');
+        $sidebar->addWidget(new VueWidget('courseware-view-widget'));
+        $sidebar->addWidget(new VueWidget('courseware-export-widget'));
     }
 
     private function getLicences()
diff --git a/app/controllers/course/courseware.php b/app/controllers/course/courseware.php
index 7c41756a92f2c56aac003a71eca35c7f8a19766e..9174192226a8f87d555c16db2aef759f4dca903c 100644
--- a/app/controllers/course/courseware.php
+++ b/app/controllers/course/courseware.php
@@ -110,11 +110,7 @@ class Course_CoursewareController extends AuthenticatedController
     private function setIndexSidebar(): void
     {
         $sidebar = Sidebar::Get();
-        $actions = new TemplateWidget(
-            _('Aktionen'),
-            $this->get_template_factory()->open('course/courseware/action_widget')
-        );
-        $sidebar->addWidget($actions)->addLayoutCSSClass('courseware-action-widget');
+        $sidebar->addWidget(new VueWidget('courseware-action-widget'));
 
         $views = new TemplateWidget(
             _('Suche'),
@@ -122,20 +118,10 @@ class Course_CoursewareController extends AuthenticatedController
         );
         $sidebar->addWidget($views)->addLayoutCSSClass('courseware-search-widget');
 
-        $views = new TemplateWidget(
-            _('Ansichten'),
-            $this->get_template_factory()->open('course/courseware/view_widget')
-        );
-        $sidebar->addWidget($views)->addLayoutCSSClass('courseware-view-widget');
-
-        $exports = new TemplateWidget(
-            _('Export '),
-            $this->get_template_factory()->open('course/courseware/export_widget')
-        );
-        $sidebar->addWidget($exports)->addLayoutCSSClass('courseware-export-widget');
+        $sidebar->addWidget(new VueWidget('courseware-view-widget'));
+        $sidebar->addWidget(new VueWidget('courseware-export-widget'));
     }
 
-
     private function setDashboardSidebar(): void
     {
         $sidebar = Sidebar::Get();
diff --git a/app/views/course/courseware/action_widget.php b/app/views/course/courseware/action_widget.php
deleted file mode 100644
index b13792e2cc059f27d0d6d3ca64219c73c6025d4c..0000000000000000000000000000000000000000
--- a/app/views/course/courseware/action_widget.php
+++ /dev/null
@@ -1 +0,0 @@
-<aside id="courseware-action-widget" class="widget-sidebar"></aside>
diff --git a/app/views/course/courseware/export_widget.php b/app/views/course/courseware/export_widget.php
deleted file mode 100644
index 1d7feb2c6e467b5e10160fe829589f0f4c80dd15..0000000000000000000000000000000000000000
--- a/app/views/course/courseware/export_widget.php
+++ /dev/null
@@ -1 +0,0 @@
-<aside id="courseware-export-widget" class="widget-sidebar"></aside>
diff --git a/app/views/course/courseware/view_widget.php b/app/views/course/courseware/view_widget.php
deleted file mode 100644
index 826913411ac922bd5a2f02844bff7946e2e985b5..0000000000000000000000000000000000000000
--- a/app/views/course/courseware/view_widget.php
+++ /dev/null
@@ -1 +0,0 @@
-<aside id="courseware-view-widget" class="widget-sidebar"></aside>
diff --git a/lib/classes/sidebar/VueWidget.php b/lib/classes/sidebar/VueWidget.php
new file mode 100644
index 0000000000000000000000000000000000000000..f4f0583acc2466d98374ab47e65ecdfe934ebf1f
--- /dev/null
+++ b/lib/classes/sidebar/VueWidget.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * This widget type delegates all rendering of the widget to vuejs.
+ *
+ * @author  Elmar Ludwig
+ * @license GPL2 or any later version
+ * @since   Stud.IP 5.0
+ */
+class VueWidget extends Widget
+{
+    /**
+     * Constructs the widget with the given id on the element.
+     */
+    public function __construct($id)
+    {
+        $this->id = $id;
+        $this->layout = 'widgets/vue-widget';
+        $this->forced_rendering = true;
+    }
+}
diff --git a/resources/vue/base-components.js b/resources/vue/base-components.js
index 526687b39763215284e518e8ae748ffc806ca419..97231d2827d47162ce34672b2cec476f0e55646c 100644
--- a/resources/vue/base-components.js
+++ b/resources/vue/base-components.js
@@ -1,6 +1,7 @@
 import Multiselect from './components/Multiselect.vue';
 import EditableList from "./components/EditableList.vue";
 import Quicksearch from './components/Quicksearch.vue';
+import SidebarWidget from './components/SidebarWidget.vue';
 import StudipActionMenu from './components/StudipActionMenu.vue';
 import StudipAssetImg from './components/StudipAssetImg.vue';
 import StudipDateTime from './components/StudipDateTime.vue';
@@ -23,6 +24,7 @@ const BaseComponents = {
     EditableList,
     Quicksearch,
     RangeInput,
+    SidebarWidget,
     StudipActionMenu,
     StudipAssetImg,
     StudipDateTime,
diff --git a/resources/vue/components/SidebarWidget.vue b/resources/vue/components/SidebarWidget.vue
new file mode 100644
index 0000000000000000000000000000000000000000..34d935d84faadd3648ae4788e86e6f46f8fd6cc9
--- /dev/null
+++ b/resources/vue/components/SidebarWidget.vue
@@ -0,0 +1,19 @@
+<template>
+    <div class="sidebar-widget">
+        <div class="sidebar-widget-header" v-if="title">
+            {{ title }}
+        </div>
+        <div class="sidebar-widget-content">
+            <slot name="content" />
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    name: 'sidebar-widget',
+    props: {
+        title: String,
+    },
+}
+</script>
diff --git a/resources/vue/components/courseware/CoursewareActionWidget.vue b/resources/vue/components/courseware/CoursewareActionWidget.vue
index 572a94e6bc758042d047ecee96e521b81e4ff46a..cc1738d55a129aa8dd88ba9bcd67161c1b8c07b7 100644
--- a/resources/vue/components/courseware/CoursewareActionWidget.vue
+++ b/resources/vue/components/courseware/CoursewareActionWidget.vue
@@ -1,60 +1,65 @@
 <template>
-    <ul class="widget-list widget-links cw-action-widget" v-if="structuralElement">
-        <li class="cw-action-widget-show-toc">
-            <button @click="toggleTOC">
-                {{ tocText }}
-            </button>
-        </li>
-        <li class="cw-action-widget-show-consume-mode">
-            <button @click="showConsumeMode">
-                <translate>Vollbild einschalten</translate>
-            </button>
-        </li>
-        <li v-if="canEdit" class="cw-action-widget-edit">
-            <button @click="editElement">
-                <translate>Seite bearbeiten</translate>
-            </button>
-        </li>
-        <li v-if="canEdit" class="cw-action-widget-sort">
-            <button @click="sortContainers">
-                <translate>Abschnitte sortieren</translate>
-            </button>
-        </li>
-        <li v-if="canEdit" class="cw-action-widget-add">
-            <button @click="addElement">
-                <translate>Seite hinzufügen</translate>
-            </button>
-        </li>
-        <li class="cw-action-widget-info">
-            <button @click="showElementInfo">
-                <translate>Informationen anzeigen</translate>
-            </button>
-        </li>
-        <li class="cw-action-widget-star">
-            <button @click="createBookmark">
-                <translate>Lesezeichen setzen</translate>
-            </button>
-        </li>
-        <li v-if="context.type === 'users'" class="cw-action-widget-link">
-            <button @click="linkElement">
-                <translate>Öffentlichen Link erzeugen</translate>
-            </button>
-        </li>
-        <li v-if="!isOwner" class="cw-action-widget-oer">
-            <button @click="suggestOER">
-                <translate>Material für %{oerTitle} vorschlagen</translate>
-            </button>
-        </li>
-        <li v-if="!isRoot && canEdit" class="cw-action-widget-trash">
-            <button @click="deleteElement">
-                <translate>Seite löschen</translate>
-            </button>
-        </li>
-    </ul>
+    <sidebar-widget :title="$gettext('Aktionen')" v-if="structuralElement">
+        <template #content>
+            <ul class="widget-list widget-links cw-action-widget">
+                <li class="cw-action-widget-show-toc">
+                    <button @click="toggleTOC">
+                        {{ tocText }}
+                    </button>
+                </li>
+                <li class="cw-action-widget-show-consume-mode">
+                    <button @click="showConsumeMode">
+                        <translate>Vollbild einschalten</translate>
+                    </button>
+                </li>
+                <li v-if="canEdit" class="cw-action-widget-edit">
+                    <button @click="editElement">
+                        <translate>Seite bearbeiten</translate>
+                    </button>
+                </li>
+                <li v-if="canEdit" class="cw-action-widget-sort">
+                    <button @click="sortContainers">
+                        <translate>Abschnitte sortieren</translate>
+                    </button>
+                </li>
+                <li v-if="canEdit" class="cw-action-widget-add">
+                    <button @click="addElement">
+                        <translate>Seite hinzufügen</translate>
+                    </button>
+                </li>
+                <li class="cw-action-widget-info">
+                    <button @click="showElementInfo">
+                        <translate>Informationen anzeigen</translate>
+                    </button>
+                </li>
+                <li class="cw-action-widget-star">
+                    <button @click="createBookmark">
+                        <translate>Lesezeichen setzen</translate>
+                    </button>
+                </li>
+                <li v-if="context.type === 'users'" class="cw-action-widget-link">
+                    <button @click="linkElement">
+                        <translate>Öffentlichen Link erzeugen</translate>
+                    </button>
+                </li>
+                <li v-if="!isOwner" class="cw-action-widget-oer">
+                    <button @click="suggestOER">
+                        <translate>Material für %{oerTitle} vorschlagen</translate>
+                    </button>
+                </li>
+                <li v-if="!isRoot && canEdit" class="cw-action-widget-trash">
+                    <button @click="deleteElement">
+                        <translate>Seite löschen</translate>
+                    </button>
+                </li>
+            </ul>
+        </template>
+    </sidebar-widget>
 </template>
 
 <script>
 import StudipIcon from './../StudipIcon.vue';
+import SidebarWidget from '../SidebarWidget.vue';
 import CoursewareExport from '@/vue/mixins/courseware/export.js';
 import { mapActions, mapGetters } from 'vuex';
 
@@ -63,6 +68,7 @@ export default {
     props: ['structuralElement', 'canVisit'],
     components: {
         StudipIcon,
+        SidebarWidget,
     },
     mixins: [CoursewareExport],
     computed: {
diff --git a/resources/vue/components/courseware/CoursewareExportWidget.vue b/resources/vue/components/courseware/CoursewareExportWidget.vue
index 7b55a7898cb9a2cfb4ebf1dbaff89a6610f191bc..2c821b735cdf66da5b26295b6d17f42bdb9cdd50 100644
--- a/resources/vue/components/courseware/CoursewareExportWidget.vue
+++ b/resources/vue/components/courseware/CoursewareExportWidget.vue
@@ -1,33 +1,41 @@
 <template>
-    <ul class="widget-list widget-links cw-export-widget" v-if="structuralElement">
-        <li v-if="showExportArchiv" class="cw-export-widget-export">
-            <button @click="exportElement">
-                <translate>Seite exportieren</translate>
-            </button>
-        </li>
-        <li v-if="showExportPdf" class="cw-export-widget-export-pdf">
-            <button @click="pdfElement">
-                <translate>Seite als pdf-Dokument exportieren</translate>
-            </button>
-        </li>
-        <li v-if="showOer" class="cw-export-widget-oer">
-            <button @click="oerElement">
-                <translate>Seite auf %{oerTitle} veröffentlichen</translate>
-            </button>
-        </li>
-        <li v-if="!showExportArchiv && !showExportPdf && !showOer">
-            <translate>Keine Exportoptionen verfügbar</translate>
-        </li>
-    </ul>
+    <sidebar-widget :title="$gettext('Export')" v-if="structuralElement">
+        <template #content>
+            <ul class="widget-list widget-links cw-export-widget" v-if="structuralElement">
+                <li v-if="showExportArchiv" class="cw-export-widget-export">
+                    <button @click="exportElement">
+                        <translate>Seite exportieren</translate>
+                    </button>
+                </li>
+                <li v-if="showExportPdf" class="cw-export-widget-export-pdf">
+                    <button @click="pdfElement">
+                        <translate>Seite als pdf-Dokument exportieren</translate>
+                    </button>
+                </li>
+                <li v-if="showOer" class="cw-export-widget-oer">
+                    <button @click="oerElement">
+                        <translate>Seite auf %{oerTitle} veröffentlichen</translate>
+                    </button>
+                </li>
+                <li v-if="!showExportArchiv && !showExportPdf && !showOer">
+                    <translate>Keine Exportoptionen verfügbar</translate>
+                </li>
+            </ul>
+        </template>
+    </sidebar-widget>
 </template>
 
 <script>
+import SidebarWidget from '../SidebarWidget.vue';
 import CoursewareExport from '@/vue/mixins/courseware/export.js';
 import { mapActions, mapGetters } from 'vuex';
 
 export default {
     name: 'courseware-export-widget',
     props: ['structuralElement', 'canVisit'],
+    components: {
+        SidebarWidget
+    },
     mixins: [CoursewareExport],
     computed: {
         ...mapGetters({
diff --git a/resources/vue/components/courseware/CoursewareRibbon.vue b/resources/vue/components/courseware/CoursewareRibbon.vue
index 72a3a50983664a4ab5226531896a13fdfce5bff1..f6797fcd9a34500df6af4437b2b50a843015d43c 100644
--- a/resources/vue/components/courseware/CoursewareRibbon.vue
+++ b/resources/vue/components/courseware/CoursewareRibbon.vue
@@ -15,12 +15,14 @@
             </div>
             <div class="cw-ribbon-wrapper-right">
                 <button
+                    v-if="showToolbarButton"
                     class="cw-ribbon-button cw-ribbon-button-menu"
                     :title="textRibbon.toolbar"
                     @click.prevent="activeToolbar"
                 >
                 </button>
                 <button
+                    v-if="showModeSwitchButton"
                     ref="consumeModeSwitch"
                     class="cw-ribbon-button"
                     :class="[consumeMode ? 'cw-ribbon-button-zoom-out' : 'cw-ribbon-button-zoom']"
diff --git a/resources/vue/components/courseware/CoursewareViewWidget.vue b/resources/vue/components/courseware/CoursewareViewWidget.vue
index 86c157a1364e627d8b838aad766a4e134c2bc139..fb3de7441a2c90ad5387472c7228c5bf37089422 100644
--- a/resources/vue/components/courseware/CoursewareViewWidget.vue
+++ b/resources/vue/components/courseware/CoursewareViewWidget.vue
@@ -1,35 +1,43 @@
 <template>
-    <ul class="widget-list widget-links sidebar-views cw-view-widget">
-        <li :class="{ active: readView }">
-            <button @click="setReadView">
-                <translate>Lesen</translate>
-            </button>
-        </li>
-        <li
-            v-if="canEdit"
-            :class="{ active: editView }"
-        >
-            <button @click="setEditView">
-                <translate>Bearbeiten</translate>
-            </button>
-        </li>
-        <li 
-            v-if="context.type === 'courses' && canVisit"
-            :class="{ active: discussView }"
-        >
-            <button @click="setDiscussView">
-                <translate>Kommentieren</translate>
-            </button>
-        </li>
-    </ul>
+    <sidebar-widget :title="$gettext('Ansichten')" v-if="structuralElement">
+        <template #content>
+            <ul class="widget-list widget-links sidebar-views cw-view-widget">
+                <li :class="{ active: readView }">
+                    <button @click="setReadView">
+                        <translate>Lesen</translate>
+                    </button>
+                </li>
+                <li
+                    v-if="canEdit"
+                    :class="{ active: editView }"
+                >
+                    <button @click="setEditView">
+                        <translate>Bearbeiten</translate>
+                    </button>
+                </li>
+                <li
+                    v-if="context.type === 'courses' && canVisit"
+                    :class="{ active: discussView }"
+                >
+                    <button @click="setDiscussView">
+                        <translate>Kommentieren</translate>
+                    </button>
+                </li>
+            </ul>
+        </template>
+    </sidebar-widget>
 </template>
 
 <script>
+import SidebarWidget from '../SidebarWidget.vue';
 import { mapActions, mapGetters } from 'vuex';
 
 export default {
     name: 'courseware-view-widget',
     props: ['structuralElement', 'canVisit'],
+    components: {
+        SidebarWidget
+    },
     computed: {
         ...mapGetters({
             viewMode: 'viewMode',
diff --git a/resources/vue/components/courseware/IndexApp.vue b/resources/vue/components/courseware/IndexApp.vue
index 5d9f1d202c1045fd5c15d21716c3f2e81c60d5eb..7c9c15304b14fce1e429664e86638471b356c736 100644
--- a/resources/vue/components/courseware/IndexApp.vue
+++ b/resources/vue/components/courseware/IndexApp.vue
@@ -10,16 +10,16 @@
                 @select="selectStructuralElement"
             ></courseware-structural-element>
             <MountingPortal mountTo="#courseware-action-widget" name="sidebar-actions">
-                <courseware-action-widget :structural-element="selected" :canVisit="canVisit"></courseware-action-widget>
+                <courseware-action-widget :structural-element="selected" :canVisit="canVisit" v-if="!showSearchResults"></courseware-action-widget>
             </MountingPortal>
             <MountingPortal mountTo="#courseware-search-widget" name="sidebar-search">
                 <courseware-search-widget></courseware-search-widget>
             </MountingPortal>
             <MountingPortal mountTo="#courseware-view-widget" name="sidebar-views">
-                <courseware-view-widget :structural-element="selected" :canVisit="canVisit"></courseware-view-widget>
+                <courseware-view-widget :structural-element="selected" :canVisit="canVisit" v-if="!showSearchResults"></courseware-view-widget>
             </MountingPortal>
             <MountingPortal mountTo="#courseware-export-widget" name="sidebar-export">
-                <courseware-export-widget :structural-element="selected" :canVisit="canVisit"></courseware-export-widget>
+                <courseware-export-widget :structural-element="selected" :canVisit="canVisit" v-if="!showSearchResults"></courseware-export-widget>
             </MountingPortal>
         </div>
         <studip-progress-indicator
diff --git a/templates/widgets/vue-widget.php b/templates/widgets/vue-widget.php
new file mode 100644
index 0000000000000000000000000000000000000000..6c376613e8b0c846ed8309571b1f525794958153
--- /dev/null
+++ b/templates/widgets/vue-widget.php
@@ -0,0 +1 @@
+<div id="<?= htmlReady($id) ?>"></div>