Skip to main content

Packaging apps for distribution

ยท 3 min read
Feodor Fitsner
Flet founder and developer

Dear friends! In the final post of this year I would like to thank you all for your contributions to Flet project whether it's spreading a word, submitting pull request, joining Discord discussion or a even sending an annoying bug report!

With your fantastic support we achieved a lot in year 2023:

  • 70+ controls (special thanks to @ndonkoHenri for his tremendous contribution).
  • 7,700 stars on GitHub.
  • 2,150 users with community moderators (thank you guys!) on Discord.
  • Flet integration with Pyodide for pure client-side Python apps - no other frameworks provide a better UI for Pyodide!
  • Flet app in AppStore and Google Play - great way to test on mobile devices and real proof of Flet apps being accepted in stores.
  • ...and finally... drum roll...๐Ÿฅ๐Ÿฅ๐Ÿฅ flet build command is here! ๐ŸŽ‰๐ŸŽ‰๐ŸŽ‰

๐ŸŽ„ "New Year" ๐ŸŽ„ edition of Flet 0.18.0 has been just released which allows packaging your Flet apps for distribution on all platforms: iOS, Android, Web, macOS, Windows and Linux!

The one command to rule them all!

The full circle is now closed: you can create (flet create), run (flet run) and build (flet build) your Flet apps with Flet CLI.

Flet CLI provides flet build command that allows packaging Flet app into a standalone executable or install package for distribution.

flet build command supersedes both flet pack (packaging into desktop app) and flet publish (packaging into a static website) commands and allows converting your Flet app into Android or iOS bundle, desktop app and a static website.

For building desktop apps flet build does not longer rely on PyInstaller like flet pack does, but uses Flutter SDK to produce a fast, offline, fully customizable (your own icons, about dialog and metadata) executable for Windows, Linux and macOS with Python runtime embedded into executable and running in-process.

Static websites built with flet build, 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.

Check Packaging app for distribution guide for complete information about flet build command.

Let us know what you think by joining Flet Discord server or creating a new thread on Flet GitHub discussions.

We wish you Happy New Year! Enjoy your holidays!

Flet for FastAPI

ยท 2 min read
Feodor Fitsner
Flet founder and developer

We've just released Flet 0.10.0 with FastAPI support!

FastAPI coupled with Uvicorn, Hypercorn, Gunicorn or other web server replaces built-in Flet web server (Fletd) to reliably run production Flet workloads.

On the other hand, seasoned FastAPI developers can use Flet to easily add interactive, real-time dashboards and admin UI to their existing or new FastAPI services.

A minimal app exampleโ€‹

import flet as ft
import flet_fastapi

async def main(page: ft.Page):
await page.add_async(
ft.Text("Hello, Flet!")
)

app = flet_fastapi.app(main)

It's a simple app that just outputs "Hello, Flet!" on a web page.

To run the app install Flet for FastAPI and Uvicorn:

pip install flet-fastapi
pip install uvicorn

Save the code above to hello.py and then start uvicorn as:

uvicorn hello:app

Open the browser and navigate to http://127.0.0.1:8000 to see the app running.

note

Flet app must be async in order to work with FastAPI WebSocket handler.

Features and benefitsโ€‹

Check the guide for complete information about Flet with FastAPI.

Let us know what you think by joining Flet Discord server or creating a new thread on Flet GitHub discussions.

Flet for Android

ยท 2 min read
Feodor Fitsner
Flet founder and developer

๐Ÿค– Android support is here!

With Flet Android app you can see how your Flet Python app looks and behaves on Android devices while the app itself is running on your computer.

Similar to iOS, Flet for Android is a Flutter app written entirely in Python with the help of two open-source packages: serious_python and flet. Resulting app package is technically compliant with Google Play requirements, so you can publish awesome Android apps in pure Python.

Follow this guide to get started with testing your Flet apps on Android. Explore the app, browse gallery, play with sample projects and app settings.

FAQโ€‹

How to package my Flet app for Google Play?โ€‹

We are going to provide a project template for bootstrap Flutter app and a guide how to combine Flutter, serious_python package and your Python app together to create a standalone Android app and publish it to Google Play.

Check serious_python's readme for instructions on how create a Flutter bootstrap and package your Python app to run within it. Use flet_example project as a starting point.

Will you provide packaging for Windows, macOS and Linux?โ€‹

