diff --git a/packages/file-handling/src/fileupload.js b/packages/file-handling/src/fileupload.js
deleted file mode 100644
index 78a05770e1ed1fb0759895ec39c04b676de85628..0000000000000000000000000000000000000000
--- a/packages/file-handling/src/fileupload.js
+++ /dev/null
@@ -1,489 +0,0 @@
-import {i18n} from './i18n';
-import {css, html} from 'lit-element';
-import {ScopedElementsMixin} from '@open-wc/scoped-elements';
-// import JSONLD from 'vpu-common/jsonld';
-import VPULitElement from 'vpu-common/vpu-lit-element';
-import * as commonUtils from "vpu-common/utils";
-import {Icon, MiniSpinner} from 'vpu-common';
-import * as commonStyles from 'vpu-common/styles';
-import {NextcloudFilePicker} from "./vpu-nextcloud-file-picker";
-import {classMap} from 'lit-html/directives/class-map.js';
-
-
-function mimeTypesToAccept(mimeTypes) {
-    // Some operating systems can't handle mime types and
-    // need file extensions, this tries to add them for some..
-    let mapping = {
-        'application/pdf': ['.pdf'],
-        'application/zip': ['.zip'],
-    };
-    let accept = [];
-    mimeTypes.split(',').forEach((mime) => {
-        accept.push(mime);
-        if (mime.trim() in mapping) {
-            accept = accept.concat(mapping[mime.trim()]);
-        }
-    });
-    return accept.join(',');
-}
-
-
-/**
- * KnowledgeBaseWebPageElementView web component
- */
-export class FileUpload extends ScopedElementsMixin(VPULitElement) {
-    constructor() {
-        super();
-        this.lang = 'de';
-        this.url = '';
-        this.nextcloudAuthUrl = '';
-        this.nextcloudWebDavUrl = '';
-        this.dropArea = null;
-        this.allowedMimeTypes = '*/*';
-        this.text = '';
-        this.buttonLabel = '';
-        this.uploadInProgress = false;
-        this.multipleUploadInProgress = false;
-        this.alwaysSendFile = false;
-        this.isDeferred = false;
-        this.queuedFiles = [];
-        this.queuedFilesCount = 0;
-        this.disabled = false;
-        this.decompressZip = false;
-        this._queueKey = 0;
-    }
-
-    static get scopedElements() {
-        return {
-            'vpu-icon': Icon,
-            'vpu-mini-spinner': MiniSpinner,
-            'vpu-nextcloud-file-picker': NextcloudFilePicker,
-        };
-    }
-
-    /**
-     * See: https://lit-element.polymer-project.org/guide/properties#initialize
-     */
-    static get properties() {
-        return {
-            lang: { type: String },
-            url: { type: String },
-            allowedMimeTypes: { type: String, attribute: 'allowed-mime-types' },
-            nextcloudAuthUrl: { type: String, attribute: 'nextcloud-auth-url' },
-            nextcloudWebDavUrl: { type: String, attribute: 'nextcloud-web-dav-url' },
-            text: { type: String },
-            buttonLabel: { type: String, attribute: 'button-label' },
-            uploadInProgress: { type: Boolean, attribute: false },
-            multipleUploadInProgress: { type: Boolean, attribute: false },
-            alwaysSendFile: { type: Boolean, attribute: 'always-send-file' },
-            isDeferred: { type: Boolean, attribute: 'deferred' },
-            queuedFilesCount: { type: Number, attribute: false },
-            disabled: { type: Boolean },
-            decompressZip: { type: Boolean, attribute: 'decompress-zip' },
-        };
-    }
-
-
-    update(changedProperties) {
-        changedProperties.forEach((oldValue, propName) => {
-            switch (propName) {
-                case "lang":
-                    i18n.changeLanguage(this.lang);
-                    break;
-                case "queuedFilesCount":
-                    const data = { "queuedFilesCount": this.queuedFilesCount, "queuedFiles": this.queuedFiles };
-                    const event = new CustomEvent("vpu-fileupload-queued-files-changed",
-                        { "detail": data, bubbles: true, composed: true });
-                    this.dispatchEvent(event);
-                    break;
-            }
-        });
-
-        super.update(changedProperties);
-    }
-
-    connectedCallback() {
-        super.connectedCallback();
-
-        this.updateComplete.then(() => {
-            this.dropArea = this._('#dropArea');
-            ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
-                this.dropArea.addEventListener(eventName, this.preventDefaults, false)
-            });
-            ['dragenter', 'dragover'].forEach(eventName => {
-                this.dropArea.addEventListener(eventName, this.highlight.bind(this), false)
-            });
-            ['dragleave', 'drop'].forEach(eventName => {
-                this.dropArea.addEventListener(eventName, this.unhighlight.bind(this), false)
-            });
-            this.dropArea.addEventListener('drop', this.handleDrop.bind(this), false);
-            this._('#fileElem').addEventListener('change', this.handleChange.bind(this));
-        });
-    }
-
-    preventDefaults (e) {
-        e.preventDefault();
-        e.stopPropagation();
-    }
-
-    highlight(e) {
-        if (this.uploadInProgress) {
-            return;
-        }
-
-        this.dropArea.classList.add('highlight')
-    }
-
-    unhighlight(e) {
-        this.dropArea.classList.remove('highlight')
-    }
-
-    handleDrop(e) {
-        if (this.uploadInProgress || this.disabled) {
-            return;
-        }
-
-        let dt = e.dataTransfer;
-        console.dir(dt);
-        let files = dt.files;
-
-        this.handleFiles(files);
-    }
-
-    async handleChange(e) {
-        let fileElem = this._('#fileElem');
-
-        if (fileElem.files.length === 0) {
-            return;
-        }
-
-        await this.handleFiles(fileElem.files);
-
-        // reset the element's value so the user can upload the same file(s) again
-        fileElem.value = '';
-    }
-
-    /**
-     * Handles files that were dropped to or selected in the component
-     *
-     * @param files
-     * @returns {Promise<void>}
-     */
-    async handleFiles(files) {
-        console.log('handleFiles: files.length = ' + files.length);
-        this.multipleUploadInProgress = true;
-
-        this.dispatchEvent(new CustomEvent("vpu-fileupload-all-start",
-            { "detail": {}, bubbles: true, composed: true }));
-
-        // we need to copy the files to another array or else they will be gone in the setTimeout function!
-        let tempFilesToHandle = [];
-        await commonUtils.asyncArrayForEach(files, async (file) => {
-            if (file.size === 0) {
-                console.log('file \'' + file.name + '\' has size=0 and is denied!')
-                return;
-            }
-
-            // check if we want to decompress the zip and queue the contained files
-            if (this.decompressZip && file.type === "application/zip") {
-                // add decompressed files to tempFilesToHandle
-                tempFilesToHandle = tempFilesToHandle.concat(await this.decompressZIP(file));
-
-                return;
-            } else if (this.allowedMimeTypes && !this.checkFileType(file)) {
-                return;
-            }
-
-            tempFilesToHandle.push(file);
-        });
-
-        // the browsers don't render updates to the dom while these files are handled!
-        // if we set a small delay the dom changes will be rendered
-        setTimeout(async () => {
-            // we need to wait for each upload until we start the next one
-            await commonUtils.asyncArrayForEach(tempFilesToHandle, async (file) =>
-                this.isDeferred ? this.queueFile(file) : this.uploadFile(file));
-
-            this.multipleUploadInProgress = false;
-
-            this.dispatchEvent(new CustomEvent("vpu-fileupload-all-finished",
-                { "detail": {}, bubbles: true, composed: true }));
-        }, 100);
-    }
-
-    checkFileType(file) {
-        // check if file is allowed
-        const [fileMainType, fileSubType] = file.type.split('/');
-        const mimeTypes = this.allowedMimeTypes.split(',');
-        let deny = true;
-
-        mimeTypes.forEach((str) => {
-            const [mainType, subType] = str.split('/');
-            deny = deny && ((mainType !== '*' && mainType !== fileMainType) || (subType !== '*' && subType !== fileSubType));
-        });
-
-        if (deny) {
-            console.log(`mime type ${file.type} of file '${file.name}' is not compatible with ${this.allowedMimeTypes}`);
-
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Decompress files synchronously
-     *
-     * @param file
-     * @returns {Promise<[]>}
-     */
-    async decompressZIP(file) {
-        // see: https://stuk.github.io/jszip/
-        let JSZip = (await import('jszip/dist/jszip.js')).default;
-        let filesToHandle = [];
-
-        // load zip file
-        await JSZip.loadAsync(file)
-            .then(async (zip) => {
-                // we are not using zip.forEach because we need to handle those files synchronously which
-                // isn't supported by JSZip (see https://github.com/Stuk/jszip/issues/281)
-                // using zip.files directly works great!
-                await commonUtils.asyncObjectForEach(zip.files, async (zipEntry) => {
-                    // skip directory entries
-                    if (zipEntry.dir) {
-                        return;
-                    }
-
-                    await zipEntry.async("blob")
-                        .then(async (blob) => {
-                            // get mime type of Blob, see https://github.com/Stuk/jszip/issues/626
-                            const mimeType = await commonUtils.getMimeTypeOfFile(blob);
-
-                            // create new file with name and mime type
-                            const zipEntryFile = new File([blob], zipEntry.name, { type: mimeType });
-
-                            // check mime type
-                            if (!this.checkFileType(zipEntryFile)) {
-                                return;
-                            }
-
-                            filesToHandle.push(zipEntryFile);
-                        }, (e) => {
-                            // handle the error
-                            console.error("Decompressing of file in " + file.name + " failed: " + e.message);
-                        });
-                    });
-            }, function (e) {
-                // handle the error
-                console.error("Loading of " + file.name + " failed: " + e.message);
-            });
-
-        return filesToHandle;
-    }
-
-    async sendFinishedEvent(response, file, sendFile = false) {
-        if (response === undefined) {
-            return;
-        }
-
-        let data =  {
-            fileName: file.name,
-            status: response.status,
-            json: {"hydra:description": ""}
-        };
-
-        try {
-            await response.json().then((json) => {
-                data.json = json;
-            });
-        } catch (e) {}
-
-        if (sendFile) {
-            data.file = file;
-        }
-
-        const event = new CustomEvent("vpu-fileupload-file-finished", { "detail": data, bubbles: true, composed: true });
-        this.dispatchEvent(event);
-    }
-
-    sendStartEvent(file) {
-        let data =  {
-            fileName: file.name,
-            fileSize: file.size,
-        };
-
-        this.dispatchEvent(new CustomEvent("vpu-fileupload-file-start",
-            { "detail": data, bubbles: true, composed: true }));
-    }
-
-    /**
-     * @param file
-     * @returns {Promise<number>} key of the queued item
-     */
-    async queueFile(file) {
-        this._queueKey++;
-        const key = this._queueKey;
-        this.queuedFiles[key] = file;
-        this.updateQueuedFilesCount();
-
-        const data = {"file": file};
-        const event = new CustomEvent("vpu-fileupload-file-queued", { "detail": data, bubbles: true, composed: true });
-        this.dispatchEvent(event);
-
-        return key;
-    }
-
-    /**
-     * Takes a file off of the queue
-     *
-     * @param key
-     */
-    takeFileFromQueue(key) {
-        const file = this.queuedFiles[key];
-        delete this.queuedFiles[key];
-        this.updateQueuedFilesCount();
-
-        return file;
-    }
-
-    uploadOneQueuedFile() {
-        const file = this.takeFileFromQueue();
-
-        return this.uploadFile(file);
-    }
-
-    getQueuedFile(key) {
-        return this.queuedFiles[key];
-    }
-
-    getQueuedFiles() {
-        return this.queuedFiles;
-    }
-
-    clearQueuedFiles() {
-        this.queuedFiles = [];
-        this.queuedFilesCount = 0;
-    }
-
-    updateQueuedFilesCount() {
-        return this.queuedFilesCount = Object.keys(this.queuedFiles).length;
-    }
-
-    getQueuedFilesCount() {
-        return this.queuedFilesCount;
-    }
-
-    /**
-     * @param file
-     * @param params
-     * @returns {Promise<void>}
-     */
-    async uploadFile(file, params = {}) {
-        this.uploadInProgress = true;
-        this.sendStartEvent(file);
-        let url = new URL(this.url)
-        url.search = new URLSearchParams(params).toString();
-        let formData = new FormData();
-        formData.append('file', file);
-
-        // I got a 60s timeout in Google Chrome and found no way to increase that
-        await fetch(url, {
-            method: 'POST',
-            headers: {
-                'Authorization': 'Bearer ' + window.VPUAuthToken,
-            },
-            body: formData
-        })
-            .then((response) => {
-                /* Done. Inform the user */
-                console.log(`Status: ${response.status} for file ${file.name}`);
-                this.sendFinishedEvent(response, file, response.status !== 201 || this.alwaysSendFile);
-            })
-            .catch((response) => {
-                /* Error. Inform the user */
-                console.log(`Error status: ${response.status} for file ${file.name}`);
-                this.sendFinishedEvent(response, file, true);
-            });
-
-        this.uploadInProgress = false;
-    }
-
-    static get styles() {
-        // language=css
-        return css`
-            ${commonStyles.getGeneralCSS()}
-            ${commonStyles.getButtonCSS()}
-
-            #dropArea {
-                border: var(--FUBorderWidth, 2px) var(--FUBorderStyle, dashed) var(--FUBBorderColor, black);
-                border-radius: var(--FUBorderRadius, 0);
-                width: var(--FUWidth, auto);
-                margin: var(--FUMargin, 0px);
-                padding: var(--FUPadding, 20px);
-            }
-
-            #dropArea.highlight {
-                border-color: var(--FUBorderColorHighlight, purple);
-            }
-
-            p {
-                margin-top: 0;
-            }
-
-            #fileElem {
-                display: none;
-            }
-
-            #nextcloud-file-picker {
-                display: inline-block;
-                margin-left: 8px;
-            }
-
-            #nextcloud-file-picker.hidden {
-                display: none;
-            }
-
-            .block {
-                margin-bottom: 10px;
-            }
-        `;
-    }
-
-    render() {
-        let allowedMimeTypes = this.allowedMimeTypes;
-
-        if (this.decompressZip) {
-            allowedMimeTypes += ",application/zip";
-        }
-
-        return html`
-            <div id="dropArea">
-                <div title="${this.uploadInProgress ? i18n.t('upload-disabled-title') : ''}">
-                    <div class="block">
-                        ${this.text || i18n.t('intro')}
-                    </div>
-                    <input ?disabled="${this.uploadInProgress || this.disabled}"
-                           type="file"
-                           id="fileElem"
-                           multiple
-                           accept="${mimeTypesToAccept(allowedMimeTypes)}"
-                           name='file'>
-                    <label class="button is-primary" for="fileElem" ?disabled="${this.disabled}">
-                        <vpu-icon style="display: ${this.uploadInProgress ? "inline-block" : "none"}" name="lock"></vpu-icon>
-                        ${this.buttonLabel || i18n.t('upload-label')}
-                    </label>
-                    <vpu-nextcloud-file-picker id="nextcloud-file-picker"
-                                               class="${classMap({hidden: this.nextcloudWebDavUrl === "" || this.nextcloudAuthUrl === ""})}"
-                                               ?disabled="${this.uploadInProgress || this.disabled}"
-                                               lang="${this.lang}"
-                                               auth-url="${this.nextcloudAuthUrl}"
-                                               web-dav-url="${this.nextcloudWebDavUrl}"
-                                               @vpu-nextcloud-file-picker-file-downloaded="${(event) => {
-                                                   this.queueFile(event.detail.file);
-                                               }}"></vpu-nextcloud-file-picker>
-                    <vpu-mini-spinner style="display: ${this.multipleUploadInProgress ? "inline-block" : "none"}"></vpu-mini-spinner>
-                </div>
-            </div>
-        `;
-    }
-}
\ No newline at end of file
diff --git a/packages/file-handling/src/index.js b/packages/file-handling/src/index.js
index 45db83f7a3f2a0f0ac2b3a30aa332be2a4d2ffd7..5ffde080d02d0a7a86cdf077cd23230ef0ed035f 100644
--- a/packages/file-handling/src/index.js
+++ b/packages/file-handling/src/index.js
@@ -1,5 +1,3 @@
-import {FileUpload} from './fileupload';
 import {FileSource} from './file-source';
 
-export {FileUpload};
 export {FileSource};
\ No newline at end of file
diff --git a/packages/file-handling/src/vpu-fileupload.js b/packages/file-handling/src/vpu-fileupload.js
deleted file mode 100644
index d1b827890f4c80ee24ff83cefa7244f36e87918c..0000000000000000000000000000000000000000
--- a/packages/file-handling/src/vpu-fileupload.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import * as commonUtils from "vpu-common/utils";
-import {FileUpload} from './fileupload';
-
-commonUtils.defineCustomElement('vpu-fileupload', FileUpload);