Skip to main content

Publish app to a static website

Introduction

Flet CLI provides flet build web and flet publish commands that allow publishing Flet app into a standalone static website (SPA) that runs entirely in the browser with Pyodide and does not require any code running on the server side.

Pyodide is a port of CPython to WebAssembly (WASM) which is an emerging technology with some limitations.

Native Python packages

Native Python packages (vs "pure" Python packages written in Python only) are packages that partially written in C, Rust or other languages producing native code. Example packages are numpy, cryptography, lxml, pydantic.

Pyodide comes with a big list of built-in packages. However, to use a Python package from PyPI it must be a pure Python package or provide a wheel with binaries built for Emscripten.

Async and threading

Flet app that published to a static website could use both sync and async event handlers and methods. Pyodide is a WebAssembly application which does not support threading. The entire Flet is running in a single thread and all sync and async control event handlers are running in the same thread. If your app has CPU-bound logic (e.g. calculating Fibonacci 😀) or "sleeps" to make UI prettier it may "hang" UI. Consider moving that logic to a server and calling it via web API. Using asyncio.sleep in async methods is OK though.

flet build web

Publish Flet app as a static website.

This is the recommended publishing method for static website.

Prerequisites

Flutter SDK must be installed on your computer for flet build web command to work.

Building website

To publish Flet app as a static website run the following command from the root of your Flet app:

flet build web

A static website is published into ./build/web directory.

Testing website

You can test a published Flet app using Python's built-in http.server module:

python -m http.server --directory build/web

Open http://localhost:8000 in your browser to check the published app.

Packaging assets

Once the website is published all files from assets directory will be copied "as is" to the root of the website.

This allows overriding such things as favicon.png or manifest.json with your own content.

URL strategy

Flet apps support two ways of configuring URL-based routing:

  • path (default) - paths are read and written without a hash. For example, fletapp.dev/path/to/view.
  • hash - paths are read and written to the hash fragment. For example, fletapp.dev/#/path/to/view.

If a hosting provider supports Single-page application (SPA) rendering you can leave default "path" URL strategy as it gives pretty URLs.

However, if a hosting provider (like GitHub Pages) doesn't support SPA mode then you need to publish your app with "hash" URL strategy.

Use --route-url-strategy argument to change URL strategy.

Web renderer

You can change default "canvaskit" web renderer (more about renderers here) to "html" with --web-renderer option:

flet build web --web-renderer html

Color emojis

To reduce app size default "CanvasKit" renderer does not use colorful emojis, because the font file with color emojies weights around 8 MB.

You can, however, opt-in for color emojis with --use-color-emoji flag:

flet build web --use-color-emoji

Alternatively, switch to html renderer which uses browser fonts.

Hosting website in a sub-directory

Multiple Flet apps can be hosted on a single domain - each app in it's own sub-directory.

To make a published Flet app work in a sub-directory you have to publish it with --base-url option:

flet build web --base-url <sub-directory>

For example, if app's URL is https://mywebsite.com/myapp then it must be published with --base-url myapp.

Splash screen

By default, generated web app will be showing a splash screen with an image from assets directory (see below) or Flet logo. You can disable splash screen for web app with --no-web-splash option.

flet publish

An alternative method to publish Flet app as a static website.

Compared to flet build web command it does not require Flutter SDK to be installed on your computer.

However, static websites built with flet build web command, compared to flet publish, have faster load time as all Python dependencies are now packaged into a single archive instead of being pulled in runtime with micropip. flet build web also detects native Python packages built into Pyodide, such as bcrypt, html5lib, numpy and many others, and installs them from Pyodide package registry.

Publish app as a static website

Run the following command to publish Flet app to a standalone website:

flet publish <your-flet-app.py>

A static website is published into ./dist directory.

Command optional arguments:

  • --pre - allow micropip to install pre-release Python packages.
  • -a ASSETS_DIR, --assets ASSETS_DIR - path to an assets directory.
  • --app-title APP_TITLE - application title.
  • --app-description APP_DESCRIPTION - application description.
  • --base-url BASE_URL - base URL for the app.
  • --web-renderer {canvaskit,html} - web renderer to use.
  • --route-url-strategy {path,hash} - URL routing strategy.

Testing website

You can test a published Flet app using Python's built-in http.server module:

python -m http.server --directory dist

Open http://localhost:8000 in your browser to check the published app.

Loading packages

You can load custom packages from PyPI during app start by listing them in requirements.txt. requirements.txt must be created in the same directory with <your-flet-app.py>.

Each line of requirements.txt contains a package name followed by an optional version specifier.

info

To install custom packages Pyodide uses micropip - a lightweight version of pip that works in a browser.

You can use Micropip API directly in your Flet app:

import sys

if sys.platform == "emscripten": # check if run in Pyodide environment
import micropip
await micropip.install("regex")

Pre-release Python packages

You can allow loading pre-release versions of PyPI packages, by adding --pre option to flet publish command:

flet publish <your-flet-app.py> --pre

Assets

If your app requires assets (images, fonts, etc.) you can copy them into website directory by using --assets <directory> option with flet publish command:

flet publish <your-flet-app.py> --assets assets
caution

If you have assets directory in your app's directory and don't specify --assets option then the contents of assets will be packaged along with a Python application rather than copied to dist.

URL strategy

Flet apps support two ways of configuring URL-based routing:

  • Path (default) - paths are read and written without a hash. For example, fletapp.dev/path/to/view.
  • Hash - paths are read and written to the hash fragment. For example, fletapp.dev/#/path/to/view.

If a hosting provider supports Single-page application (SPA) rendering you can leave default "path" URL strategy as it gives pretty URLs.

However, if a hosting provider (like GitHub Pages) doesn't support SPA mode then you need to publish your app with "hash" URL strategy.

To specify "hash" URL strategy during static app publishing use --route-url-strategy option:

flet publish <your-flet-app.py> --route-url-strategy hash

Web renderer

You can change default "canvaskit" web renderer (more about renderers here) to "html" with --web-renderer option:

flet publish <your-flet-app.py> --web-renderer html

Color emojis

To reduce app size default "CanvasKit" renderer does not use colorful emojis, because the font file with color emojies weights around 8 MB.

You can, however, opt-in for color emojis with --use-color-emoji flag:

flet publish <your-flet-app.py> --use-color-emoji

Alternatively, switch to html renderer which uses browser fonts.

Hosting website in a sub-directory

Multiple Flet apps can be hosted on a single domain - each app in it's own sub-directory.

To make a published Flet app work in a sub-directory you have to publish it with --base-url option:

flet publish <your-flet-app.py> --base-url <sub-directory>

For example, if app's URL is https://mywebsite.com/myapp then it must be published with --base-url myapp.