Yes! At the moment Flet desktop apps are packaged with flet pack command and PyInstaller. Produced app bundle adds performance and size overhead and is hard to customize, so we are going to replace it with native Flutter packaging.

Flet v0.9.0 release notesโ€‹

For testing on Android you need to upgrade your Flet installation to v0.9.0.

There were a few changes mainly to support Android in Flet CLI. Let us know if you notice something unusual.

Enjoy!

Flet for iOS

ยท 2 min read
Feodor Fitsner
Flet founder and developer

๐ŸŽ‰ Whoo-hoo, Flet app is now on App Store! ๐ŸŽ‰

With Flet iOS app you can see how your Flet Python app looks and behaves on iPhone or iPad while the app itself is running on your computer.

But it's more than just testing Flet apps on the phone! Flet mobile app itself is written in Python and its publishing to App Store is an important milestone for the entire Flet project. It is a successful proof that you can create awesome mobile apps in Python only and package them so that they are accepted in App Store!

Follow this guide to get started with testing your Flet apps on iPhone or iPad. Explore the app, browse gallery, play with sample projects and app settings.

I would like to thank Kivy project for making a toolchain for iOS which we used to compile Python interpreter and dependencies for iOS devices. We published serious_python package for adding Python runtime to any Flutter app.

FAQโ€‹

When Android is supported?โ€‹

Soon. It has #1 priority now and we've already started working on it.

How to package my Flet app for App Store?โ€‹

We are going to provide a project template for bootstrap Flutter app and a guide how to combine Flutter, serious_python package and your Python app together to create a standalone iOS app and publish it to App Store.

Later this year we'll create a CI pipeline to fully automate the process.

Check serious_python's readme for instructions on how create a Flutter bootstrap and package your Python app to run within it. Use flet_example project as a starting point.

Flet v0.8.0 release notesโ€‹

For testing on iOS you need to upgrade your Flet installation to v0.8.0.

It's been changed a lot in v0.8.0 and there were some breaking changes. Bear with us while you are upgrading to 0.8.0 and let us know if you have any troubles with it.

Enjoy!

Scrolling controls and Theming

ยท 5 min read
Feodor Fitsner
Flet founder and developer

Flet 0.7.1 enables developers changing scroll position and receiving scroll notifications from Page, View, Column, Row, ListView and GridView controls.

The release also introduces theming improvements:

Controlling scroll positionโ€‹

Scrollable controls (Page, View, Column, Row, ListView and GridView) introduce scroll_to() method to change their scroll position to either absolute offset, relative delta or jump to the control with specified key.

Moving to a key is particularly exciting as it allows simulating the navigation between page bookmarks, kind of HTML hrefs with #:

Check the source code of the example above.

See Column.scroll_to for more details about controlling scroll position.

Receiving scroll notificationsโ€‹

All scrollable controls now provide on_scroll event handler which fires when a scroll position is changed. From event object properties you can determine whether scroll operation has started, finished, changed direction or scroll position went behind scrolling extent (overscroll). You can also get updates of the current scroll position as well as dimensions of the scroll area, for example:

import flet as ft

def main(page: ft.Page):
def on_column_scroll(e: ft.OnScrollEvent):
print(
f"Type: {e.event_type}, pixels: {e.pixels}, min_scroll_extent: {e.min_scroll_extent}, max_scroll_extent: {e.max_scroll_extent}"
)

cl = ft.Column(
spacing=10,
height=200,
width=200,
scroll=ft.ScrollMode.ALWAYS,
on_scroll=on_column_scroll,
)
for i in range(0, 50):
cl.controls.append(ft.Text(f"Text line {i}", key=str(i)))

page.add(
ft.Container(cl, border=ft.border.all(1)),
)

ft.app(main)

See Column.on_scroll for more details about scroll notification.

Check infinite scroll example.

Color scheme customizationโ€‹

Until today the only way to control color scheme for your application was specifying color_scheme_seed when creating a new ft.Theme object.

This release enables you to fine tune all 30 colors based on the Material spec and used by various Flet controls.

You can even use Material Theme Builder and apply exported color palette to your app, for example:

page.theme = ft.Theme(
color_scheme=ft.ColorScheme(
primary=ft.colors.GREEN,
primary_container=ft.colors.GREEN_200
# ...
),
)

See ColorScheme class for more details.

Nested themesโ€‹

Another awesome feature of this release is nested themes!

