diff --git a/CMakeLists.txt b/CMakeLists.txt
index ffdee5d5b945eb8b2db39a7775e0b103a12918b6..42061f13ce3428c4729f244eda3b21af22e9ac41 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -47,16 +47,15 @@ execute_process(COMMAND git -C ${CMAKE_SOURCE_DIR}/3rdparty/zxing-cpp describe -
 add_definitions( -DCMAKE_VAR_GIT_VERSION="${CMAKE_VAR_GIT_VERSION}" )
 add_definitions( -DCMAKE_VAR_QT_QUICK_COMPONENTS_VERSION="${CMAKE_VAR_QT_QUICK_COMPONENTS_VERSION}" )
 add_definitions( -DCMAKE_VAR_ZXING_VERSION="${CMAKE_VAR_ZXING_VERSION}" )
-
-add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/zxing-cpp)
-add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src)
-add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tests)
-
 # this needs to be increased with every new release
 if(NOT DEFINED GOOGLE_PLAY_APP_VERSION)
     set(GOOGLE_PLAY_APP_VERSION 31)
 endif()
 
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/zxing-cpp)
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src)
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tests)
+
 message(STATUS "GOOGLE_PLAY_APP_VERSION: ${GOOGLE_PLAY_APP_VERSION}")
 message(STATUS "PROJECT VERSION: ${CMAKE_VAR_GIT_VERSION}")
 message(STATUS "QT_VERSION: ${QT_VERSION}")
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c140b57f320f0a244dd6bfb8f2099d9c572060c9..4330115bfb9bdbbb879b1d53e28e8ec5bbb86e0f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -78,7 +78,7 @@ target_include_directories(qtuiviewerlib PUBLIC
 
 set_target_properties(${PROJECT_NAME} PROPERTIES QT_ANDROID_PACKAGE_NAME "io.qt.qtdesignviewer")
 set_property(TARGET ${PROJECT_NAME}
-    APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android
+APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android
 )
 set_property(TARGET ${PROJECT_NAME}
     APPEND PROPERTY QT_ANDROID_EXTRA_LIBS
@@ -86,5 +86,6 @@ set_property(TARGET ${PROJECT_NAME}
         ${ANDROID_OPENSSL_PATH}/libssl_3.so
 )
 
+
 # CMAKE_VAR_GIT_VERSION (coming from the top-level CMakeLists.txt) and GOOGLE_PLAY_APP_VERSION replaced in the following file
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/android/AndroidManifest.xml.in ${CMAKE_CURRENT_SOURCE_DIR}/android/AndroidManifest.xml)
diff --git a/src/HomePage.qml b/src/HomePage.qml
index d00944a69d5df750580fe82a7022af5619bf95cb..f5b8bfbdfb455a50fb165da8975b81875f9b4eb0 100644
--- a/src/HomePage.qml
+++ b/src/HomePage.qml
@@ -101,7 +101,7 @@ Flickable {
                     }
 
                     Repeater {
-                        model: [qsTr("Open Qt Design Studio"), qsTr("Click Play > Manage Run Targets"), qsTr("In Manage Run Targets window click Add run target button.")]
+                        model: [qsTr("Open up the Qt Design Studio, and a project"), qsTr("Click on the dropdown menu of the Play button in the header"), qsTr("Select Open Device Manager from the menu"), qsTr("In the Device Manager window click on Set Device IP and type in the IP address found from below")]
 
                         delegate: RowLayout {
                             Layout.fillWidth: true
@@ -150,16 +150,35 @@ Flickable {
                     Layout.fillWidth: true
                     text: qsTr("xxx.xxx.xxx.xxx")
                     font.pixelSize: Constants.lgTextSize
-                    font.bold: true
+                    font.bold: false
                     wrapMode: Text.WordWrap
 
-                    Component.onCompleted: {
+                    function updateIpAddresses() {
                         ipAddress.text = '';
                         var val = backend.getIpAddresses();
-                        for(var i = 0; i < val.length; i++) {
+
+                        if(val.length === 0)
+                            ipAddress.text = qsTr("Not connected to any network.");
+
+                        for(var i = 0; i < val.length; i++)
                             ipAddress.text += val[i].interface + ': ' + val[i].ip + '\n';
+                    }
+
+                    Timer {
+                        id: timer
+                        interval: 1000
+                        running: true
+                        repeat: true
+
+                        onTriggered: {
+                            ipAddress.updateIpAddresses();
                         }
                     }
+
+                    Component.onCompleted: {
+                        ipAddress.updateIpAddresses();
+                        timer.start();
+                    }
                 }
             }
         }
diff --git a/src/backend/backend.cpp b/src/backend/backend.cpp
index cc2c8f7a464f42366e253b3890001657678d54e4..8a5e82c63783715e0b52bd121725da4fc32dacc1 100644
--- a/src/backend/backend.cpp
+++ b/src/backend/backend.cpp
@@ -110,7 +110,7 @@ QString Backend::buildInfo() const
     // clang-format off
     return {
         QCoreApplication::applicationVersion() +
-        "\nTechnology Preview - "+ CMAKE_VAR_GIT_VERSION +
+        "\n"+ CMAKE_VAR_GIT_VERSION +
         "\nQt " + QT_VERSION_STR + " - " + buildType + " Build" +
         "\nQt Quick Components " + CMAKE_VAR_QT_QUICK_COMPONENTS_VERSION +
         "\nZXing-Cpp: " + CMAKE_VAR_ZXING_VERSION +
@@ -138,12 +138,21 @@ void Backend::initProjectManager()
 {
     m_projectManager.reset(new ProjectManager(this));
 
-    connect(m_projectManager.get(), &ProjectManager::closingProject, this, [this] {
-        QMetaObject::invokeMethod(m_dsManager.get(),
-                                  "sendProjectStopped",
-                                  Qt::QueuedConnection,
-                                  Q_ARG(QString, m_lastProjectSenderId));
-    });
+    connect(m_projectManager.get(),
+            &ProjectManager::closingProject,
+            this,
+            [this](const QString &sessionId) {
+                // most likely the project was running from the leftover session
+                // (DS connected, project started, DS disconnected without stopping the project)
+                // so we'll stop the project and do not send any signals to the DS
+                if (sessionId != m_lastSessionId)
+                    return;
+
+                QMetaObject::invokeMethod(m_dsManager.get(),
+                                          "sendProjectStopped",
+                                          Qt::QueuedConnection,
+                                          Q_ARG(QString, m_lastProjectSenderId));
+            });
 }
 
 void Backend::initDsManager()
@@ -175,23 +184,36 @@ void Backend::initDsManager()
     connect(m_dsManager.get(),
             &DesignStudioManager::projectIncoming,
             this,
-            [this](const int projectSize) {
+            [this](const QString &id, const int projectSize) {
                 qDebug() << "Project incoming with size" << projectSize;
                 emit updatePopupText("Receiving project...");
+                // we'll use this to notify the correct DS when the project started/stopped
+                m_lastProjectSenderId = id;
+                m_lastSessionId = QUuid::createUuid().toString(QUuid::WithoutBraces);
+                QMetaObject::invokeMethod(m_projectManager.get(),
+                                          "stopProject",
+                                          Qt::QueuedConnection);
+
             });
 
-    // connect(m_dsManager.get(),
-    //         &DesignStudioManager::projectIncomingProgress,
-    //         this,
-    //         [this](const QString &id, const int percentage) { updatePopupProgress(percentage); });
+    connect(m_dsManager.get(),
+            &DesignStudioManager::projectIncomingProgress,
+            this,
+            [this](const QString &id, const int percentage) { updatePopupProgress(percentage); });
 
     connect(m_dsManager.get(),
             &DesignStudioManager::projectStopRequested,
             this,
             [this](const QString &id) {
+                qDebug() << "Project stop requested";
+                emit popupClose();
                 QMetaObject::invokeMethod(m_projectManager.get(),
                                           "stopProject",
                                           Qt::QueuedConnection);
+                QMetaObject::invokeMethod(m_dsManager.get(),
+                                          "sendProjectStopped",
+                                          Qt::QueuedConnection,
+                                          Q_ARG(QString, m_lastProjectSenderId));
             });
 
     m_dsManager->init();
@@ -211,20 +233,22 @@ void Backend::runProject(const QString &id, const QByteArray &projectData)
 {
     emit updatePopupText("Running project...");
 
-    // we'll use this to notify the correct DS when the project started/stopped
-    m_lastProjectSenderId = id;
-    QMetaObject::invokeMethod(m_dsManager.get(), "sendProjectRunning", Q_ARG(QString, id));
-    bool retVal;
-    QMetaObject::invokeMethod(m_projectManager.get(),
-                              "runProject",
-                              Q_RETURN_ARG(bool, retVal),
-                              Q_ARG(QByteArray, projectData),
-                              Q_ARG(bool, autoScaleProject()));
-
-    if (!retVal)
-        QMetaObject::invokeMethod(m_dsManager.get(), "sendProjectStopped", Q_ARG(QString, id));
-
-    emit popupClose();
+    QTimer::singleShot(1000, [this, id, projectData] {
+        bool retVal;
+        QMetaObject::invokeMethod(m_projectManager.get(),
+                                  "runProject",
+                                  Q_RETURN_ARG(bool, retVal),
+                                  Q_ARG(QByteArray, projectData),
+                                  Q_ARG(bool, autoScaleProject()),
+                                  Q_ARG(QString, m_lastSessionId));
+
+        if (!retVal)
+            QMetaObject::invokeMethod(m_dsManager.get(), "sendProjectStopped", Q_ARG(QString, id));
+        else
+            QMetaObject::invokeMethod(m_dsManager.get(), "sendProjectRunning", Q_ARG(QString, id));
+
+        emit popupClose();
+    });
 }
 
 void Backend::scanQrCode()
@@ -310,7 +334,6 @@ QJsonArray Backend::getIpAddresses() const
     for (const auto &interface : networkInterface.allInterfaces()) {
         for (const auto &entry : interface.addressEntries()) {
             if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol && !entry.ip().isLoopback()) {
-                qDebug() << "Interface:" << interface.name() << "IP:" << entry.ip().toString();
                 ipAddresses.append(
                     QJsonObject{{"interface", interface.name()}, {"ip", entry.ip().toString()}});
             }
diff --git a/src/backend/backend.h b/src/backend/backend.h
index 072ce8da192270618cd657d978c3b89955f7898d..27858b0761fe845bd780726c902ccf4b26f42f1e 100644
--- a/src/backend/backend.h
+++ b/src/backend/backend.h
@@ -51,6 +51,7 @@ private:
     QScopedPointer<QrScanner> m_qrScanner;
 
     QString m_lastProjectSenderId;
+    QString m_lastSessionId;
 
     // Settings
     Settings m_settings;
diff --git a/src/backend/dsconnector/ds.cpp b/src/backend/dsconnector/ds.cpp
index 5554a41ea1d8e54b08df373b5fe989156546bf6a..464ec80b599c38e7a91c59c51d0f61369c468cc6 100644
--- a/src/backend/dsconnector/ds.cpp
+++ b/src/backend/dsconnector/ds.cpp
@@ -7,15 +7,48 @@
 #include <QJsonObject>
 #include <QScreen>
 
-DesignStudio::DesignStudio(QWebSocket *socket, const QString &m_deviceUuid, QObject *parent)
+namespace PackageFromDesignStudio {
+using namespace Qt::Literals;
+constexpr auto designStudioReady = "designStudioReady"_L1;
+constexpr auto projectData = "projectData"_L1;
+constexpr auto stopRunningProject = "stopRunningProject"_L1;
+}; // namespace PackageFromDesignStudio
+
+namespace PackageToDesignStudio {
+using namespace Qt::Literals;
+constexpr auto deviceInfo = "deviceInfo"_L1;
+constexpr auto projectReceivingProgress = "projectReceivingProgress"_L1;
+constexpr auto projectStarting = "projectStarting"_L1;
+constexpr auto projectRunning = "projectRunning"_L1;
+constexpr auto projectStopped = "projectStopped"_L1;
+constexpr auto projectLogs = "projectLogs"_L1;
+}; // namespace PackageToDesignStudio
+
+DesignStudio::DesignStudio(QWebSocket *socket, const QString &deviceID, QObject *parent)
     : QObject(parent)
-    , m_deviceUuid(m_deviceUuid)
+    , m_deviceID(deviceID)
     , m_socket(socket)
 {
     initPingPong();
     initSocket();
+    startPingPong();
+    m_projectStallTimer.setInterval(5000);
+    m_projectStallTimer.setSingleShot(true);
+    connect(&m_projectStallTimer, &QTimer::timeout, this, [this]() {
+        qDebug() << "Project is stalled. Closing the connection.";
+        m_socket->close();
+        m_socket->abort();
+        emit disconnected(m_designStudioID);
+    });
 
-    m_pingTimer.start();
+    m_speedCalculator.setInterval(1000);
+    m_speedCalculator.setSingleShot(false);
+    connect(&m_speedCalculator, &QTimer::timeout, this, [this]() {
+        quint64 elapsedTime = m_projectNotificationTime.msecsTo(QTime::currentTime()) / 1000;
+        int receiveSpeed = elapsedTime > 0 ? m_projectData.size() / elapsedTime / 1024 : 0;
+        qDebug() << "Receive speed" << receiveSpeed << "KB/s (" << receiveSpeed / 1024 << "MB/s )"
+                 << "percentage" << m_lastPercentage << "%";
+    });
 }
 
 void DesignStudio::initPingPong()
@@ -27,7 +60,7 @@ void DesignStudio::initPingPong()
 
     connect(&m_pingTimer, &QTimer::timeout, this, [this]() {
         m_socket->ping();
-        m_pongTimer.start();
+        startPingPong();
     });
 
     connect(m_socket.data(),
@@ -39,20 +72,32 @@ void DesignStudio::initPingPong()
             });
 
     connect(&m_pongTimer, &QTimer::timeout, this, [this]() {
-        qDebug() << "Design Studio" << m_id << "is not responding. Closing the connection.";
+        qDebug() << "Design Studio" << m_designStudioID
+                 << "is not responding. Closing the connection.";
         m_socket->close();
         m_socket->abort();
-        emit disconnected(m_id);
+        emit disconnected(m_designStudioID);
     });
 }
 
+void DesignStudio::stopPingPong()
+{
+    m_pingTimer.stop();
+    m_pongTimer.stop();
+}
+
+void DesignStudio::startPingPong()
+{
+    m_pingTimer.start();
+}
+
 void DesignStudio::initSocket()
 {
     connect(m_socket.data(), &QWebSocket::disconnected, this, [this]() {
-        qDebug() << "Design Studio" << m_id << "disconnected";
+        qDebug() << "Design Studio" << m_designStudioID << "disconnected";
         m_pingTimer.stop();
         m_pongTimer.stop();
-        emit disconnected(m_id);
+        emit disconnected(m_designStudioID);
     });
 
     connect(m_socket.data(),
@@ -61,20 +106,9 @@ void DesignStudio::initSocket()
             &DesignStudio::processTextMessage);
 
     connect(m_socket.data(),
-            &QWebSocket::binaryFrameReceived,
+            &QWebSocket::binaryMessageReceived,
             this,
-            [this](const QByteArray &frame, bool isLastFrame) {
-                m_projectData.append(frame);
-                int percentage = m_projectData.size() * 100 / m_incomingProjectSize;
-                qDebug() << "frame size:" << frame.size() << "current size:" << m_projectData.size()
-                         << "total size:" << m_incomingProjectSize << "percentage:" << percentage
-                         << "isLastFrame:" << isLastFrame;
-                emit projectIncomingProgress(m_id,
-                                             m_projectData.size() * 100 / m_incomingProjectSize);
-                if (isLastFrame) {
-                    emit projectReceived(m_id, m_projectData);
-                }
-            });
+            &DesignStudio::processBinaryMessage);
 }
 
 QString DesignStudio::ipv4Addr() const
@@ -84,7 +118,7 @@ QString DesignStudio::ipv4Addr() const
 
 QString DesignStudio::id() const
 {
-    return m_id;
+    return m_designStudioID;
 }
 
 void DesignStudio::sendDeviceInfo()
@@ -97,7 +131,7 @@ void DesignStudio::sendDeviceInfo()
     deviceInfo["os"] = QSysInfo::prettyProductName();
     deviceInfo["osVersion"] = QSysInfo::productVersion();
     deviceInfo["architecture"] = QSysInfo::currentCpuArchitecture();
-    deviceInfo["deviceId"] = m_deviceUuid;
+    deviceInfo["deviceId"] = m_deviceID;
     deviceInfo["appVersion"] = QString(CMAKE_VAR_GIT_VERSION);
 
     qDebug() << "Sending device info to Design Studio" << deviceInfo;
@@ -131,31 +165,73 @@ void DesignStudio::processTextMessage(const QString &message)
     }
 
     const QString dataType = jsonObj.value("dataType").toString();
+    const QJsonObject data = jsonObj.value("data").toObject();
 
     if (dataType == PackageFromDesignStudio::designStudioReady) {
-        const QString newDesignStudioId = jsonObj.value("data").toString();
-        qDebug() << "Design Studio ready with ID" << newDesignStudioId;
-        m_id = newDesignStudioId;
+        const QString newDesignStudioId = data["designStudioID"].toString();
+        const int commVersion = data["commVersion"].toInt();
+        qDebug() << "Design Studio ready with ID" << newDesignStudioId << "and comm version"
+                 << commVersion;
+        m_designStudioID = newDesignStudioId;
         sendDeviceInfo();
         emit idReceived(newDesignStudioId, ipv4Addr());
     } else if (dataType == PackageFromDesignStudio::projectData) {
-        m_incomingProjectSize = jsonObj.value("data").toInt();
-        qDebug() << "Project is expected with size" << m_incomingProjectSize;
+        m_incomingProjectSize = data["projectSize"].toInt();
+        const QString qtVersion = data["qtVersion"].toString();
+
+        auto qcompare = QString::compare(qtVersion, QT_VERSION_STR, Qt::CaseInsensitive);
+        if (qcompare != 0) {
+            qDebug() << "Qt version mismatch. Expected" << QT_VERSION_STR " or lower, but got"
+                     << qtVersion << ". Project may not work correctly.";
+            emit projectVersionMismatch(QT_VERSION_STR, qtVersion);
+        }
+
+        qDebug() << "Project is expected with size" << m_incomingProjectSize << "and Qt version"
+                 << qtVersion;
         m_projectData.clear();
-        emit projectIncoming(m_incomingProjectSize);
+        m_projectNotificationTime = QTime::currentTime();
+        m_speedCalculator.start();
+        m_projectStallTimer.start();
+
+        stopPingPong();
+        emit projectIncoming(m_designStudioID, m_incomingProjectSize);
     } else if (dataType == PackageFromDesignStudio::stopRunningProject) {
         qDebug() << "Stop running project requested";
-        emit projectStopRequested(m_id);
+        m_projectData.clear();
+        m_speedCalculator.stop();
+        m_projectStallTimer.stop();
+        emit projectStopRequested(m_designStudioID);
     } else {
-        qDebug() << "Unkown JSON message";
+        qDebug() << "Unkown JSON message type:" << dataType;
     }
 }
 
-// this function should only be triggered when the device is receiving a qmlrc project
 void DesignStudio::processBinaryMessage(const QByteArray &data)
 {
-    qDebug() << "Binary message received (most probably a project)";
-    emit projectReceived(m_id, data);
+    m_projectStallTimer.start();
+    m_projectData.append(data);
+    const bool isProjectComplete = m_projectData.size() == m_incomingProjectSize;
+
+    int percentage = m_projectData.size() * 100 / m_incomingProjectSize;
+
+    if (m_lastPercentage != percentage) {
+        emit projectIncomingProgress(m_designStudioID, percentage);
+        m_lastPercentage = percentage;
+        sendData(PackageToDesignStudio::projectReceivingProgress, percentage);
+    }
+
+    if (isProjectComplete) {
+        startPingPong();
+        sendProjectStarting();
+        emit projectReceived(m_designStudioID, m_projectData);
+        m_speedCalculator.stop();
+        m_projectStallTimer.stop();
+    }
+}
+
+void DesignStudio::sendProjectStarting()
+{
+    sendData(PackageToDesignStudio::projectStarting);
 }
 
 void DesignStudio::sendProjectRunning()
diff --git a/src/backend/dsconnector/ds.h b/src/backend/dsconnector/ds.h
index 468381b77fbd5fc8d92f41691e5e008269249f67..db69e0c3a067f5304869c8262774454dbc25a86b 100644
--- a/src/backend/dsconnector/ds.h
+++ b/src/backend/dsconnector/ds.h
@@ -7,26 +7,11 @@
 #include <QTimer>
 #include <QWebSocket>
 
-namespace PackageFromDesignStudio {
-using namespace Qt::Literals;
-constexpr auto designStudioReady = "designStudioReady"_L1;
-constexpr auto projectData = "projectData"_L1;
-constexpr auto stopRunningProject = "stopRunningProject"_L1;
-}; // namespace PackageFromDesignStudio
-
-namespace PackageToDesignStudio {
-using namespace Qt::Literals;
-constexpr auto deviceInfo = "deviceInfo"_L1;
-constexpr auto projectRunning = "projectRunning"_L1;
-constexpr auto projectStopped = "projectStopped"_L1;
-constexpr auto projectLogs = "projectLogs"_L1;
-}; // namespace PackageToDesignStudio
-
 class DesignStudio : public QObject
 {
     Q_OBJECT
 public:
-    DesignStudio(QWebSocket *socket, const QString &m_deviceUuid, QObject *parent = nullptr);
+    DesignStudio(QWebSocket *socket, const QString &deviceID, QObject *parent = nullptr);
 
     // Getters
     QString ipv4Addr() const;
@@ -34,6 +19,7 @@ public:
 
     // Send data
     void sendDeviceInfo();
+    void sendProjectStarting();
     void sendProjectRunning();
     void sendProjectStopped();
     void sendProjectLogs(const QString &logs);
@@ -47,18 +33,24 @@ private:
     QTimer m_pongTimer;
 
     // DS data
-    QString m_id;
-    QString m_deviceUuid;
+    QString m_designStudioID;
+    QString m_deviceID;
 
     // project
     QByteArray m_projectData;
     int m_incomingProjectSize;
+    int m_lastPercentage;
+    QTime m_projectNotificationTime;
+    QTimer m_speedCalculator;
+    QTimer m_projectStallTimer;
 
     // DS comm
     void sendData(const QLatin1String &dataType, const QJsonValue &data = QJsonValue());
 
     // Internal
     void initPingPong();
+    void startPingPong();
+    void stopPingPong();
     void initSocket();
 
 private slots:
@@ -72,7 +64,8 @@ signals:
 
     // DS signals
     void idReceived(const QString &id, const QString &ipv4Addr);
-    void projectIncoming(const int projectSize);
+    void projectVersionMismatch(const QString &version, const QString &got);
+    void projectIncoming(const QString &id, const int projectSize);
     void projectIncomingProgress(const QString &id, const int percentage);
     void projectReceived(const QString &id, const QByteArray &data);
     void projectStopRequested(const QString &id);
diff --git a/src/backend/dsconnector/dsmanager.cpp b/src/backend/dsconnector/dsmanager.cpp
index 20cf38d012a6284677c452414d8e366c6d3dd440..e2c44b35d6a21507f2ffaecbfb83c3c4565920c8 100644
--- a/src/backend/dsconnector/dsmanager.cpp
+++ b/src/backend/dsconnector/dsmanager.cpp
@@ -76,55 +76,62 @@ void DesignStudioManager::incomingConnection()
             this,
             &DesignStudioManager::projectIncomingProgress);
 
+    connect(designStudio.data(),
+            &DesignStudio::projectVersionMismatch,
+            this,
+            &DesignStudioManager::projectVersionMismatch);
+
     connect(designStudio.data(),
             &DesignStudio::projectReceived,
             this,
-            [this, &designStudio](const QString &id, const QByteArray &project) {
-                emit projectReceived(id, project);
-            });
+            &DesignStudioManager::projectReceived);
 
     connect(designStudio.data(),
             &DesignStudio::projectStopRequested,
             this,
-            [this](const QString &id) { emit projectStopRequested(id); });
+            &DesignStudioManager::projectStopRequested);
 
     m_designStudios.append(designStudio);
     emit designStudioConnected(designStudio->id(), designStudio->ipv4Addr());
 }
 
