Learn what Felgo offers to help your business succeed. Start your free evaluation today! Felgo for Your Business

Deploying Felgo Apps to the Web


Felgo allows local development and deployment for the Web with WebAssembly. WebAssembly is a bytecode representation generated from C++ code that is executed inside a virtual machine in web browsers. Most of the recent browser versions of Chrome, Firefox and Safari support running WebAssembly code.

Felgo targets WebAssembly as another Desktop platform. This allows you to target your mobile users via the app stores while running the very same app from a single source code on the Web for the desktop.

Note: Due to mobile browser support of WebAssembly, running the WebAssembly target on mobile devices is currently not intended.

This guide describes how to deploy Felgo apps & games for the Web.

Live Code Reloading on Web During development

You can test your code on the browser without any additional setup, using the Felgo Live Client for Web. You can open the Web Live Client with the "Web Client" tab within Felgo Live Server.

Add Felgo Packages for Web Platform

The Felgo installer only installs the packages for your desktop system initially. You can add other packages via the Maintenance Tool. Please note you'll need a Qt commercial license to distribute your application with Qt for WASM. Contact us here to get access to the Felgo for WASM package first.

The Maintenance Tool is located within the installation directory of your Felgo SDK. The executable is called MaintenanceTool. Run this application and select Add or remove components:

Then choose the platforms you want to add:

Build Your App or Game

Felgo for WebAssembly uses the Emscripten compiler to build C++ portable applications to target browsers with WebAssembly support.

Prepare your Project

WebAssembly builds are created statically, which means all libraries and files required by your app are packaged within the binary format for WebAssembly (.wasm).

WASM apps can only access files that are bundled via the qrc file system. In contrast to building for Desktop or the mobile platforms, you also have to add your asset files (images, fonts, etc) to the qrc file.

Therefore, make sure to add all your QML & JavaScript files and assets to your qrc file before building your project. To learn how to do that, have a look at the publishing guide.

Important: Enable RESOURCES += resources.qrc in your .pro file and set the main qml file (i.e. qrc:/qml/Main.qml) in your `main.cpp` file. `DEPLOYMENTFOLDERS` are not supported and `RESOURCES` are mandatory. If you see an empty, white page in the browser, check if you have prepared your project accordingly.

Build Your Project

Qt Creator ships with an experimental plugin to build a WASM app. Felgo recommends to build your apps from the command line, as described with the following steps:

Build on Windows

1. Open a Git Bash terminal and prepare the environment:

 # Unix separator! /c/Software instead of C:\Software
 export PATH="$PATH:<Path to your Felgo SDK>/Tools/mingw730_32/bin"
 source <Path to your Felgo SDK>/Felgo/wasm_32/emsdk/emsdk_env.sh

If a Python related error appears, turn off the Windows enforced Python alias:

2. Create your build directory outside your project folder (shadow build directory):

 mkdir build-wasm && cd build-wasm

3. Run qmake:

 <Path to your Felgo SDK>/Felgo/wasm_32/qmake <Project Path>

4. Run `make` to build the wasm file:

 mingw32-make.exe -j 5

Build on macOS and Linux

1. Open a Terminal and setup the environment:

 source <Path to your Felgo SDK>/Felgo/wasm_32/emsdk/emsdk_env.sh

2. Create a build directory outside your project folder (shadow build directory):

 mkdir build-wasm && cd build-wasm

3. Run qmake

 <Path to your Felgo SDK>/Felgo/wasm_32/bin/qmake <PROJECT_PATH>

4. Run `make` to build the wasm file

 make -j 5

Build Output

The build process will generate multiple files:

  • index.html: The default Felgo entry point of your application for the browser. You can customize the HTML to your needs
  • index.js: This file contains the WebAssembly module corresponding to your application.
  • index.wasm: The actual WebAssembly binary of your application, including all files that you added to the qrc file, i.e. QML & JavaScript files and assets like images or fonts.
  • qtloader.js: Provides APIs for application life-cycle management like the loading screen or crash and process exit handling.
  • felgo-logo.png: Splash image used for the default HTML.

Test Your App

Opening the generated index.html file directly in your web browser won’t work because loading WASM modules is only supported via a web server. To run your app, you therefore need to load it from a (local) web server.

For local testing, you can run the included web server by executing the command emrun --browser chrome index.html from within the dist folder in your terminal.

