diff --git a/packages/common/dbp-lit-element.js b/packages/common/dbp-lit-element.js
index 5b0af19e314548d0e903d3c81b050242e4492377..2112ab566c72fa4b7bcd80818022b1b22258e3b3 100644
--- a/packages/common/dbp-lit-element.js
+++ b/packages/common/dbp-lit-element.js
@@ -1,30 +1,58 @@
 import {AdapterLitElement} from "./src/adapter-lit-element";
 
 export default class DBPLitElement extends AdapterLitElement {
-    _(selector) {
-        return this.shadowRoot === null ? this.querySelector(selector) : this.shadowRoot.querySelector(selector);
+    constructor() {
+        super();
+        this.htmlOverrides = '';
+    }
+
+    /**
+     * See: https://lit-element.polymer-project.org/guide/properties#initialize
+     */
+    static get properties() {
+        return {
+            ...super.properties,
+            htmlOverrides: { type: String, attribute: 'html-overrides' },
+        };
+
     }
 
     connectedCallback() {
         this.updateComplete.then(() => {
-            // transform all named template slots in the light DOM to named div slots
-            this.transformTemplateSlots();
+            // transform all global override templates or named template slots in the light DOM to named div slots
+            this.transformSlots();
         });
 
         super.connectedCallback();
     }
 
+    _(selector) {
+        return this.shadowRoot === null ? this.querySelector(selector) : this.shadowRoot.querySelector(selector);
+    }
+
+    getTagName() {
+        const tagName = this.dataset ? (this.dataset.tagName || '') : '';
+
+        return tagName !== '' ? tagName : this.tagName.toLowerCase();
+    }
+
     /**
-     * Transforms all named template slots in the light DOM to named div slots
+     * Transforms all global override templates or named template slots in the light DOM to named div slots
      */
-    transformTemplateSlots() {
+    transformSlots() {
         // query all named slots of the component
         const slots = this.shadowRoot.querySelectorAll("slot[name]");
 
+        // if there are no slots we can exit
+        if (slots.length === 0) {
+            return;
+        }
+
         slots.forEach((slot) => {
-            const name = slot.name;
+            const slotName = slot.name;
+
             // search if there is a template with the name of the slot in the light DOM of the component
-            const templateElem = this.querySelector("template[slot=" + name + "]");
+            const templateElem = this.querySelector("template[slot=" + slotName + "]");
 
             if (!templateElem) {
                 return;
@@ -32,14 +60,51 @@ export default class DBPLitElement extends AdapterLitElement {
 
             // create a slot div container to put in the cloned template content
             const divElem = document.createElement('div');
-            divElem.slot = name;
+            divElem.slot = slotName;
             divElem.appendChild(templateElem.content.cloneNode(true));
 
-            // remove the old template with slot attribute
+            // remove the old template
             templateElem.remove();
 
             // put the slot div container with the cloned template in the light DOM
             this.appendChild(divElem);
         });
+
+        // check if we have an "html-override" attribute set so we need to check for the global override template
+        if (this.htmlOverrides !== '') {
+            const globalOverrideTemplateElem = document.querySelector('template#' + this.htmlOverrides);
+
+            if (globalOverrideTemplateElem) {
+                // we need to clone the element so we can access the content
+                const overrideTemplateElemClone = globalOverrideTemplateElem.content.cloneNode(true);
+                const tagName = this.getTagName();
+
+                // then we will look if there is an override for the current tag
+                const templateOverrideElem = overrideTemplateElemClone.querySelector('template#' + tagName);
+
+                if (templateOverrideElem) {
+                    // if there is an override we again need to clone that template so we can access the content
+                    const templateOverrideElemClone = templateOverrideElem.content.cloneNode(true);
+
+                    // now we need to look for slots in the override
+                    slots.forEach((slot) => {
+                        const slotName = slot.name;
+
+                        // if a slot is found we need to remove the current slot in the light DOM
+                        // so we are not showing the old and new content at the same time
+                        if (templateOverrideElemClone.querySelector('[slot="' + slotName + '"]')) {
+                            const currentSlotElement = this.querySelector('[slot="' + slotName + '"]');
+
+                            if (currentSlotElement) {
+                                currentSlotElement.remove();
+                            }
+                        }
+                    });
+
+                    // append the cloned template to the light DOM
+                    this.appendChild(templateOverrideElemClone);
+                }
+            }
+        }
     }
 }
diff --git a/packages/file-handling/src/dbp-nextcloud-file-picker.js b/packages/file-handling/src/dbp-nextcloud-file-picker.js
index d352f07f8e7ebbe1b220dfb0f504bb22f9bdf541..23506dd408573ccfb2b70f24c2fc86dbc7b906f5 100644
--- a/packages/file-handling/src/dbp-nextcloud-file-picker.js
+++ b/packages/file-handling/src/dbp-nextcloud-file-picker.js
@@ -1508,7 +1508,8 @@ export class NextcloudFilePicker extends ScopedElementsMixin(DBPLitElement) {
                     </div>
                     <div class="block text-center m-inherit ${classMap({hidden: this.isPickerActive})}">
                         <p class="m-inherit"><br>
-                            ${i18n.t('nextcloud-file-picker.auth-info')}<br>${this.authInfo}  
+                            ${i18n.t('nextcloud-file-picker.auth-info')}
+                            <slot name="auth-info"><br />${this.authInfo}</slot>
                         </p>
                     </div>
                 </div>
diff --git a/packages/file-handling/src/file-sink.js b/packages/file-handling/src/file-sink.js
index adae346b932e3105128146e7ee739639f6602012..e9a48d19748ccb3887390e5be70d7a4aeea9652a 100644
--- a/packages/file-handling/src/file-sink.js
+++ b/packages/file-handling/src/file-sink.js
@@ -268,6 +268,7 @@ export class FileSink extends ScopedElementsMixin(DBPLitElement) {
                    select-button-text="${i18n.t('file-sink.select-directory')}"
                    ?disabled="${this.disabled}"
                    lang="${this.lang}"
+                   subscribe="html-overrides"
                    auth-url="${this.nextcloudAuthUrl}"
                    web-dav-url="${this.nextcloudWebDavUrl}"
                    nextcloud-name="${this.nextcloudName}"
diff --git a/packages/file-handling/src/file-source.js b/packages/file-handling/src/file-source.js
index 9c7bf2d80cafb2829a36ce1200d3208f90ac046d..e1e2376b5c8c61a74d9ba85cbb134a040356806d 100644
--- a/packages/file-handling/src/file-source.js
+++ b/packages/file-handling/src/file-source.js
@@ -464,6 +464,7 @@ export class FileSource extends ScopedElementsMixin(DBPLitElement) {
                    class="${classMap({hidden: this.nextcloudWebDavUrl === "" || this.nextcloudAuthUrl === ""})}"
                    ?disabled="${this.disabled}"
                    lang="${this.lang}"
+                   subscribe="html-overrides"
                    auth-url="${this.nextcloudAuthUrl}"
                    web-dav-url="${this.nextcloudWebDavUrl}"
                    nextcloud-name="${this.nextcloudName}"