diff --git a/README.md b/README.md
index 249afcfbd9f5ee0244c37b0f58af47dab4193e11..ccd5ccb1db46a33bc636e4c433293e059bb931e1 100644
--- a/README.md
+++ b/README.md
@@ -8,62 +8,19 @@ Qt Design Viewer works in a variety of web browsers which support WebAssembly, o
 ## Prerequisites
 
 * CMake 3.16 or newer
-* Android
-    * Qt6.5.0 or newer
-    * OpenSSL (<https://github.com/KDAB/android_openssl>)
-    * Android SDK and NDK (<https://developer.android.com/studio>)
 * WebAssembly
     * Qt6.4.3 or newer
     * EMSDK (<https://emscripten.org/docs/getting_started/downloads.html>)
 
 ## Building
 
-Build instructions are provided for Linux, macOS hosts and for Android and WebAssembly targets. Windows should work as well but is not tested.
-> Note:
+> Note 1:
+> Build instructions are provided for Linux, macOS hosts and for WebAssembly target. Windows should work as well but is not tested.
+>
+> Note 2:
 > If you're building in a Docker container and you've mounted the source directory into the container, you may need to change the build path pointing out somewhere out of the source directory. Otherwise you may get errors like the following;
 > `CMake Error at /opt/qt-v.6.5.0/android-arm64-v8a/lib/cmake/Qt6/QtSyncQtHelpers.cmake:235 (message): syncqt.cpp failed for module QtQuickStudioApplication: Unable to remove file ...`
 
-### Android
-
-> Note:
-> Android build instructions can also be used on desktop (or host) for testing purposes. Just replace the `CMAKE_TOOLCHAIN_FILE` path with the path to your Qt host installation.
-
-First build and install QtQuickDesigner Components for Android:
-
-```bash
-cd qtquickdesigner-components
-cmake \
-    -S . \
-    -B build \
-    -G Ninja \
-    -DCMAKE_TOOLCHAIN_FILE=<qt-android-path>/lib/cmake/Qt6/qt.toolchain.cmake \
-    -DCMAKE_INSTALL_PREFIX=<qt-android-path> \
-    -DANDROID_SDK_ROOT=<android-sdk-path> \
-    -DANDROID_NDK_ROOT=<android-sdk-path>/ndk/<ndk-version> \
-    -DANDROID_OPENSSL_PATH=<openssl-path>
-
-cmake --build build
-cmake --install build
-cd ..
-```
-
-Then build the Qt Design Viewer:
-
-```bash
-cmake \
-    -S . \
-    -B build \
-    -G Ninja \
-    -DCMAKE_TOOLCHAIN_FILE=<qt-android-path>/lib/cmake/Qt6/qt.toolchain.cmake \
-    -DANDROID_SDK_ROOT=<android-sdk-path> \
-    -DANDROID_NDK_ROOT=<android-sdk-path>/ndk/<ndk-version> \
-    -DANDROID_OPENSSL_PATH=<openssl-path>
-
-cmake --build build
-```
-
-### WebAssembly
-
 First activate the correct EMSDK version:
 
 ```bash
@@ -82,8 +39,9 @@ cmake \
     -S . \
     -B build \
     -G Ninja \
-    -DCMAKE_TOOLCHAIN_FILE=<qt-wasm-path>/wasm/lib/cmake/Qt6/qt.toolchain.cmake \
-    -DCMAKE_INSTALL_PREFIX=<qt-wasm-path>
+    -DCMAKE_PREFIX_PATH=<qt-wasm-path> \
+    -DCMAKE_INSTALL_PREFIX=<qt-wasm-path> \
+    -DCMAKE_TOOLCHAIN_FILE=<qt-wasm-path>/wasm/lib/cmake/Qt6/qt.toolchain.cmake
 
 cmake --build build
 cmake --install build
@@ -97,6 +55,8 @@ cmake \
     -S . \
     -B build \
     -G Ninja \
+    -DCMAKE_PREFIX_PATH=<qt-wasm-path> \
+    -DCMAKE_INSTALL_PREFIX=<qt-wasm-path> \
     -DCMAKE_TOOLCHAIN_FILE=<qt-wasm-path>/wasm/lib/cmake/Qt6/qt.toolchain.cmake
 
 cmake --build build
diff --git a/qtquickdesigner-components b/qtquickdesigner-components
index 0e457477d54b068abc89cf124daedefe0436dd89..55dfd50975935efbe67ea8cdb77ac01e4640db88 160000
--- a/qtquickdesigner-components
+++ b/qtquickdesigner-components
@@ -1 +1 @@
-Subproject commit 0e457477d54b068abc89cf124daedefe0436dd89
+Subproject commit 55dfd50975935efbe67ea8cdb77ac01e4640db88
diff --git a/resources/dvicon-new.png b/resources/dvicon-new.png
new file mode 100644
index 0000000000000000000000000000000000000000..554b5eee2046e491e36ea9c489a20fa602b72bd7
Binary files /dev/null and b/resources/dvicon-new.png differ
diff --git a/src/designviewer.cpp b/src/designviewer.cpp
index 941ae499651259ed2c7cace150a2f4f10d5618d1..f073872ec70ed7eb57c662c82a7e9556530cf2df 100644
--- a/src/designviewer.cpp
+++ b/src/designviewer.cpp
@@ -24,9 +24,9 @@
 ****************************************************************************/
 
 #include "designviewer.h"
-#if defined(Q_OS_WASM)
 
 #include <emscripten.h>
+#include <emscripten/val.h>
 #include <functional>
 
 #include <QBuffer>
@@ -38,6 +38,7 @@
 #include <QResource>
 #include <QTemporaryDir>
 #include <QTemporaryFile>
+#include <QTimer>
 #include <QtCore/private/qzipreader_p.h>
 
 #define printErr(x) printError(x, __FILE_NAME__, __LINE__)
@@ -56,55 +57,29 @@ extern "C" EMSCRIPTEN_KEEPALIVE void qt_callSetFileData(char *content,
 
 DesignViewer::DesignViewer()
 {
+    printLog("DesignViewer constructor");
     QString projectFileName;
     QByteArray projectData;
+    printLog("Fetching project");
     fetchProject(&projectData, &projectFileName);
-    if (!runProject(projectData, projectFileName))
-        printError("Failed to run project", projectFileName, 0);
+    printLog("Running project");
+    if (!runProject(projectData, projectFileName)) {
+        printErr("Failed to run project");
+    }
+    printLog("DesignViewer constructor done");
 }
 
 void DesignViewer::fetchProject(QByteArray *data, QString *fileName)
 {
-    // Call qt_callSetFileData to make sure the emscripten linker does not
-    // optimize it away, which may happen if the function is called from JavaScript
-    // only. Set g_setFileDataCallback to null to make it a no-op.
-    ::g_setFileDataCallback = nullptr;
-    ::qt_callSetFileData(nullptr, 0, nullptr);
-
-    auto setFileDataCallback =
-        [data, fileName](char *content, size_t contentSize, char *projectFilename)
-    {
-        data->setRawData(content, contentSize);
-        *fileName = QString::fromUtf8(projectFilename);
-    };
-    g_setFileDataCallback = setFileDataCallback;
-
-    EM_ASM_({
-        // Copy the file file content to the C++ heap.
-        // Note: this could be simplified by passing the content as an
-        // "array" type to ccall and then let it copy to C++ memory.
-        // However, this built-in solution does not handle files larger
-        // than ~15M (Chrome). Instead, allocate memory manually and
-        // pass a pointer to the C++ side (which will free() it when done).
-
-        // TODO: consider slice()ing the file to read it picewise and
-        // then assembling it in a QByteArray on the C++ side.
-
-        const contentSize = contentArray.byteLength;
-        const heapPointer = _malloc(contentSize);
-        const heapBytes = new Uint8Array(Module.HEAPU8.buffer, heapPointer, contentSize);
-        heapBytes.set(contentArray);
-
-        // Null out the first data copy to enable GC
-        reader = null;
-        contentArray = null;
-
-        // Call the C++ file data ready callback
-        ccall("qt_callSetFileData",
-              null,
-              [ "number", "number", "string" ],
-              [ heapPointer, contentSize, projectfileName ]);
-    });
+    printLog("Init project data");
+    // Access global variables set by index.html
+    emscripten::val jsData = emscripten::val::global("contentArray");
+    emscripten::val jsFileName = emscripten::val::global("projectfileName");
+
+    printLog("Copying project data");
+    // Copy project data to the C++ heap and convert string
+    *data = QByteArray::fromEcmaUint8Array(jsData);
+    *fileName = QString::fromStdString(jsFileName.as<std::string>());
 }
 
 QString DesignViewer::unpackProject(const QByteArray &project, bool extractZip)
@@ -385,10 +360,27 @@ void DesignViewer::showAppWindow()
 {
     printLog("Resizing the QML app window");
     const QSize size;
-    const QString command = QString::fromLatin1("setScreenSize(%1, %2);").arg(size.width()).arg(size.height());
-    emscripten_run_script(command.toUtf8());
+
+    emscripten::val qtContainer = emscripten::val::global("container"); // global from index.html
+    emscripten::val qtContainerStyle = qtContainer["style"];
+
+    if (size.isEmpty()) {
+        qtContainerStyle.set("width", std::string("100%"));
+        qtContainerStyle.set("height",
+                             std::string(
+                                 "100%")); // ### FIXME: 100% height gives 0px height for some reason
+    } else {
+        qtContainerStyle.set("width", QString("%1px").arg(size.width()).toStdString());
+        qtContainerStyle.set("height", QString("%1px").arg(size.height()).toStdString());
+    }
+
+    // Make Qt pick up the new container size by calling the resizeCanvasElement()
+    // qtloader API. This needs to be done on delay after initial setup to make
+    // sure qtloader is initialized.
+    QTimer::singleShot(0, [qtContainer]() {
+        emscripten::val qtLoader = emscripten::val::global("qtLoader");
+        qtLoader.call<void>("resizeCanvasElement", qtContainer);
+    });
     printLog("Showing the QML app window");
     m_quickWindow->show();
 }
-
-#endif // Q_OS_WASM
diff --git a/www/index.html b/www/index.html
index f63216846c29a0fd269a6f4b07ddc84fef3be767..9f4209c2f8513f3707a7dba84f60514d26f06c5a 100644
--- a/www/index.html
+++ b/www/index.html
@@ -55,6 +55,7 @@
         <div id="title">Qt Design Viewer</div>
         <div id="subtitle" class="subtitleclass">Powered by WebAssembly</div>
         <div id="qtstatus"></div>
+        <div id="screen"></div>
         <noscript
           >JavaScript is disabled. Please enable JavaScript to use this
           application.</noscript
@@ -119,10 +120,11 @@
     </div>
 
     <canvas
-      id="qtcanvas"
+      id="qtcontainer"
       oncontextmenu="event.preventDefault()"
       contenteditable="true"
     ></canvas>
+    <!-- <div id="qtcontainer"></div> -->
     <div id="footer">
       <div id="alertBox" class="alert">
         <span
@@ -148,7 +150,7 @@
       </p>
       <p id="versioninfo_main">Version: 1.0.0</p>
     </div>
-
+    <script src="qtdesignviewer.js"></script>
     <script src="scripts/script.js" type="text/javascript"></script>
     <script src="qtloader.js" type="text/javascript"></script>
   </body>
diff --git a/www/scripts/script.js b/www/scripts/script.js
index f6ae3ba1c1bb1eace1fdb1f70f3d450d7fd67e76..ad59ac294e05dee9c51d1b09b1312d2a4c4dae2b 100644
--- a/www/scripts/script.js
+++ b/www/scripts/script.js
@@ -1,8 +1,8 @@
 var contentArray;
 var projectfileName;
 var reader;
-var spinner = document.querySelector("#qtspinner");
-var canvas = document.querySelector("#qtcanvas");
+
+var canvas = document.querySelector("#qtcontainer");
 var uploadform = document.querySelector("#uploadform");
 var fileinput = document.querySelector("#fileinput");
 var dropzone = document.querySelector("#dropzone");
@@ -210,46 +210,57 @@ function restart() {
     qtLoader.loadEmscriptenModule("qtdesignviewer");
 }
 
-function loadProjector() {
-    qtLoader = QtLoader({
-        canvasElements: [canvas],
-        showLoader: function (loaderStatus) {
-            spinner.style.display = "block";
-            canvas.style.display = "none";
-            if (loaderStatus === "Downloading/Compiling")
-                loaderStatus = "Starting";
-            launchstatustext.innerHTML = loaderStatus;
-        },
-        showError: function (errorText) {
-            launchstatustext.innerHTML = errorText;
-            spinner.style.display = "block";
-            canvas.style.display = "none";
-        },
-        showExit: function () {
-            launchstatustext.innerHTML = "Application exit";
-            if (qtLoader.exitCode !== undefined)
-                launchstatustext.innerHTML += " with code " + qtLoader.exitCode;
-            if (qtLoader.exitText !== undefined)
-                launchstatustext.innerHTML += " (" + qtLoader.exitText + ")";
-            spinner.style.display = "block";
-            canvas.style.display = "none";
-        },
-        showCanvas: function () {
-            spinner.style.display = "none";
-            canvas.style.display = "block";
-            launchstatus.style.display = "none";
-            appheader.style.display = "block";
-        },
-    });
-
+async function loadProjector() {
     // workaround for making sure that self.module is set up before
     // running setScreenSize
+    self.moduleConfig = {};
     self.moduleConfig.preRun = [];
     self.moduleConfig.preRun.push(function (module) {
         self.module = module;
     });
 
-    qtLoader.loadEmscriptenModule("qtdesignviewer");
+    const spinner = document.querySelector("#qtspinner");
+    const screen = document.querySelector('#screen');
+    const status = document.querySelector('#qtstatus');
+
+    const showUi = (ui) => {
+        [spinner, screen].forEach(element => element.style.display = 'none');
+        if (screen === ui)
+            screen.style.position = 'default';
+        ui.style.display = 'block';
+        console.log("showUi", ui);
+    }
+
+    try {
+        showUi(spinner);
+        status.innerHTML = 'Loading...';
+
+        const instance = await qtLoad({
+            qt: {
+                onLoaded: () => showUi(screen),
+                onExit: exitData => {
+                    status.innerHTML = 'Application exit';
+                    status.innerHTML +=
+                        exitData.code !== undefined ? ` with code ` : '';
+                    status.innerHTML +=
+                        exitData.text !== undefined ? ` ()` : '';
+                    showUi(spinner);
+                },
+                entryFunction: window.createQtAppInstance,
+                containerElements: [screen]
+            }
+        }).then((result) => {
+            qtLoader = result;
+            console.log("qtLoader", qtLoader);
+            setScreenSize(window.innerWidth, window.innerHeight);
+        }).catch((err) => {
+            console.error(err);
+            console.error(err.stack);
+        });
+    } catch (e) {
+        console.error(e);
+        console.error(e.stack);
+    }
 }
 
 function setScreenSize(width, height) {
@@ -264,5 +275,7 @@ function setScreenSize(width, height) {
         document.documentElement.style.overflow =
             document.body.style.overflow = "hidden";
     }
+    console.log("setScreenSize", width, height);
+    console.log("current qtloader object:", qtLoader);
     qtLoader.resizeCanvasElement(canvas);
 }