+void DesignStudioManager::sendProjectStarting(const QString &id)
+{
+    for (const auto &designStudio : m_designStudios) {
+        if (designStudio->id() == id)
+            designStudio->sendProjectStarting();
+    }
+}
+
 void DesignStudioManager::sendProjectRunning(const QString &id)
 {
     for (const auto &designStudio : m_designStudios) {
-        if (designStudio->id() == id) {
+        if (designStudio->id() == id)
             designStudio->sendProjectRunning();
-        }
     }
 }
 
 void DesignStudioManager::sendProjectStopped(const QString &id)
 {
     for (const auto &designStudio : m_designStudios) {
-        if (designStudio->id() == id) {
+        if (designStudio->id() == id)
             designStudio->sendProjectStopped();
-        }
     }
 }
 
 void DesignStudioManager::sendProjectLogs(const QString &id, const QString &logs)
 {
     for (const auto &designStudio : m_designStudios) {
-        if (designStudio->id() == id) {
+        if (designStudio->id() == id)
             designStudio->sendProjectLogs(logs);
-        }
     }
 }
 
 QString DesignStudioManager::getDesignStudioIp(const QString &id) const
 {
     for (const auto &designStudio : m_designStudios) {
-        if (designStudio->id() == id) {
+        if (designStudio->id() == id)
             return designStudio->ipv4Addr();
-        }
     }
 
     return {};
diff --git a/src/backend/dsconnector/dsmanager.h b/src/backend/dsconnector/dsmanager.h
index de381675d52c11c70bc7567b7f701ab3c0149260..708190bb8abe7af87324d6a479c78d87779ae1da 100644
--- a/src/backend/dsconnector/dsmanager.h
+++ b/src/backend/dsconnector/dsmanager.h
@@ -16,6 +16,7 @@ public:
     void init();
 
 public slots:
+    void sendProjectStarting(const QString &id);
     void sendProjectRunning(const QString &id);
     void sendProjectStopped(const QString &id);
     void sendProjectLogs(const QString &id, const QString &logs);
@@ -35,7 +36,8 @@ private:
     void incomingConnection();
 
 signals:
-    void projectIncoming(const int &projectSize);
+    void projectVersionMismatch(const QString &expected, const QString &got);
+    void projectIncoming(const QString &id, const int &projectSize);
     void projectIncomingProgress(const QString &id, const int percentage);
     void projectReceived(const QString &id, const QByteArray &project);
     void designStudioConnected(const QString &id, const QString &ipAddr);
diff --git a/src/backend/importdummy.qml b/src/backend/importdummy.qml
index cb75b90a43c052262c8814ef6a4cad3d2af710e6..334e5ae6b8b9973c1a17d7bb6d808374aa55170b 100644
--- a/src/backend/importdummy.qml
+++ b/src/backend/importdummy.qml
@@ -25,6 +25,9 @@ import QtQuick.Studio.MultiText
 import QtQuick.Studio.Utils
 import QtQuick.Studio.DesignEffects
 
+import QtQuick.Timeline
+import QtQuick.Timeline.BlendTrees
+
 import QtQuickUltralite.Extras
 import QtQuickUltralite.Layers
 
diff --git a/src/backend/projectmanager.cpp b/src/backend/projectmanager.cpp
index acb50e386421c4e086a6b1292c9b145012bd8ca4..13fed112a687ef42958d97100043417e033db3b7 100644
--- a/src/backend/projectmanager.cpp
+++ b/src/backend/projectmanager.cpp
@@ -198,9 +198,12 @@ bool ProjectManager::isQt6Project(const QString &qmlProjectFileContent)
     return qt6ProjectMatch.hasMatch();
 }
 