You can have a part of your app to use a different theme or override some theme styles for specific controls.

Remember page object having theme and theme_mode properties? Now Container has theme and theme_mode properties too!

Container.theme accepts the same ft.Theme object as a page. Specifying theme_mode in the container means you don't want to inherit parent theme, but want a completely new, unique scheme for all controls inside the container. However, if the container does not have theme_mode property set then the styles from its theme property will override the ones from the parent, inherited theme:

import flet as ft

def main(page: ft.Page):
# Yellow page theme with SYSTEM (default) mode
page.theme = ft.Theme(
color_scheme_seed=ft.colors.YELLOW,
)

page.add(
# Page theme
ft.Container(
content=ft.ElevatedButton("Page theme button"),
bgcolor=ft.colors.SURFACE_VARIANT,
padding=20,
width=300,
),

# Inherited theme with primary color overridden
ft.Container(
theme=ft.Theme(color_scheme=ft.ColorScheme(primary=ft.colors.PINK)),
content=ft.ElevatedButton("Inherited theme button"),
bgcolor=ft.colors.SURFACE_VARIANT,
padding=20,
width=300,
),

# Unique always DARK theme
ft.Container(
theme=ft.Theme(color_scheme_seed=ft.colors.INDIGO),
theme_mode=ft.ThemeMode.DARK,
content=ft.ElevatedButton("Unique theme button"),
bgcolor=ft.colors.SURFACE_VARIANT,
padding=20,
width=300,
),
)

ft.app(main)

Scrollbar themeโ€‹

You can now customize the look and fill of scrollbars in your application (or a particular scroillbar with nested themes).

It could be done via page.theme.scrollbar_theme property, for example:

page.theme = ft.Theme(
scrollbar_theme=ft.ScrollbarTheme(
track_color={
ft.MaterialState.HOVERED: ft.colors.AMBER,
ft.MaterialState.DEFAULT: ft.colors.TRANSPARENT,
},
track_visibility=True,
track_border_color=ft.colors.BLUE,
thumb_visibility=True,
thumb_color={
ft.MaterialState.HOVERED: ft.colors.RED,
ft.MaterialState.DEFAULT: ft.colors.GREY_300,
},
thickness=30,
radius=15,
main_axis_margin=5,
cross_axis_margin=10,
)
)

Text themingโ€‹

Material 3 design defines 5 groups of text styles with 3 sizes in each group: "Display", "Headline", "Title", "Label" and "Body" which are used across Flet controls. You can now customize each of those styles with page.theme.text_theme, for example:

import flet as ft

def main(page: ft.Page):
page.theme = ft.Theme(
text_theme=ft.TextTheme(body_medium=ft.TextStyle(color=ft.colors.GREEN))
)

page.add(ft.Text("Hello, green world!"))

ft.app(main)

Apparently, Body Medium is used by Text control as a default style.

See TextTheme class for more details.

Tabs themingโ€‹

You can now control the look and feel of Tabs control. In this release Tabs adds a bunch of new properties and there is a new page.theme.tabs_theme property to style all tabs in your app:

page.theme = ft.Theme(
tabs_theme=ft.TabsTheme(
divider_color=ft.colors.BLUE,
indicator_color=ft.colors.RED,
indicator_tab_size=True,
label_color=ft.colors.GREEN,
unselected_label_color=ft.colors.AMBER,
overlay_color={
ft.MaterialState.FOCUSED: ft.colors.with_opacity(0.2, ft.colors.GREEN),
ft.MaterialState.DEFAULT: ft.colors.with_opacity(0.2, ft.colors.PINK),
},
)
)

See TabsTheme class for more details.

Other changesโ€‹

Flutter 3.10โ€‹

This Flet release is based on Flutter 3.10 which brings new features, performance and size optimizations. As a result, most of Flet dependencies bumped their versions too, so if you notice any issues please let us know.

Color emoji in web appsโ€‹

Color emoji support in web apps are back! In Flutter 3.7 color emoji were disabled in "CanvasKit" renderer (default in Flet) because of their font size (8 MB!) and returned back as an opt-in in Flutter 3.10. You can enable color emoji in server-driven app with use_color_emoji argument:

ft.app(main, use_color_emoji=True)

and use --use-color-emoji switch when publishing app as a static side.

That's all for today!

Upgrade Flet module to the latest version (pip install flet --upgrade) and let us know what you think!