
Secure Boot and Firmware Protection in Embedded Systems
Users of embedded devices – from industrial controllers to consumer electronics – are often unaware of hidden vulnerabilities that threaten […]
Join us at Qt C++ Warsaw Meetup - 21.08.2025
Sign up for free!Hey, welcome back to another blog post. Today we’re going to talk about the new Qt WebAssembly. This post will help you understand the basics and get practical information and examples to get started quickly. We’ll cover what this is and why you should use it, and then we’ll build some cool demos together.
As a team with years of experience in Qt development — from cross-platform desktop apps to embedded systems — we’re always looking for new ways to push the technology further. If you’re considering Qt WebAssembly for your next project and need support, guidance or a development partner, feel free to contact us.
Enough chit-chat, let’s get started!
As a Qt developer I always felt that with this tech stack I can do projects for almost all target platforms, from bare metal hardware, microcontrollers to full desktop and mobile applications. I could even create a computer game 😎
There was one area that I always thought I had covered — web applications. Until recently I was under the impression that the only option was HTML+CSS+JS + [insert your favourite JS-based framework here].
Luckily I was wrong and I checked out how Qt Web Assembly works, and oh boy, now I rule them all! It took some trial and error to get here — and I’ll also highlight where you might go wrong if you’re just getting started. We’ll cover what to watch out for so you don’t repeat mine.
But before I start explaining the benefits of this approach, let me explain what the whole web assembly even is.
Before we dive in, you should learn what WebAssembly actually is — understanding this will help you make the right technical decisions later.
WebAssembly (Wasm) is a low-level, binary instruction format designed to run code in web browsers with near-native performance. It was created to address one of the key limitations of traditional web technologies: the difficulty of executing complex, computationally intensive applications efficiently within the browser environment.
Unlike JavaScript, which is interpreted and dynamically typed, WebAssembly is compiled from languages such as C, C++ or Rust into a binary format that can be loaded and executed by the browser at high speed.
At the heart of every WebAssembly application is the .wasm file. This file contains the actual code that the browser will execute. But instead of being human-readable like JavaScript or HTML, it’s a binary format—compact, efficient and designed for fast execution.
You can think of a .wasm file as the compiled version of your program, much like how C++ code is compiled into an .exe or .out file for native platforms. The difference is that .wasm is designed to run inside the browser’s WebAssembly runtime, which is built into all major modern browsers.
The .wasm file itself is produced during the build process using the Emscripten toolchain. Emscripten compiles C or C++ source code into an intermediate representation, then translates it into the WebAssembly binary format.
While WebAssembly is powerful, it’s not without its drawbacks. Before you jump into using it for production apps, consider the following:
Now that we have the theory out of the way, let’s get to something more interesting. However, we will first prepare our environment and the necessary things.
To use Qt for WebAssembly, you need:
The whole process of setting up the environment is well described in this article of the official documentation, so I won’t duplicate it and we will move on.
Now that we have the environment ready, let’s try WebAssembly.
Instead of writing an app from scratch, try opening a project you have already written before. I will open one of our demos – Brain Viewer. If you are not familiar with it, I invite you to read its case study. But in short, it’s an app I developed to display a 3D model of the human brain.
Let’s see how Web Assembly will handle this tough challenge!
Ok, so first thing is to open Qt Creator and your project. Once your app is ready, you can build it for WebAssembly directly from Qt Creator, if the Qt for WebAssembly kit is installed and configured correctly. Qt Creator simplifies the process by handling the underlying toolchain and build steps, so you can focus on development rather than low-level configuration.
After a successful build, Qt Creator will generate a set of files in your build directory:
These files can be deployed to any HTTP/HTTPS server and accessed via a modern browser. By default Qt creator runs localhost server on port 30000.
A frequent mistake is attempting to build without a properly configured WebAssembly kit or missing Emscripten from your PATH. Make sure all tools are installed and up to date. If your app fails to load, check the browser console for missing files or CORS errors.
When selecting a WebAssembly kit in Qt Creator, you may see options for single-threaded and multi-threaded builds. This choice affects how the application is compiled and how it behaves at runtime.
Use single-threaded for broader compatibility and simpler deployment, and multi-threaded if your application relies on concurrency and you can control the hosting environment.
In simple cases, the generated HTML file can be opened directly via a local server. In production, these files are often embedded into a larger web application or custom UI.
Typical integration steps:
Qt WebAssembly applications are drawn into an HTML <canvas>, managed automatically by the runtime script. The generated .html file is a basic wrapper, you can use as-is or replace with your web page – just make sure the JS runtime is loaded and a canvas element is present for the app to render into.
Note: While the auto-generated HTML is helpful, many users choose to integrate the WebAssembly module into an existing web app for more control. Make sure to document each integration step to help others learn from your experience.
For demonstration purposes, let’s assume we have a simple website and want to embed our demo on it. I wrote a minimal example of a Python HTTP server that supports cross-origin isolation, which is required for multithreaded WebAssembly:
from http.server import SimpleHTTPRequestHandler, HTTPServer class CustomHandler(SimpleHTTPRequestHandler): def end_headers(self): # Adds necessary headers for enabling WebAssembly multithreading self.send_header("Cross-Origin-Opener-Policy", "same-origin") self.send_header("Cross-Origin-Embedder-Policy", "require-corp") super().end_headers() def do_GET(self): # Serves a specific HTML file as the default entry point if self.path == '/': self.path = '/appBrainViewer.html' return super().do_GET() PORT = 8080 with HTTPServer(("", PORT), CustomHandler) as httpd: print(f"Serving at http://0.0.0.0:{PORT}") httpd.serve_forever()
This local server handles every incoming HTTP request and serves your WebAssembly files with the correct headers. It’s a great way for users to test their build locally without deploying to production.
What this does:
This script allows you to test your app locally with full WASM features enabled, including multithreading where applicable.
That’s all from today’s article. If you’re curious as to what other (perhaps as yet uncreated) platforms you can run Qt application to, then keep an eye on our blog, until next time!
We hope this article helped you find the information you were looking for. If you agree that Qt WebAssembly opens exciting new possibilities, give our demo a try or request a consult from our team.
Let's face it? It is a challenge to get top Qt QML developers on board. Help yourself and start the collaboration with Scythe Studio - real experts in Qt C++ framework.
Discover our capabilitiesUsers of embedded devices – from industrial controllers to consumer electronics – are often unaware of hidden vulnerabilities that threaten […]
Graphical user interfaces (GUIs) are becoming more and more important in embedded devices – from home appliances to medical equipment […]
Technical managers in the embedded space often face a classic challenge: integrating industrial communication protocols into modern applications. One such […]