-bool ProjectManager::runProject(const QByteArray &project, const bool autoScaleProject)
+bool ProjectManager::runProject(const QByteArray &project,
+                                const bool autoScaleProject,
+                                const QString &sessionId)
 {
     m_autoScaleProject = autoScaleProject;
+    m_sessionId = sessionId;
 
     const QString projectPath = unpackProject(project);
     qDebug() << "Project location: " << projectPath;
@@ -361,7 +364,7 @@ void ProjectManager::showAppWindow()
         disconnect(screen, &QScreen::orientationChanged, this, &ProjectManager::orientateWindow);
         // this signal is connected to the lambda in the backend
         // which will reset the project manager
-        emit closingProject();
+        emit closingProject(m_sessionId);
     });
 
     m_quickWindow->setFlags(Qt::Window | Qt::WindowStaysOnTopHint);
@@ -373,6 +376,7 @@ void ProjectManager::stopProject()
     if (!m_quickWindow || !m_quickWindow->isVisible())
         return;
 
+    m_sessionId.clear();
     qDebug("Stopping the QML app window");
     m_quickWindow->close();
 }
diff --git a/src/backend/projectmanager.h b/src/backend/projectmanager.h
index 5240f857f0e5b066c1fe623811015f7930c93d27..ef92360900b2e515b83610d3ed2cb952bfe5ed02 100644
--- a/src/backend/projectmanager.h
+++ b/src/backend/projectmanager.h
@@ -37,13 +37,16 @@ public:
     bool isRunning();
 
 public slots:
-    bool runProject(const QByteArray &project, const bool autoScaleProject);
+    bool runProject(const QByteArray &project,
+                    const bool autoScaleProject,
+                    const QString &sessionId);
     void stopProject();
 
 private:
     // Member variables
     QByteArray m_projectData;
     QString m_projectPath;
+    QString m_sessionId;
     bool m_autoScaleProject;
 
     // Qml related members
@@ -70,5 +73,5 @@ private:
     void showAppWindow();
 
 signals:
-    void closingProject();
+    void closingProject(const QString &sessionId);
 };