Note: You can also use Python or Ruby in your build directory to serve your build:

 [[ "$(python --version)" == "2."* ]] && python -m SimpleHTTPServer 8000 || python -m http.server 8000 -d dist
 ruby -run -e httpd -- -p 8000 dist

Publish Your App or Game to the Web

In order to publish your app or game, you need to use a static web server. Most common servers do just fine, but there are a few considerations to deliver the best user experience:

Set Content-Type header

In order for browsers to download and compile your binary files quicker, they can take advantage of streamed compilation. This only works if browsers know that they are dealing with a WebAssembly binary in advance. To tell them, you need to set the Content-Type: application/wasm header.

Enable Caching

Make sure that your server is sending the ETag and Cache-Control headers. This way, subsequent opens of the website load the wasm files from cache. A new download is only triggered if you have updated your .wasm file (you can set the highest max-age value possible for your wasm files).

Enable gzip Compression

Qt .wasm files might be a bit larger than what most users would expect. To reduce download time, enable compression at your server configuration. We suggest using gzip but you can also try brotli (bear in mind that is less widely supported). You can also compress the .wasm file beforehand using gzip, this reduces the download size up to half the original file size and therefore greatly improves the download time.


Cross Origin restrictions apply to all requests made by your application, just like those to browser-side JavaScript requests. Make sure your backend and media servers are set accordingly to your website host domain serving your app.

HTML Canvas

With the default HTML, the target canvas uses the full size of the browser window. You can modify the HTML to your needs to define a canvas that coexists with different HTML elements, like in the example illustrated below.

Current Limitations

File System and Networking

Your app runs in a sandboxed environment inside the browser that has the same restrictions as the rest of your website, such as:

  • Mixed content: If your website is hosted using HTTPS, browsers might block or warn about mixed content requests. To prevent such warnings, make sure to use HTTPS instead of HTTP for your network requests.
  • File system access:
    • There is no direct file system access to the host machine, you can access files or download from your application using the QFileDialog::getOpenFileContent() and QFileDialog::saveFileContent() C++ APIs.
    • The WebAssembly compiler provides alternatives for applications that make use of the file system:
      • MEMFS: There is an in-memory file system used for temporary file access. This API is synchronous and can be accessed with the default Qt File implementation anywhere outside the /home/web_user directory, e.g. /tmp.
      • IDBFS: There is also support for persistent file storage on top of the “Browser Indexed DB”. This file system is asynchronous and full synchronization is done before the application starts, as well as write synchronization at the end of application execution. You can use persistent storage in the /home/web_user directory provided by the IDBFS.
      • Note that MEMFS and IDBFS are emulations of a Linux/POSIX file system and do not correspond in any way to the underlying host FS, as you might expect.


Following NativeUtils QML APIs are not supported with WebAssembly:

Qt Modules

The WebAssembly platform currently does not ship with the following Qt modules and QML components:

  • DataVisualization
  • WebView
  • Multimedia: No playback of audio/video within WebAssembly

Following Qt modules can be used but functionality is not implemented for WebAssembly:

  • Location & Positioning
  • Sensors

JavaScript Environment

It is important to note that there are two different JavaScript environments in place, the one provided by the browser your app is running on and the one implemented in the QML JavaScript engine. All of your QML/JavaScript code runs inside the WebAssembly sandbox and can’t directly interact with the browser-side JavaScript, unless you write specific C++ code to handle the communication.


Due to the current implementation of Qt, WebAssembly applications report the platform as “unix” in the platform.os string. Instead of that you can use the “system.isPlatform(System.Wasm)” check in your QML code to get to know if you are running your app as a WebAssembly build.

Destructors are not called on app exit, due to the way WebAssembly main loop is implemented, C++ destructors execution is not not guaranteed on application exit.

Since the WebAssembly platform is single threaded, the implementation for the QML/JS Engine WorkerScript component is synchronous.

Nested event loops are not supported. Applications should not call e.g. QDialog::exec() or create a new QEventLoop object. Otherwise the app stops execution and you need to reload your browser.

Applications do not have access to system fonts. Font files must be distributed with the app in qrc files.

Qt renders application content to a canvas element, and does not use native DOM elements. Therefore, accessibility tools like screen readers are not supported and text inputs do not necessarily trigger virtual keyboards.

Official WebAssembly Guides

Qt_Technology_Partner_RGB_475 Qt_Service_Partner_RGB_475_padded