PackageTrack
Sign in Get early access

flet

Write entire Flutter app in Python or add server-driven UI experience into existing Flutter app.

0.86.5 19K downloads/mo #2266 most downloaded on pub.dev flet-dev/flet

What this package is like to depend on

Last release 22 days ago

01 Aug 2026

Ships fairly regularly

a new release about every 2 weeks

Nearly every release is documented

notes for 89 of 91 stable releases

1 version withdrawn

withdrawn after publishing

4 years old

92 releases · first in 2022

23 releases in the last 12 months

see the full history below

Release timeline

92 releases · Oct 2022 to Aug 2026
2023 2024 2025 2026
Release Pre-release Withdrawn

Releases

latest 60 of 92
  1. 0.86.5 01 Aug 2026
    Release notes

    Bug fixes

    • Fix every flet_ads control (BannerAd, InterstitialAd, NativeAd, ConsentManager) crashing on construction with RuntimeError: <Ad>(N) Control must be added to the page first, which made the package unusable since 0.85. The mobile-only platform guard read self.page from init(), which runs at construction — before the control is attached to the page — so the parent-chain lookup raised. The guard is back in before_update(), a post-mount hook where self.page resolves, so ads construct freely and only reject web/desktop at mount time (#6726, #6735) by @ndonkoHenri.

    Improvements

    • An Android permission set to false is now actively removed from the merged manifest instead of merely being left out of the generated one. Gradle's manifest merger folds in the manifest of every Flutter plugin and can also synthesize permissions on its own, and false previously had no effect on either — the template only skipped emitting the entry, so a plugin-contributed permission passed straight through with no way to stop it. Concretely: flet-camera pulls in camera_android_camerax, which declares WRITE_EXTERNAL_STORAGE bounded to maxSdkVersion="28", and the merger implies an unbounded READ_EXTERNAL_STORAGE from it (legacy behaviour — write once implied read). Both then appear in the Play Console despite being absent from pyproject.toml, and the unbounded read is exactly the shape Google Play's storage policy objects to. Permissions set to false now render as <uses-permission android:name="…" tools:node="remove" /> (the template's <manifest> gained the tools namespace), which strips them during the merge; removing a permission nothing declares is a harmless no-op. Verified on Flet Studio: 11 permissions down to 9, both storage entries gone from the built APK by @FeodorFitsner.

    • Bumped serious_python to 4.5.1 and re-pinned the bundled python-build snapshot to 20260730 (dart_bridge 1.7.1). serious_python 4.5.1 tracks the same python-build release, keeping PYTHON_BUILD_RELEASE_DATE in sync with its pythonReleaseDate as the pin requires by @FeodorFitsner.

    • Android ProGuard/R8 rules can now be extended from pyproject.toml via [tool.flet.android].proguard_rules. The generated project's android/app/proguard-rules.pro was a fixed template file, so an app that needed an extra keep rule had no way to add one short of downloading the published build template, patching the file and passing --template. This matters for Pyjnius: autoclass() resolves Java classes by name at runtime, and R8 renames anything in the APK that isn't kept — so autoclass() on a class bundled by a Flutter plugin or by your own Java/Kotlin fails in release builds. It fails hard: JNI FindClass returns null and the process aborts with JNI DETECTED ERROR IN APPLICATION: obj == null / SIGABRT rather than raising a catchable Python exception, and because R8 only runs in release builds it never reproduces in debug. Android framework classes (android.os.Build and friends) live outside the APK and never needed a rule. Rules are appended to the defaults, since R8 has no directive that undoes a keep; to remove the defaults instead — in particular -keepnames class * { *; }, which keeps every class and member name in the app and costs 2.5 MB of classes.dex on Flet Studio (5.9 MB → 3.4 MB, -43%) — set [tool.flet.android].proguard_default_rules = false. Dropping the defaults is safe for Pyjnius's PythonActivity access, because serious_python_android 4.1.0+ ships that keep rule in its own consumer-rules.pro. Defaults are unchanged, so existing builds render exactly the same file by @FeodorFitsner.

    • Android Gradle properties can now be configured from pyproject.toml via [tool.flet.android.gradle_properties]. The generated project's android/gradle.properties was previously fixed, so its memory settings — org.gradle.jvmargs=-Xmx8G plus a 4 GB metaspace — could not be changed. That is larger than the total RAM of a standard GitHub-hosted runner (measured: 7.8 GB with 3 GB of swap), so release builds, which additionally run Dart AOT once per ABI and R8, could exhaust memory and stall with no error; the only workaround was to download the published build template, patch the file and pass --template. Entries in the table override the defaults or add new properties, e.g. "org.gradle.jvmargs" = "-Xmx3G -XX:MaxMetaspaceSize=1G" and "org.gradle.workers.max" = 2. Defaults are unchanged, so existing builds render exactly the same file by @FeodorFitsner.

    Full Changelog: v0.86.4...v0.86.5

    Open source →
    Release notes

    Bug fixes

    • Fix every flet_ads control (BannerAd, InterstitialAd, NativeAd, ConsentManager) crashing on construction with RuntimeError: <Ad>(N) Control must be added to the page first, which made the package unusable since 0.85. The mobile-only platform guard read self.page from init(), which runs at construction — before the control is attached to the page — so the parent-chain lookup raised. The guard is back in before_update(), a post-mount hook where self.page resolves, so ads construct freely and only reject web/desktop at mount time (#6726, #6735) by @ndonkoHenri.

    Improvements

    • An Android permission set to false is now actively removed from the merged manifest instead of merely being left out of the generated one. Gradle's manifest merger folds in the manifest of every Flutter plugin and can also synthesize permissions on its own, and false previously had no effect on either — the template only skipped emitting the entry, so a plugin-contributed permission passed straight through with no way to stop it. Concretely: flet-camera pulls in camera_android_camerax, which declares WRITE_EXTERNAL_STORAGE bounded to maxSdkVersion="28", and the merger implies an unbounded READ_EXTERNAL_STORAGE from it (legacy behaviour — write once implied read). Both then appear in the Play Console despite being absent from pyproject.toml, and the unbounded read is exactly the shape Google Play's storage policy objects to. Permissions set to false now render as <uses-permission android:name="…" tools:node="remove" /> (the template's <manifest> gained the tools namespace), which strips them during the merge; removing a permission nothing declares is a harmless no-op. Verified on Flet Studio: 11 permissions down to 9, both storage entries gone from the built APK (#6742) by @FeodorFitsner.

    • Bumped serious_python to 4.5.1 and re-pinned the bundled python-build snapshot to 20260730 (dart_bridge 1.7.1). serious_python 4.5.1 tracks the same python-build release, keeping PYTHON_BUILD_RELEASE_DATE in sync with its pythonReleaseDate as the pin requires (#6742) by @FeodorFitsner.

    • Android ProGuard/R8 rules can now be extended from pyproject.toml via [tool.flet.android].proguard_rules. The generated project's android/app/proguard-rules.pro was a fixed template file, so an app that needed an extra keep rule had no way to add one short of downloading the published build template, patching the file and passing --template. This matters for Pyjnius: autoclass() resolves Java classes by name at runtime, and R8 renames anything in the APK that isn't kept — so autoclass() on a class bundled by a Flutter plugin or by your own Java/Kotlin fails in release builds. It fails hard: JNI FindClass returns null and the process aborts with JNI DETECTED ERROR IN APPLICATION: obj == null / SIGABRT rather than raising a catchable Python exception, and because R8 only runs in release builds it never reproduces in debug. Android framework classes (android.os.Build and friends) live outside the APK and never needed a rule. Rules are appended to the defaults, since R8 has no directive that undoes a keep; to remove the defaults instead — in particular -keepnames class * { *; }, which keeps every class and member name in the app and costs 2.5 MB of classes.dex on Flet Studio (5.9 MB → 3.4 MB, -43%) — set [tool.flet.android].proguard_default_rules = false. Dropping the defaults is safe for Pyjnius's PythonActivity access, because serious_python_android 4.1.0+ ships that keep rule in its own consumer-rules.pro. Defaults are unchanged, so existing builds render exactly the same file (#6741) by @FeodorFitsner.

    • Android Gradle properties can now be configured from pyproject.toml via [tool.flet.android.gradle_properties]. The generated project's android/gradle.properties was previously fixed, so its memory settings — org.gradle.jvmargs=-Xmx8G plus a 4 GB metaspace — could not be changed. That is larger than the total RAM of a standard GitHub-hosted runner (measured: 7.8 GB with 3 GB of swap), so release builds, which additionally run Dart AOT once per ABI and R8, could exhaust memory and stall with no error; the only workaround was to download the published build template, patch the file and pass --template. Entries in the table override the defaults or add new properties, e.g. "org.gradle.jvmargs" = "-Xmx3G -XX:MaxMetaspaceSize=1G" and "org.gradle.workers.max" = 2. Defaults are unchanged, so existing builds render exactly the same file (#6732, #6733) by @FeodorFitsner.

    Open source →
    Release notes

    No changes in the flet Dart package; version bumped for release coordination with configurable Android gradle.properties on the Python side (#6733).

    Open source →
  2. 0.86.4 27 Jul 2026
    Release notes

    Bug fixes

    • Fix services registered after an embedded FletApp is opened never becoming usable on the host page — calling one failed with Timeout waiting for invoke method listener for <Service>(id).<method>. ServiceRegistry subclasses Service, so it registered itself on construction; when an embedded app's page built its own registry while the host page was still the current context, the embedded registry was registered as a service inside the host's registry. The client has no binding for a control of type ServiceRegistry, so building it threw Unknown service inside the host's service loop and aborted it, leaving every service positioned after that entry unbound — permanently, since the entry stays in the list. A registry is the container for services, not a service, so it no longer self-registers; the client-side loop also isolates per-service failures now, so a single unbuildable entry can't stop the rest from binding. Reproduced with a host app embedding a FletApp and registering a Clipboard afterwards by @FeodorFitsner.

    Full Changelog: v0.86.3...v0.86.4

    Open source →
    Release notes

    Bug fixes

    • Fix services registered after an embedded FletApp is opened never becoming usable on the host page — calling one failed with Timeout waiting for invoke method listener for <Service>(id).<method>. ServiceRegistry subclasses Service, so it registered itself on construction; when an embedded app's page built its own registry while the host page was still the current context, the embedded registry was registered as a service inside the host's registry. The client has no binding for a control of type ServiceRegistry, so building it threw Unknown service inside the host's service loop and aborted it, leaving every service positioned after that entry unbound — permanently, since the entry stays in the list. A registry is the container for services, not a service, so it no longer self-registers; the client-side loop also isolates per-service failures now, so a single unbuildable entry can't stop the rest from binding. Reproduced with a host app embedding a FletApp and registering a Clipboard afterwards (#6728) by @FeodorFitsner.
    Open source →
    Release notes
    • Isolate per-service failures when building the page's service registry. ServiceBinding throws Unknown service for a control type no extension can build, and that exception escaping ServiceRegistry._onServicesUpdated() aborted the whole loop, so every service after the offending entry was silently never bound and later invokeMethod calls on them hung until they timed out. Each binding is now built independently and a failure is logged and skipped. Also rebuilds the registry when the _services control instance is replaced (not just when its uid changes), matching how the window service tracks its control by identity.
    Open source →
  3. 0.86.3 26 Jul 2026
    Release notes

    Improvements

    • An embedded FletApp can now run over the in-process dart_bridge transport instead of a socket. Set url="dartbridge://" and the client allocates a native channel, delivers its port through the new FletApp.on_connect event, and the host serves that port with a FletDartBridgeServer — so a Flet program hosted inside another Flet app (a gallery, a preview) exchanges messages at memcpy speed with no socket file, no TCP port, and no AF_UNIX path-length limit (which broke embedded apps on the iOS simulator, where the container path overflows sun_path). High-throughput DataChannels used by embedded apps (RawImage, MatplotlibChart) get their own dedicated bridge too. The transport is opt-in and falls back to the existing URL-scheme channels: on web and desktop dev builds, where dart_bridge is unavailable, hosts keep using a socket URL by @FeodorFitsner.

    • flet run can now pass custom arguments to your app script: everything after a -- separator is forwarded to the script instead of being parsed by Flet, and arrives there as sys.argv[1:] - e.g. flet run --web main.py -- --dataset big.csv --verbose. Previously there was no way to do this: the app was always launched as python -u <script> with no extra arguments, so a flag meant for the app was consumed by the CLI's own parser and rejected with flet: error: unrecognized arguments: --verbose. The arguments are re-applied on every hot reload and work in all run modes (desktop, --web, --ios, --android, and -m module invocations). Arguments that don't look like options can be passed without the separator (flet run main.py big.csv), and mistyped Flet options are still reported as errors - now with a hint to use -- when they were meant for the app. See Passing arguments to your app by @FeodorFitsner.

    Bug fixes

    • Fix iOS apps built with flet build ipa crashing at startup with Failed to lookup symbol 'serious_python_run': dlsym(RTLD_DEFAULT, serious_python_run): symbol not found. serious_python shipped dart_bridge — which provides the in-process Dart↔Python transport — as a static library linked into the app executable. An iOS executable exports nothing to the dynamic symbol table by default and the release build strips local symbols, so the dlsym lookups that Dart (DynamicLibrary.process()) and Python (import dart_bridge) perform at runtime could not resolve. Only release/archive (device) builds under the Swift Package Manager path were affected — debug and simulator builds don't dead-strip, so the failure did not reproduce there, and Android was never affected (its dart_bridge is a dynamic .so, which exports its symbols). Bumps serious_python to 4.4.0, which ships dart_bridge as a dynamic framework — embedded and signed into the app like Python.xcframework, with its symbols exported — and re-pins the bundled python-build snapshot to 20260726 (dart_bridge 1.5.1 → 1.6.1, Pyodide 3.14 314.0.2 → 314.0.3); the bundled Python versions (3.12.13 / 3.13.14 / 3.14.6) are unchanged by @FeodorFitsner.

    • Fix MatplotlibChart freezing permanently when its platform view is disposed with a frame in flight — the common trigger is switching to another tab inside the app, which races the frame stream: DataChannel.send on a disposed channel silently drops, so the frame's [0xFF] frame-applied ack never arrives and _send_and_wait's unbounded await parks MatplotlibChart._receive_loop — the sole consumer of the frame queue — for the rest of the session, with no exception raised; remounting opens a fresh channel but the stale ack futures were never resolved, so the chart stayed frozen. _capture_channel now resolves all pending ack futures when a new channel is captured (a fresh channel means every pending ack belongs to the disposed one), unparking the producer instantly on remount, and the ack await is bounded by FRAME_ACK_TIMEOUT (5s; a healthy ack lands in milliseconds) — on expiry the frame is dropped and its future removed from the ack FIFO so subsequent acks keep resolving the right entries (#6709, #6710) by @ForsakenDurian.

    • Fix a system/edge-swipe back gesture exiting the whole host app instead of navigating back when it lands on an embedded FletApp (an app rendered inside another Flet app — e.g. a gallery host running example apps in-process). The embedded app's WidgetsApp (MaterialApp/CupertinoApp) ran the default NavigationNotification handler, which reported SystemNavigator.setFrameworkHandlesBack(false) for a nested app that couldn't pop (typically a single-view example) and swallowed the notification, so the OS finished the whole activity on back and the host never got to report that it could pop. An embedded page now lets that notification bubble to the host (which re-reports canHandlePop) and chains a ChildBackButtonDispatcher to the host Router, so a system back propagates to the host and pops the view that embeds it by @FeodorFitsner.

    • Fix page.window.maximized = True intermittently reverting to unmaximized right after startup on macOS, when set in the same patch as page.title (e.g. page.title = "My App"; page.window.maximized = True in main()) by @davidlawson.

    • Fix flet build picking a non-decodable icon/splash image when several files share a base name, producing a machine-dependent NoDecoderForImageFormatException from flutter_launcher_icons. When an app's assets held, say, both icon.png and icon.svg, find_platform_image selected the first match from glob.glob(...) — whose order is filesystem-dependent — so the same app could pick icon.png on one machine and icon.svg on another (SVG is vector and can't be decoded by the raster icon/splash generators), turning a working build into a crash purely based on directory listing order. Candidates are now filtered to formats the generators can actually decode (.svg is dropped everywhere; .icns stays macOS-only and .ico Windows-only) and ranked so a raster image (.png first) always wins, making the choice deterministic across machines. When the only supplied image is an SVG (no raster sibling), it's skipped with a build-log warning and the default Flet icon is used instead of crashing by @FeodorFitsner.

    • Fix modal controls (AlertDialog, CupertinoAlertDialog, BottomSheet, CupertinoBottomSheet) crashing to a black screen with "setState()/markNeedsBuild() called during build" when they close in the same frame that another route or overlay opens — e.g. dismissing a bottom sheet and showing a SnackBar from one handler. The close path popped the route synchronously during build, so the exit animation notified a listener that was mid-build. Each modal now tracks its own ModalRoute and closes it in a post-frame callback, popping that route (never the topmost one); View's confirm-pop pops its own route too, so a modal dismissed in the same tick as a view pop can no longer dismiss the wrong one by @FeodorFitsner.

    Full Changelog: v0.86.2...v0.86.3

    Open source →
    Release notes

    Improvements

    • An embedded FletApp can now run over the in-process dart_bridge transport instead of a socket. Set url="dartbridge://" and the client allocates a native channel, delivers its port through the new FletApp.on_connect event, and the host serves that port with a FletDartBridgeServer — so a Flet program hosted inside another Flet app (a gallery, a preview) exchanges messages at memcpy speed with no socket file, no TCP port, and no AF_UNIX path-length limit (which broke embedded apps on the iOS simulator, where the container path overflows sun_path). High-throughput DataChannels used by embedded apps (RawImage, MatplotlibChart) get their own dedicated bridge too. The transport is opt-in and falls back to the existing URL-scheme channels: on web and desktop dev builds, where dart_bridge is unavailable, hosts keep using a socket URL (#6723) by @FeodorFitsner.

    • flet run can now pass custom arguments to your app script: everything after a -- separator is forwarded to the script instead of being parsed by Flet, and arrives there as sys.argv[1:] - e.g. flet run --web main.py -- --dataset big.csv --verbose. Previously there was no way to do this: the app was always launched as python -u <script> with no extra arguments, so a flag meant for the app was consumed by the CLI's own parser and rejected with flet: error: unrecognized arguments: --verbose. The arguments are re-applied on every hot reload and work in all run modes (desktop, --web, --ios, --android, and -m module invocations). Arguments that don't look like options can be passed without the separator (flet run main.py big.csv), and mistyped Flet options are still reported as errors - now with a hint to use -- when they were meant for the app. See Passing arguments to your app (#6721) by @FeodorFitsner.

    Bug fixes

    • Fix iOS apps built with flet build ipa crashing at startup with Failed to lookup symbol 'serious_python_run': dlsym(RTLD_DEFAULT, serious_python_run): symbol not found. serious_python shipped dart_bridge — which provides the in-process Dart↔Python transport — as a static library linked into the app executable. An iOS executable exports nothing to the dynamic symbol table by default and the release build strips local symbols, so the dlsym lookups that Dart (DynamicLibrary.process()) and Python (import dart_bridge) perform at runtime could not resolve. Only release/archive (device) builds under the Swift Package Manager path were affected — debug and simulator builds don't dead-strip, so the failure did not reproduce there, and Android was never affected (its dart_bridge is a dynamic .so, which exports its symbols). Bumps serious_python to 4.4.0, which ships dart_bridge as a dynamic framework — embedded and signed into the app like Python.xcframework, with its symbols exported — and re-pins the bundled python-build snapshot to 20260727 (dart_bridge 1.5.1 → 1.6.1, Pyodide 3.14 314.0.2 → 314.0.3); the bundled Python versions (3.12.13 / 3.13.14 / 3.14.6) are unchanged (#6723) by @FeodorFitsner.

    • Fix MatplotlibChart freezing permanently when its platform view is disposed with a frame in flight — the common trigger is switching to another tab inside the app, which races the frame stream: DataChannel.send on a disposed channel silently drops, so the frame's [0xFF] frame-applied ack never arrives and _send_and_wait's unbounded await parks MatplotlibChart._receive_loop — the sole consumer of the frame queue — for the rest of the session, with no exception raised; remounting opens a fresh channel but the stale ack futures were never resolved, so the chart stayed frozen. _capture_channel now resolves all pending ack futures when a new channel is captured (a fresh channel means every pending ack belongs to the disposed one), unparking the producer instantly on remount, and the ack await is bounded by FRAME_ACK_TIMEOUT (5s; a healthy ack lands in milliseconds) — on expiry the frame is dropped and its future removed from the ack FIFO so subsequent acks keep resolving the right entries (#6709, #6710) by @ForsakenDurian.

    • Fix a system/edge-swipe back gesture exiting the whole host app instead of navigating back when it lands on an embedded FletApp (an app rendered inside another Flet app — e.g. a gallery host running example apps in-process). The embedded app's WidgetsApp (MaterialApp/CupertinoApp) ran the default NavigationNotification handler, which reported SystemNavigator.setFrameworkHandlesBack(false) for a nested app that couldn't pop (typically a single-view example) and swallowed the notification, so the OS finished the whole activity on back and the host never got to report that it could pop. An embedded page now lets that notification bubble to the host (which re-reports canHandlePop) and chains a ChildBackButtonDispatcher to the host Router, so a system back propagates to the host and pops the view that embeds it (#6715) by @FeodorFitsner.

    • Fix page.window.maximized = True intermittently reverting to unmaximized right after startup on macOS, when set in the same patch as page.title (e.g. page.title = "My App"; page.window.maximized = True in main()) (#6712) by @davidlawson.

    • Fix flet build picking a non-decodable icon/splash image when several files share a base name, producing a machine-dependent NoDecoderForImageFormatException from flutter_launcher_icons. When an app's assets held, say, both icon.png and icon.svg, find_platform_image selected the first match from glob.glob(...) — whose order is filesystem-dependent — so the same app could pick icon.png on one machine and icon.svg on another (SVG is vector and can't be decoded by the raster icon/splash generators), turning a working build into a crash purely based on directory listing order. Candidates are now filtered to formats the generators can actually decode (.svg is dropped everywhere; .icns stays macOS-only and .ico Windows-only) and ranked so a raster image (.png first) always wins, making the choice deterministic across machines. When the only supplied image is an SVG (no raster sibling), it's skipped with a build-log warning and the default Flet icon is used instead of crashing (#6707) by @FeodorFitsner.

    • Fix modal controls (AlertDialog, CupertinoAlertDialog, BottomSheet, CupertinoBottomSheet) crashing to a black screen with "setState()/markNeedsBuild() called during build" when they close in the same frame that another route or overlay opens — e.g. dismissing a bottom sheet and showing a SnackBar from one handler. The close path popped the route synchronously during build, so the exit animation notified a listener that was mid-build. Each modal now tracks its own ModalRoute and closes it in a post-frame callback, popping that route (never the topmost one); View's confirm-pop pops its own route too, so a modal dismissed in the same tick as a view pop can no longer dismiss the wrong one (#6714) by @FeodorFitsner.

    Open source →
    Release notes
    • Fix a system/edge-swipe back gesture exiting the whole host app instead of navigating back when it lands on an embedded FletApp (an app rendered inside another Flet app — e.g. a gallery host running example apps in-process). The embedded app's WidgetsApp (MaterialApp/CupertinoApp) ran the default NavigationNotification handler, which reported SystemNavigator.setFrameworkHandlesBack(false) for a nested app that couldn't pop (typically a single-view example) and swallowed the notification, so the OS finished the whole activity on back and the host never got to report that it could pop. An embedded page now lets that notification bubble to the host (which re-reports canHandlePop) and chains a ChildBackButtonDispatcher to the host Router, so a system back propagates to the host and pops the view that embeds it.
    • Fix modal controls (AlertDialog, CupertinoAlertDialog, BottomSheet, CupertinoBottomSheet) throwing "setState()/markNeedsBuild() called during build" and blanking the screen when closed in the same frame another route/overlay opens (e.g. a SnackBar). Each modal now tracks its own ModalRoute and closes it via a post-frame closeModalRoute() that pops that specific route; View's confirm-pop pops its own route too, removing the wrong-route race between a dismissing modal and a view pop.
    Open source →
  4. 0.86.2 22 Jul 2026
    Release notes

    Bug fixes

    • Fix code edits not taking effect under flet debug android: after re-running the command, the app kept executing the previously-unpacked, stale code instead of your changes. flet debug rebuilds and reinstalls the same-version APK on each iteration (flutter run does an update install that preserves app data), and serious_python's on-device extraction cache — keyed only on versionName+versionCode — never saw the version change, so it skipped re-unpacking the new app.zip. Bumps serious_python to 4.3.4, which folds the APK's lastUpdateTime into that cache key so every (re)install re-extracts the current code while ordinary relaunches still hit the cache. flet build apk was never affected (#6682) by @FeodorFitsner.
    • Fix an embedded FletApp (an app rendered inside another Flet app — e.g. a preview or gallery host that runs example apps in-process) not refreshing its UI in response to events. Auto-update mode was tracked as components_mode on a single process-global context singleton, so a host app that rendered via page.render/page.render_views turned components mode on process-wide and context.auto_update_enabled() then returned False for the embedded app too — any handler that mutated a control without calling .update() (the common imperative style, including all page.services sensor readings) silently never re-rendered. Event dispatch also ran in a fresh task whose page context var could carry a different session's page, so context-derived state resolved against the wrong session. components_mode is now stored per-Session, and Session.dispatch_event binds the page context to its own session before invoking handlers, so multiple Flet apps sharing one process keep independent update behavior by @FeodorFitsner.
    • Modernize examples for 0.86: replace the removed TextField.error_text with error (chat tutorial, mind_queue, palette_editor), and declare the device permissions each sensor example needs to run on-device — NSMotionUsageDescription on iOS for the motion/barometer sensors and android.permission.VIBRATE for HapticFeedback by @FeodorFitsner.
    • Fix opening a flet run --ios / --android app URL in a desktop browser: the page loaded but stayed on the boot screen, endlessly retrying a WebSocket connection to ws://<host>:<port>/ws. Mobile-mode apps are mounted under a non-root path (e.g. /counter/main.py), so the real WebSocket route lives at /counter/main.py/ws - but since 1.0 Alpha the FastAPI wrapper always passed the bare default ws endpoint name into FletStaticFiles, bypassing its mount-path-aware fallback, and index.html got patched with flet.webSocketEndpoint="ws", which the web client resolves against the server root. The native iOS/Android client derives the path from the page URL and was unaffected. A relative WebSocket endpoint is now resolved against the app mount path when patching index.html, fixing browser access to any Flet web app mounted under a non-root path (--ios/--android, flet run --name, or a flet_web.fastapi app mounted at a sub-path) by @FeodorFitsner.
    • Fix web RawImage and MatplotlibChart animations flooding the console with uncatchable engine exceptions (and breaking the animation) after the browser tab was backgrounded for a while and then refocused. On Flet web the frame producer runs in a Pyodide worker (or on a remote server over a WebSocket) that the browser never throttles, while the client's Flutter frame pipeline is suspended whenever the tab is hidden - so setState schedules frames that never paint and the post-frame callbacks that dispose replaced ui.Images never fire. Decoded images and pending disposals then pile up unbounded in the Dart heap and flush into the engine all at once on resume, one exception per queued frame. This is a client-side accumulation independent of transport, so it also affected native windows minimized with an animation running. Fixed in two layers: (1) a shared FrameStreamVisibility client-side mixin - used by both RawImage and flet-charts' MatplotlibChartCanvas - stops decoding/uploading and frees replaced images immediately while hidden (keeping only cheap offscreen state up to date, so incremental matplotlib diffs stay correct), then presents just the latest frame on resume; (2) a new page.wait_until_visible() gate (driven by on_app_lifecycle_state_change, alongside a page.app_visible property) that the streaming controls await internally, so producer loops park while hidden instead of rendering frames a suspended client can only discard (#6691) by @FeodorFitsner.
    • Fix flet build / flet publish flooding non-interactive logs (CI, cloud build, any piped stdout) with thousands of progress-spinner frames, and fix the --no-rich-output flag not actually producing plain output. The CLI's rich Console was created with force_terminal=True whenever the FLET_CLI_NO_RICH_OUTPUT env var was unset, which forces the Live status spinner to repaint even when stdout isn't a TTY — so in a pipe every animation frame lands on its own line (e.g. hundreds of ( ● ) Initializing web build... lines). And the --no-rich-output CLI flag never reached that console at all: it's parsed per-command, after the module-level console is already built, so it only suppressed emojis while color and the spinner kept going. Now the console auto-detects the terminal (force_terminal=None) — interactive terminals keep the animated spinner while piped output stays quiet — and both FLET_CLI_NO_RICH_OUTPUT and --no-rich-output (detected from sys.argv at import) force fully plain output by @FeodorFitsner.

    Improvements

    • Flutter updated to 3.44.7.
    • Fix flet_video.Video resetting its volume (and pitch, playback_rate, shuffle_playlist, playlist_mode, subtitle_track) to the player's defaults after toggling visible off then on — e.g. volume jumped back to 100. Hiding a Video disposes its native media_kit player and showing it recreates a fresh one at default settings; the "last-applied" tracking now lives with the player (not the persistent control model) and is reset on recreation, so build() re-applies every setting to the new player (#6683, #6694) by @ndonkoHenri.
    • Fix SearchBar.on_tap_outside_bar not firing when the user tapped outside the open search view. That case now has a dedicated SearchBar.on_tap_outside_view event (fired when tapping outside the open view, e.g. to dismiss it), and on_tap_outside_bar is documented to match what it actually does: fire while the bar is focused and the view is closed, like TextField.on_tap_outside (#6593, #6697) by @ndonkoHenri.
    • Add a --android-legacy-packaging flag (and [tool.flet.android].legacy_packaging setting) to flet build apk/aab for opting into legacy Android native-library packaging. By default (modern packaging), native .so files are stored uncompressed and page-aligned in the APK and memory-mapped directly at runtime, which typically gives a smaller install and Play Store download but a larger raw .apk file. Enabling this option sets useLegacyPackaging = true so the .so are compressed inside the APK and extracted to disk on install: the raw .apk file is smaller (handy when side-loading), at the cost of a larger on-device install and slower native-library loading. The extraction directory is exposed to Python as ANDROID_NATIVE_LIBRARY_DIR, which can help custom native-library consumers that require a real filesystem path. See Native library packaging by @FeodorFitsner.

    Full Changelog: v0.86.1...v0.86.2

    Open source →
    Release notes

    Bug fixes

    • Fix code edits not taking effect under flet debug android: after re-running the command, the app kept executing the previously-unpacked, stale code instead of your changes. flet debug rebuilds and reinstalls the same-version APK on each iteration (flutter run does an update install that preserves app data), and serious_python's on-device extraction cache — keyed only on versionName+versionCode — never saw the version change, so it skipped re-unpacking the new app.zip. Bumps serious_python to 4.3.4, which folds the APK's lastUpdateTime into that cache key so every (re)install re-extracts the current code while ordinary relaunches still hit the cache. flet build apk was never affected (#6682) by @FeodorFitsner.
    • Fix an embedded FletApp (an app rendered inside another Flet app — e.g. a preview or gallery host that runs example apps in-process) not refreshing its UI in response to events. Auto-update mode was tracked as components_mode on a single process-global context singleton, so a host app that rendered via page.render/page.render_views turned components mode on process-wide and context.auto_update_enabled() then returned False for the embedded app too — any handler that mutated a control without calling .update() (the common imperative style, including all page.services sensor readings) silently never re-rendered. Event dispatch also ran in a fresh task whose page context var could carry a different session's page, so context-derived state resolved against the wrong session. components_mode is now stored per-Session, and Session.dispatch_event binds the page context to its own session before invoking handlers, so multiple Flet apps sharing one process keep independent update behavior (#6699) by @FeodorFitsner.
    • Modernize examples for 0.86: replace the removed TextField.error_text with error (chat tutorial, mind_queue, palette_editor), and declare the device permissions each sensor example needs to run on-device — NSMotionUsageDescription on iOS for the motion/barometer sensors and android.permission.VIBRATE for HapticFeedback (#6699) by @FeodorFitsner.
    • Fix opening a flet run --ios / --android app URL in a desktop browser: the page loaded but stayed on the boot screen, endlessly retrying a WebSocket connection to ws://<host>:<port>/ws. Mobile-mode apps are mounted under a non-root path (e.g. /counter/main.py), so the real WebSocket route lives at /counter/main.py/ws - but since 1.0 Alpha the FastAPI wrapper always passed the bare default ws endpoint name into FletStaticFiles, bypassing its mount-path-aware fallback, and index.html got patched with flet.webSocketEndpoint="ws", which the web client resolves against the server root. The native iOS/Android client derives the path from the page URL and was unaffected. A relative WebSocket endpoint is now resolved against the app mount path when patching index.html, fixing browser access to any Flet web app mounted under a non-root path (--ios/--android, flet run --name, or a flet_web.fastapi app mounted at a sub-path) (#6699) by @FeodorFitsner.
    • Fix web RawImage and MatplotlibChart animations flooding the console with uncatchable engine exceptions (and breaking the animation) after the browser tab was backgrounded for a while and then refocused. On Flet web the frame producer runs in a Pyodide worker (or on a remote server over a WebSocket) that the browser never throttles, while the client's Flutter frame pipeline is suspended whenever the tab is hidden - so setState schedules frames that never paint and the post-frame callbacks that dispose replaced ui.Images never fire. Decoded images and pending disposals then pile up unbounded in the Dart heap and flush into the engine all at once on resume, one exception per queued frame. This is a client-side accumulation independent of transport, so it also affected native windows minimized with an animation running. Fixed in two layers: (1) a shared FrameStreamVisibility client-side mixin - used by both RawImage and flet-charts' MatplotlibChartCanvas - stops decoding/uploading and frees replaced images immediately while hidden (keeping only cheap offscreen state up to date, so incremental matplotlib diffs stay correct), then presents just the latest frame on resume; (2) a new page.wait_until_visible() gate (driven by on_app_lifecycle_state_change, alongside a page.app_visible property) that the streaming controls await internally, so producer loops park while hidden instead of rendering frames a suspended client can only discard (#6691) by @FeodorFitsner.
    • Fix flet build / flet publish flooding non-interactive logs (CI, cloud build, any piped stdout) with thousands of progress-spinner frames, and fix the --no-rich-output flag not actually producing plain output. The CLI's rich Console was created with force_terminal=True whenever the FLET_CLI_NO_RICH_OUTPUT env var was unset, which forces the Live status spinner to repaint even when stdout isn't a TTY — so in a pipe every animation frame lands on its own line (e.g. hundreds of ( ● ) Initializing web build... lines). And the --no-rich-output CLI flag never reached that console at all: it's parsed per-command, after the module-level console is already built, so it only suppressed emojis while color and the spinner kept going. Now the console auto-detects the terminal (force_terminal=None) — interactive terminals keep the animated spinner while piped output stays quiet — and both FLET_CLI_NO_RICH_OUTPUT and --no-rich-output (detected from sys.argv at import) force fully plain output (#6704) by @FeodorFitsner.

    Improvements

    • Flutter updated to 3.44.7.
    • Fix flet_video.Video resetting its volume (and pitch, playback_rate, shuffle_playlist, playlist_mode, subtitle_track) to the player's defaults after toggling visible off then on — e.g. volume jumped back to 100. Hiding a Video disposes its native media_kit player and showing it recreates a fresh one at default settings; the "last-applied" tracking now lives with the player (not the persistent control model) and is reset on recreation, so build() re-applies every setting to the new player (#6683, #6694) by @ndonkoHenri.
    • Fix SearchBar.on_tap_outside_bar not firing when the user tapped outside the open search view. That case now has a dedicated SearchBar.on_tap_outside_view event (fired when tapping outside the open view, e.g. to dismiss it), and on_tap_outside_bar is documented to match what it actually does: fire while the bar is focused and the view is closed, like TextField.on_tap_outside (#6593, #6697) by @ndonkoHenri.
    • Add a --android-legacy-packaging flag (and [tool.flet.android].legacy_packaging setting) to flet build apk/aab for opting into legacy Android native-library packaging. By default (modern packaging), native .so files are stored uncompressed and page-aligned in the APK and memory-mapped directly at runtime, which typically gives a smaller install and Play Store download but a larger raw .apk file. Enabling this option sets useLegacyPackaging = true so the .so are compressed inside the APK and extracted to disk on install: the raw .apk file is smaller (handy when side-loading), at the cost of a larger on-device install and slower native-library loading. The extraction directory is exposed to Python as ANDROID_NATIVE_LIBRARY_DIR, which can help custom native-library consumers that require a real filesystem path. See Native library packaging (#6698, #6703) by @FeodorFitsner.
    Open source →
    Release notes
    Open source →
  5. 0.86.1 17 Jul 2026
    Release notes

    Improvements

    • flet-mcp's get_api tool now covers top-level callables — the app entry point (run), reactive hooks (use_state, use_ref, use_effect, …), and decorators (component, memo, observable) — which previously returned not found because only classes were indexed. A new functions bucket in the API builder extracts each package's re-exported public callables and renders them with a signature: line. get_api also resolves enum member lookups inline: get_api("Colors", query="RED") now returns the matching members instead of erroring with a redirect to search_enum_members. Both changes remove wasted agent round-trips observed in production usage by @FeodorFitsner.

    Bug fixes

    • Fix flet build windows failing on non-UTF-8 system locales (e.g. Simplified-Chinese Windows, code page 936/GBK) with warning C4819 escalated to error C2220 while compiling a plugin's Windows sources. A non-ASCII character in a plugin source (e.g. an em dash in a comment) couldn't be decoded under the system code page, and the build template's /WX (warnings-as-errors) turned it fatal. The Windows build template now compiles all targets with /utf-8, so every plugin — including third-party ones flet doesn't control (e.g. connectivity_plus) — reads its sources as UTF-8 regardless of the build machine's code page. Also bumps serious_python to 4.3.3, which removes the character from its own plugin at the source (#6686) by @FeodorFitsner.
    • Fix the cryptic shutil.ReadError: ... is not a zip file failure in web apps when the app package download fails. The Pyodide worker piped the pyfetch(app_package_url) response straight into unpack_archive() without a status check, so any non-2xx response (transient server 500, expired auth 401, deleted app 404) wrote the JSON/HTML error body to a temp file and crashed while unpacking it. The worker now checks response.ok and raises a readable Failed to download app package: HTTP <status> <url> — <body> error, including the first 200 chars of the error body. Applied to both the Flet web client and the flet build template (#6680) by @FeodorFitsner.
    • Remove unused BasePage return type and import from BaseControl and ControlEvent (#6606) by @Iaw4tch.
    • Fix GestureDetector.allowed_devices crashing with type 'List<dynamic>' is not a subtype of type 'List<String?>?' and preventing the control from rendering. Property values are deserialized from JSON as List<dynamic>, but the value was read via get<List<String?>>(...), whose reified cast fails because a List<dynamic> is not a List<String?>. It's now read as List<dynamic> and each entry is converted to a string before parsing, restoring supportedDevices filtering for Flutter's GestureDetector (#6684) by @TURBODRIVER.

    New Contributors

    Full Changelog: v0.86.0...v0.86.1

    Open source →
    Release notes

    Improvements

    • flet-mcp's get_api tool now covers top-level callables — the app entry point (run), reactive hooks (use_state, use_ref, use_effect, …), and decorators (component, memo, observable) — which previously returned not found because only classes were indexed. A new functions bucket in the API builder extracts each package's re-exported public callables and renders them with a signature: line. get_api also resolves enum member lookups inline: get_api("Colors", query="RED") now returns the matching members instead of erroring with a redirect to search_enum_members. Both changes remove wasted agent round-trips observed in production usage (#6680) by @FeodorFitsner.

    Bug fixes

    • Fix flet build windows failing on non-UTF-8 system locales (e.g. Simplified-Chinese Windows, code page 936/GBK) with warning C4819 escalated to error C2220 while compiling a plugin's Windows sources. A non-ASCII character in a plugin source (e.g. an em dash in a comment) couldn't be decoded under the system code page, and the build template's /WX (warnings-as-errors) turned it fatal. The Windows build template now compiles all targets with /utf-8, so every plugin — including third-party ones flet doesn't control (e.g. connectivity_plus) — reads its sources as UTF-8 regardless of the build machine's code page. Also bumps serious_python to 4.3.3, which removes the character from its own plugin at the source (#6686) by @FeodorFitsner.
    • Fix the cryptic shutil.ReadError: ... is not a zip file failure in web apps when the app package download fails. The Pyodide worker piped the pyfetch(app_package_url) response straight into unpack_archive() without a status check, so any non-2xx response (transient server 500, expired auth 401, deleted app 404) wrote the JSON/HTML error body to a temp file and crashed while unpacking it. The worker now checks response.ok and raises a readable Failed to download app package: HTTP <status> <url> — <body> error, including the first 200 chars of the error body. Applied to both the Flet web client and the flet build template (#6680) by @FeodorFitsner.
    • Remove unused BasePage return type and import from BaseControl and ControlEvent (#6606) by @Iaw4tch.
    • Fix GestureDetector.allowed_devices crashing with type 'List<dynamic>' is not a subtype of type 'List<String?>?' and preventing the control from rendering. Property values are deserialized from JSON as List<dynamic>, but the value was read via get<List<String?>>(...), whose reified cast fails because a List<dynamic> is not a List<String?>. It's now read as List<dynamic> and each entry is converted to a string before parsing, restoring supportedDevices filtering for Flutter's GestureDetector (#6684) by @TURBODRIVER.
    Open source →
    Release notes

    No changes in the flet Dart package; version bumped for release coordination with the web client's readable app-package download errors (#6680).

    Open source →
  6. 0.86.0 14 Jul 2026
    Release notes

    New features

    • Add support for Python multiprocessing in packaged Flet desktop apps built with flet build macos, flet build windows, and flet build linux. multiprocessing APIs such as Process, ProcessPoolExecutor, the spawn/forkserver start methods, and the resource tracker now work in packaged desktop apps. Previously, worker processes re-executed sys.executable, which pointed to the app binary itself, causing each worker to launch another GUI app instance and hang. Flet desktop runners now detect CPython multiprocessing child command lines before Flutter starts and divert them to a headless embedded Python interpreter via dart_bridge 1.5.0+. The Python bootstrap also runs the app module as the real sys.modules["__main__"] with python -m semantics, so top-level worker functions in main.py can be pickled correctly. When using multiprocessing, your app must follow normal Python multiprocessing rules: guard ft.run(...) with if __name__ == "__main__":, define worker functions at module top level, and do not access Flet UI objects from worker processes. See the new Multiprocessing cookbook page. Mobile platforms remain unsupported because iOS and Android do not allow apps to spawn arbitrary child processes (#4283, #6577) by @ndonkoHenri.
    • Multi-version bundled CPython support in flet build and flet publish. Pick the runtime your app ships with via the new --python-version flag (3.12 / 3.13 / 3.14), or let it be derived from [project].requires-python in your pyproject.toml; defaults to the latest supported stable (currently 3.14). The matching CPython-standalone build, Pyodide release (0.27.7 / 0.29.4 / 314.0.1), and Emscripten wheel platform tag are all resolved from flet-dev/python-build's date-keyed manifest. Adding a future pre-release CPython line (e.g. 3.15 beta) is a one-row append with prerelease=True — opt-in only via an explicit --python-version 3.15 or requires-python = "==3.15.*", never the auto-resolved default. Requires serious_python >= 4.0.0, now pinned in the flet build template. See the new Choosing a Python version docs section (#6577) by @FeodorFitsner.
    • Add ft.DataChannel: dedicated byte channels for widgets that move bulk binary data (image frames, audio buffers, ML tensors) between Dart and Python, bypassing the MsgPack control protocol. The Dart side opens a channel via FletBackend.of(context).openDataChannel() and announces it to Python by firing a data_channel_open control event with {channel_name, channel_id}; the Python side declares on_data_channel_open: Optional[ft.EventHandler[ft.DataChannelOpenEvent]] and captures the channel via self.get_data_channel(e.channel_id). Backed by a dedicated PythonBridge per channel in embedded native mode (4–7 GiB/s on M2 Pro) and by the default ProtocolMuxedDataChannelFactory in dev / web modes (raw-byte frames muxed over the active Flet protocol transport with a 1-byte type discriminator). Pyodide gets zero-copy outbound sends via postMessage Transferable ArrayBuffer. First consumer: flet-charts MatplotlibChartCanvas, migrated from _invoke_method PNG dispatch to a 1-byte-opcode data channel by @FeodorFitsner.
    • In-process Python transport (dart_bridge FFI). package:flet gains a third protocol transport alongside the UDS / TCP socket servers: it can run Flet's MsgPack protocol over an in-process dart_bridge byte channel via a FletApp(channelBuilder: …) seam (the flet package stays Python-independent — it doesn't depend on serious_python or know about PythonBridge; the embedder wires the channel). serious_python >= 3.0.0 uses this seam to embed the Python interpreter in-process instead of talking to it over a localhost socket, and the flet build template migrates from sockets to the FFI transport. On Android, where the OS may keep the process alive across a back-button quit and restart only the Dart VM, the transport rebinds to the new VM's dart_bridge ports on a session-restart signal (libdart_bridge >= 1.3.0) — the Python process and its in-memory state are preserved and the Flet session is rebuilt from REGISTER_CLIENT by @FeodorFitsner.
    • Add flet clean command that deletes the build directory of a Flet app — the Flutter bootstrap project, cached artifacts, and generated output — in a single step (#6233) by @ndonkoHenri.
    • Add compression_quality to FilePicker.pick_files() for selecting the image compression quality used by supported platforms (#6573) by @ndonkoHenri.
    • Add ConsentManager to flet-ads for gathering user consent (e.g. GDPR/EEA) via Google's User Messaging Platform (UMP) before requesting ads (#6569, #6615) by @ndonkoHenri.
    • Add ft.RawImage: a high-bandwidth pixel-frame display control for Pillow output, NumPy arrays, camera frames and procedural graphics. Frames stream over a dedicated ft.DataChannel instead of the control protocol: raw premultiplied RGBA straight to a GPU texture on local transports (desktop, flet run, Pyodide), automatic PNG fallback on remote flet-web sessions. The awaitable render(pil_or_numpy) / render_rgba(w, h, bytes) / render_encoded(png_jpeg_webp_bytes) methods resolve when the client has displayed the frame, so a plain while True: await ri.render(...) loop self-paces to display speed. Premultiplied-alpha conversion runs in Pillow's C loops with an opaque fast-path; Pillow and NumPy remain optional. The last frame is retained and replayed on remount, mirroring Image.src. Ships with five gallery examples (photo viewer, plasma, Pillow paint, Mandelbrot explorer, Game of Life) and a docs page with RawImage vs Image guidance (#6674) by @FeodorFitsner.

    Improvements

    • Swift Package Manager for iOS/macOS builds (on by default). flet build / flet debug now integrate the embedded Python runtime via SPM instead of CocoaPods (CocoaPods goes read-only in December 2026). Flet auto-falls back to CocoaPods when the app depends on a package that isn't SPM-ready — currently flet-video (media_kit) — since Flutter then builds the whole app with CocoaPods. Force CocoaPods for other non-SPM packages with --no-swift-package-manager (or swift_package_manager = false under [tool.flet]). Flet does not change Flutter's global SPM configuration; the setting only selects how serious_python stages the runtime to match. When SPM is used (it has no pod install hook), flet build sets SERIOUS_PYTHON_DARWIN_SPM so serious_python's package step stages the runtime (Python/dart_bridge xcframeworks, the iOS native extensions, and the stdlib/site-packages/app resources) into the plugin's Package.swift layout on the host before flutter build, and exports the SP_NATIVE_SET cache-bust key into the build. Requires the SPM-capable serious_python release.
    • Smaller Android apps with no native-packaging config. flet build apk/aab consume serious_python's new Android packaging: Python extension modules load memory-mapped directly from the APK (no extraction to disk), and pure Python ships in stored asset zips read via zipimport, so the standard library is no longer duplicated per ABI. Apps no longer need useLegacyPackaging / keepDebugSymbols — the flet build Android template drops them; just use minSdk 23+. New --android-extract-packages flag and [tool.flet.android].extract_packages ship "path-hungry" packages — those that read bundled data via __file__ / pkg_resources instead of importlib.resources — extracted to disk instead of inside the zip (most packages, including certifi, are zip-safe and need no entry). Requires serious_python with the native-mmap packaging (dart_bridge 1.4.0).
    • Pyodide is no longer pre-baked into the flet build template. Each flet build web / flet publish run downloads the matching pyodide-core-<version>.tar.bz2 (plus the runtime micropip and packaging wheels) into a per-version cache at ~/.flet/pyodide/<version>/ and copies the files into the build output. Subsequent builds reuse the cache; the older 0.27.5 bundle previously shipped in the cookiecutter template is gone (#6577) by @FeodorFitsner.
    • The supported Python / Pyodide / dart_bridge versions are loaded on demand from flet-dev/python-build's date-keyed manifest.json (fetched once and cached under ~/.flet/cache), the single source of truth shared with serious_python — replacing flet's hand-mirrored version table. flet build forwards only SERIOUS_PYTHON_VERSION and lets serious_python derive the full version / build date / dart_bridge version from its own committed snapshot. The module exposes get_supported_python_versions() / get_default_python_version() (the previous SUPPORTED_PYTHON_VERSIONS / DEFAULT_PYTHON_VERSION constants are removed) (#6577) by @FeodorFitsner.
    • flet --version shows just the Flet and Flutter versions; the static Pyodide: … line and the global flet.version.pyodide_version export are removed (the supported Python / Pyodide set now lives in python-build's manifest, not the CLI output) (#6577) by @FeodorFitsner.
    • flet --version --json emits a machine-readable document — Flet/Flutter versions and the Linux build dependencies — for CI to read via jq instead of importing Flet internals with python -c. (The supported Python/Pyodide table is no longer included; it comes from python-build's manifest.) The canonical Linux apt dependency list moved from flet.utils.linux_deps (runtime package) to flet_cli.utils.linux_deps (build tooling) by @FeodorFitsner.
    • client/web/python.js and the build template's python.js no longer hardcode defaultPyodideUrl. patch_index.py now injects flet.pyodideUrl per build (CDN URL by default, or the local pyodide/pyodide.js path under --no-cdn) so the runtime URL always tracks the resolved Pyodide release (#6577) by @FeodorFitsner.
    • Stream-oriented Flet protocol transports (UDS / TCP used by flet run dev mode) now use length-prefixed framing instead of streaming msgpack.Unpacker.feed. Combined with a new 1-byte type discriminator at the head of every packet (0x00 = MsgPack control frame, 0x01 = raw DataChannel frame), this unifies framing across all transports (sockets, WebSocket, dart_bridge FFI, Pyodide postMessage). StreamingMsgpackDeserializer is removed from package:flet; each inbound packet is one complete MsgPack value, decoded one-shot via msgpack.deserialize(bytes) by @FeodorFitsner.
    • Bump the bundled Flutter to 3.44.2 (from 3.41.7). The Flet client and the flet build template migrate to Flutter 3.44's built-in Kotlin (the Android app no longer applies the Kotlin Gradle plugin itself) and Java 17; the client's Gradle wrapper moves to 8.14 by @FeodorFitsner.
    • Raw RGBA Matplotlib frames on local transports. MatplotlibChart now skips per-frame diffing and PNG encode/decode when the client runs on the same machine: uncompressed RGBA full frames stream straight from Agg's buffer over the chart's DataChannel (new 0x04 opcode) and are displayed with a single decodeImageFromPixels + swap on the Dart side. A 1600×1000 @ DPR 2 figure (24 MB/frame) over a local socket goes from 7.4 to 18.7 fps, leaving matplotlib's own render as the dominant per-frame cost; remote WebSocket clients keep the compact PNG full+diff pipeline. The format is auto-selected via the new Connection.local_data_transport capability flag (set by the socket, dart_bridge and Pyodide transports). Also fixes O(n²) length-prefixed packet reassembly in the Dart socket transport — multi-MB frames arrive in dozens of chunks and previously re-flattened the accumulation buffer on every chunk (#6673) by @FeodorFitsner.
    • flet build web and flet publish now default the web renderer to canvaskit instead of auto. With auto, Chromium selects the dart2wasm/skwasm renderer, whose JS↔Dart typed-data boundary costs make byte-streaming Pyodide apps (matplotlib frames, RawImage) ~6–7x slower per frame; pass --renderer auto or set [tool.flet.web].renderer to restore the old behavior. Also fixes tool.flet.web.renderer being ignored by flet publish (shadowed by an argparse default) (#6673) by @FeodorFitsner.
    • Faster mobile cold start: import flet is now lazy. The flet package previously executed its full ~270-module public API eagerly on import flet; it now resolves public names on first access via a module-level __getattr__ (PEP 562), so an app loads only the modules it actually uses. On a mid-range Android device this cut import flet from ~2.0s to ~0.15s. The eager subsystem clusters that Page pulled in (auth, components/hooks, Cupertino controls) are deferred too. Type checkers, IDEs, and from flet import * are unaffected (#6597) by @FeodorFitsner.

    Breaking changes

    • App files now ship unpacked in a read-only bundle, and the storage directories were reworked (requires serious_python >= 4.0.0, now pinned in the flet build template). Your Python sources ship unpacked inside the app bundle next to the stdlib/site-packages (no first-launch app.zip extraction) on macOS/iOS/Windows/Linux; on Android they ship as a stored app.zip asset unpacked once on first launch; web is unchanged. The app directory is now read-only, so the Python program's working directory moved to a writable, app-private data dir. FLET_APP_STORAGE_DATA now maps to the OS application support dir (a data subdir) instead of the user's Documents folder and is the cwd; FLET_APP_STORAGE_TEMP now points to the OS temp dir (was the cache dir) and a new FLET_APP_STORAGE_CACHE exposes the cache dir. flet run sets the dev cwd to a hidden, git-ignored <project>/.flet/storage/data. Relative reads of bundled files (open("seed.json")) must move to __file__/importlib.resources or assets/. See the app files unpacked / storage dirs guide by @FeodorFitsner.
    • flet build and flet publish now bundle CPython 3.14 by default (previously 3.12, implicit via the old single-version serious_python). Existing apps that depend on native wheels without 3.14 binaries should pin explicitly with --python-version 3.12 (CLI), requires-python = ">=3.12,<3.13" (pyproject), or SERIOUS_PYTHON_VERSION=3.12 in the build environment (#6577) by @FeodorFitsner.
    • Android builds now include only the ABIs the bundled Python supports, sourced per-version from python-build's manifest (pythons.<short>.android_abis) rather than hardcoded in flet. As of python-build 20260630, armeabi-v7a (32-bit ARM) is published for 3.12, 3.13 and 3.14, so all three build it by default; an explicit --arch <abi> is validated against the selected Python's supported set and fails with a clear error otherwise (#6578) by @ndonkoHenri.
    • flet build / flet publish now compile your app and packages to .pyc by default (previously off). This removes per-launch bytecode recompilation — a significant cold-start win, especially on mobile where pure Python is imported from a stored zip (zipimport) and can't cache bytecode back to disk, so every module would otherwise recompile from source on each launch. The CLI flags gain --no-compile-app / --no-compile-packages (via argparse.BooleanOptionalAction; the existing --compile-app / --compile-packages still work), and [tool.flet.compile].app / .packages now default to true. Pass --no-compile-* or set them to false to restore the old behavior (faster iterative builds, or keeping .py source in the bundle). Compiled web builds were verified to load in Pyodide (bundled CPython and Pyodide share the same minor version). See the compile-on-by-default guide (#6598) by @FeodorFitsner.
    • Flet protocol wire format on stream-oriented transports (UDS / TCP) is incompatible with pre-0.86 servers and clients. Every packet now starts with a 4-byte little-endian length prefix and a 1-byte type discriminator (0x00 = MsgPack control frame, 0x01 = raw DataChannel frame). WebSocket / postMessage / dart_bridge transports keep native message boundaries and only gain the type byte. The Flet CLI dev server and the in-process Python runtime are upgraded in lockstep — running flet run with mismatched flet versions across CLI and runtime is no longer supported. See the DataChannel protocol framing upgrade guide. The MatplotlibChartCanvas widget transports its full / diff / clear frames via a DataChannel rather than _invoke_method arguments — visually identical, but custom code that subclassed it and overrode the apply methods may need updating by @FeodorFitsner.

    Deprecations

    • Deprecate the --clear-cache flag of flet build and flet debug; use the new flet clean command instead. The flag remains functional but now emits a deprecation warning, and is scheduled for removal in 0.89.0 (#6233) by @ndonkoHenri.

    Bug fixes

    • Fix a debug-mode '!_dirty': is not true assertion (EXCEPTION CAUGHT BY WIDGETS LIBRARY in _BootOverlay) thrown by apps built or debugged from the flet build template when the app becomes ready. With the default boot_screen.fade_out_duration of 0 the overlay's zero-duration AnimatedOpacity completed synchronously, firing onEnd — and its setState — in the middle of the overlay's own rebuild. The overlay is now removed in a single state update when no fade is configured; non-zero fade durations still animate as before. Debug-mode only: the assertion is compiled out of release builds (#6666) by @FeodorFitsner.
    • Fix flet build failing on Windows when a dependency is pulled in via [tool.flet.<platform>].dev_packages (or any local-path install): the rewritten <pkg> @ file://<path> URL now uses Path.as_uri(), producing the correct file:///D:/... three-slash form instead of file://D:\..., which pip on Windows parsed as a UNC path and aborted with OSError: [Errno 2] No such file or directory: '\\\\D:\\a\\...' (#6577) by @FeodorFitsner.
    • Fix flet build web --python-version 3.13 failing to match any Pyodide-built native wheel. The 3.13 row in the Python version registry was set to Pyodide platform tag pyodide-2025.0-wasm32, but Pyodide actually publishes 0.29 wheels under pyemscripten_2025_0_wasm32 (the pyodide_pyemscripten_ prefix transition happened at 0.28/0.29, not at 314.0). Corrected to pyemscripten-2025.0-wasm32 so pip's wheel selection picks up the correct tags by @FeodorFitsner.
    • flet build now cleans the build directory when the bundled Python version changes between builds, preventing stale compiled bytecode from the previous version crashing the app at runtime with ImportError: bad magic number by @FeodorFitsner.
    • Fix locating Flet controls by their user-assigned key in tests. ValueKey(control.key) was constructed as ValueKey<Object>, and Flutter's runtimeType-strict ValueKey.== never matches that against the ValueKey<String> the rendered widget carries — so find.byKey(Key('foo')) (flutter_test) and find_by_key('foo') (Flet tester) located 0 widgets. The ValueKey is now built with the value's concrete type (String → ValueKey<String>, int → ValueKey<int>, …) on both the Dart and Python sides by @FeodorFitsner.
    • Fix flet build apk / flet build aab with --arch packaging native libraries for all Android ABIs instead of only the requested ones. The requested architectures are now forwarded to Flutter as --target-platform (so --split-per-abi builds only the requested splits), unrequested ABI directories are excluded from the artifact via packaging.jniLibs.excludes, Android --arch values are validated against the bundled Python's supported ABIs, multiple --arch values now correctly reach serious_python (comma-joined), and stale artifacts from previous builds are no longer copied into the output directory (#6567, #6578) by @ndonkoHenri.
    • Fix repeated --arch, --source-packages and --permissions flags in flet build keeping only the values of the last occurrence (action="extend" on each) (#6578) by @ndonkoHenri.
    • Fix flet build apk failing at mergeDebugNativeLibs with N files found with path 'lib/<abi>/libc++_shared.so' when an app combines serious_python_android with another Flutter plugin that also bundles the NDK C++ runtime (#6570, #6571) by @ndonkoHenri.
    • Specify handler signatures in subscribe and subscribe_topic methods of PubSubClient for better type checking (#6549) by @Iaw4tch
    • Fix FilePicker.pick_files() on web for slow network shares or slow machines: pass cancel_upload_on_window_blur=False to prevent valid file selections from being reported as cancelled when the browser window loses focus during file picking (#771, #6573) by @ndonkoHenri.
    • Support PagePlatform.ANDROID_TV in Page.get_device_info() retrieval (#6604) by @bl1nch.
    • Fix ProgressRing.year_2023 being ignored, so the control correctly switches between the latest and 2023 Material Design appearances (#6614) by @ndonkoHenri.
    • flet build ipa / ios apps that ship ctypes packages with plain .dylib shared libraries (e.g. llama-cpp-python) now load them on the iOS simulator instead of failing at launch with a dlopen platform mismatch (have 'iOS', need 'iOS-simulator'); the iOS runtime also now bundles the _multiprocessing extension (importable, not spawnable). Bumps the pinned bundle to serious_python 4.2.1 / python-build 20260701 (serious_python#223) by @ndonkoHenri, @FeodorFitsner.
    • Improve performance of checking added/removed controls in Session.patch_control from O(N²) to O(N) (#6651) by @davidlawson.
    • Fix stateful controls inside ResponsiveRow (video players, WebViews, scroll positions) losing their state whenever a window resize crossed a breakpoint and the layout switched between a single row and wrapping (#6661, #6663) by @FeodorFitsner.

    Documentation

    • Improve FilePicker.save_file() documentation: on desktop, passing src_bytes writes those bytes to the selected file (#6573) by @ndonkoHenri.

    New Contributors

    Full Changelog: v0.85.3...v0.86.0

    Open source →
    Release notes

    New features

    • Add support for Python multiprocessing in packaged Flet desktop apps built with flet build macos, flet build windows, and flet build linux. multiprocessing APIs such as Process, ProcessPoolExecutor, the spawn/forkserver start methods, and the resource tracker now work in packaged desktop apps. Previously, worker processes re-executed sys.executable, which pointed to the app binary itself, causing each worker to launch another GUI app instance and hang. Flet desktop runners now detect CPython multiprocessing child command lines before Flutter starts and divert them to a headless embedded Python interpreter via dart_bridge 1.5.0+. The Python bootstrap also runs the app module as the real sys.modules["__main__"] with python -m semantics, so top-level worker functions in main.py can be pickled correctly. When using multiprocessing, your app must follow normal Python multiprocessing rules: guard ft.run(...) with if __name__ == "__main__":, define worker functions at module top level, and do not access Flet UI objects from worker processes. See the new Multiprocessing cookbook page. Mobile platforms remain unsupported because iOS and Android do not allow apps to spawn arbitrary child processes (#4283, #6577) by @ndonkoHenri.
    • Multi-version bundled CPython support in flet build and flet publish. Pick the runtime your app ships with via the new --python-version flag (3.12 / 3.13 / 3.14), or let it be derived from [project].requires-python in your pyproject.toml; defaults to the latest supported stable (currently 3.14). The matching CPython-standalone build, Pyodide release (0.27.7 / 0.29.4 / 314.0.1), and Emscripten wheel platform tag are all resolved from flet-dev/python-build's date-keyed manifest. Adding a future pre-release CPython line (e.g. 3.15 beta) is a one-row append with prerelease=True — opt-in only via an explicit --python-version 3.15 or requires-python = "==3.15.*", never the auto-resolved default. Requires serious_python >= 4.0.0, now pinned in the flet build template. See the new Choosing a Python version docs section (#6577) by @FeodorFitsner.
    • Add ft.DataChannel: dedicated byte channels for widgets that move bulk binary data (image frames, audio buffers, ML tensors) between Dart and Python, bypassing the MsgPack control protocol. The Dart side opens a channel via FletBackend.of(context).openDataChannel() and announces it to Python by firing a data_channel_open control event with {channel_name, channel_id}; the Python side declares on_data_channel_open: Optional[ft.EventHandler[ft.DataChannelOpenEvent]] and captures the channel via self.get_data_channel(e.channel_id). Backed by a dedicated PythonBridge per channel in embedded native mode (4–7 GiB/s on M2 Pro) and by the default ProtocolMuxedDataChannelFactory in dev / web modes (raw-byte frames muxed over the active Flet protocol transport with a 1-byte type discriminator). Pyodide gets zero-copy outbound sends via postMessage Transferable ArrayBuffer. First consumer: flet-charts MatplotlibChartCanvas, migrated from _invoke_method PNG dispatch to a 1-byte-opcode data channel (#6601) by @FeodorFitsner.
    • In-process Python transport (dart_bridge FFI). package:flet gains a third protocol transport alongside the UDS / TCP socket servers: it can run Flet's MsgPack protocol over an in-process dart_bridge byte channel via a FletApp(channelBuilder: …) seam (the flet package stays Python-independent — it doesn't depend on serious_python or know about PythonBridge; the embedder wires the channel). serious_python >= 3.0.0 uses this seam to embed the Python interpreter in-process instead of talking to it over a localhost socket, and the flet build template migrates from sockets to the FFI transport. On Android, where the OS may keep the process alive across a back-button quit and restart only the Dart VM, the transport rebinds to the new VM's dart_bridge ports on a session-restart signal (libdart_bridge >= 1.3.0) — the Python process and its in-memory state are preserved and the Flet session is rebuilt from REGISTER_CLIENT (#6601) by @FeodorFitsner.
    • Add flet clean command that deletes the build directory of a Flet app — the Flutter bootstrap project, cached artifacts, and generated output — in a single step (#6233) by @ndonkoHenri.
    • Add compression_quality to FilePicker.pick_files() for selecting the image compression quality used by supported platforms (#6573) by @ndonkoHenri.
    • Add ConsentManager to flet-ads for gathering user consent (e.g. GDPR/EEA) via Google's User Messaging Platform (UMP) before requesting ads (#6569, #6615) by @ndonkoHenri.
    • Add ft.RawImage: a high-bandwidth pixel-frame display control for Pillow output, NumPy arrays, camera frames and procedural graphics. Frames stream over a dedicated ft.DataChannel instead of the control protocol: raw premultiplied RGBA straight to a GPU texture on local transports (desktop, flet run, Pyodide), automatic PNG fallback on remote flet-web sessions. The awaitable render(pil_or_numpy) / render_rgba(w, h, bytes) / render_encoded(png_jpeg_webp_bytes) methods resolve when the client has displayed the frame, so a plain while True: await ri.render(...) loop self-paces to display speed. Premultiplied-alpha conversion runs in Pillow's C loops with an opaque fast-path; Pillow and NumPy remain optional. The last frame is retained and replayed on remount, mirroring Image.src. Ships with five gallery examples (photo viewer, plasma, Pillow paint, Mandelbrot explorer, Game of Life) and a docs page with RawImage vs Image guidance (#6674) by @FeodorFitsner.

    Improvements

    • Swift Package Manager for iOS/macOS builds (on by default). flet build / flet debug now integrate the embedded Python runtime via SPM instead of CocoaPods (CocoaPods goes read-only in December 2026). Flet auto-falls back to CocoaPods when the app depends on a package that isn't SPM-ready — currently flet-video (media_kit) — since Flutter then builds the whole app with CocoaPods. Force CocoaPods for other non-SPM packages with --no-swift-package-manager (or swift_package_manager = false under [tool.flet]). Flet does not change Flutter's global SPM configuration; the setting only selects how serious_python stages the runtime to match. When SPM is used (it has no pod install hook), flet build sets SERIOUS_PYTHON_DARWIN_SPM so serious_python's package step stages the runtime (Python/dart_bridge xcframeworks, the iOS native extensions, and the stdlib/site-packages/app resources) into the plugin's Package.swift layout on the host before flutter build, and exports the SP_NATIVE_SET cache-bust key into the build. Requires the SPM-capable serious_python release (#6608).
    • Smaller Android apps with no native-packaging config. flet build apk/aab consume serious_python's new Android packaging: Python extension modules load memory-mapped directly from the APK (no extraction to disk), and pure Python ships in stored asset zips read via zipimport, so the standard library is no longer duplicated per ABI. Apps no longer need useLegacyPackaging / keepDebugSymbols — the flet build Android template drops them; just use minSdk 23+. New --android-extract-packages flag and [tool.flet.android].extract_packages ship "path-hungry" packages — those that read bundled data via __file__ / pkg_resources instead of importlib.resources — extracted to disk instead of inside the zip (most packages, including certifi, are zip-safe and need no entry). Requires serious_python with the native-mmap packaging (dart_bridge 1.4.0) (#6601).
    • Pyodide is no longer pre-baked into the flet build template. Each flet build web / flet publish run downloads the matching pyodide-core-<version>.tar.bz2 (plus the runtime micropip and packaging wheels) into a per-version cache at ~/.flet/pyodide/<version>/ and copies the files into the build output. Subsequent builds reuse the cache; the older 0.27.5 bundle previously shipped in the cookiecutter template is gone (#6577) by @FeodorFitsner.
    • The supported Python / Pyodide / dart_bridge versions are loaded on demand from flet-dev/python-build's date-keyed manifest.json (fetched once and cached under ~/.flet/cache), the single source of truth shared with serious_python — replacing flet's hand-mirrored version table. flet build forwards only SERIOUS_PYTHON_VERSION and lets serious_python derive the full version / build date / dart_bridge version from its own committed snapshot. The module exposes get_supported_python_versions() / get_default_python_version() (the previous SUPPORTED_PYTHON_VERSIONS / DEFAULT_PYTHON_VERSION constants are removed) (#6577) by @FeodorFitsner.
    • flet --version shows just the Flet and Flutter versions; the static Pyodide: … line and the global flet.version.pyodide_version export are removed (the supported Python / Pyodide set now lives in python-build's manifest, not the CLI output) (#6577) by @FeodorFitsner.
    • flet --version --json emits a machine-readable document — Flet/Flutter versions and the Linux build dependencies — for CI to read via jq instead of importing Flet internals with python -c. (The supported Python/Pyodide table is no longer included; it comes from python-build's manifest.) The canonical Linux apt dependency list moved from flet.utils.linux_deps (runtime package) to flet_cli.utils.linux_deps (build tooling) (#6601) by @FeodorFitsner.
    • client/web/python.js and the build template's python.js no longer hardcode defaultPyodideUrl. patch_index.py now injects flet.pyodideUrl per build (CDN URL by default, or the local pyodide/pyodide.js path under --no-cdn) so the runtime URL always tracks the resolved Pyodide release (#6577) by @FeodorFitsner.
    • Stream-oriented Flet protocol transports (UDS / TCP used by flet run dev mode) now use length-prefixed framing instead of streaming msgpack.Unpacker.feed. Combined with a new 1-byte type discriminator at the head of every packet (0x00 = MsgPack control frame, 0x01 = raw DataChannel frame), this unifies framing across all transports (sockets, WebSocket, dart_bridge FFI, Pyodide postMessage). StreamingMsgpackDeserializer is removed from package:flet; each inbound packet is one complete MsgPack value, decoded one-shot via msgpack.deserialize(bytes) (#6601) by @FeodorFitsner.
    • Bump the bundled Flutter to 3.44.2 (from 3.41.7). The Flet client and the flet build template migrate to Flutter 3.44's built-in Kotlin (the Android app no longer applies the Kotlin Gradle plugin itself) and Java 17; the client's Gradle wrapper moves to 8.14 (#6601) by @FeodorFitsner.
    • Raw RGBA Matplotlib frames on local transports. MatplotlibChart now skips per-frame diffing and PNG encode/decode when the client runs on the same machine: uncompressed RGBA full frames stream straight from Agg's buffer over the chart's DataChannel (new 0x04 opcode) and are displayed with a single decodeImageFromPixels + swap on the Dart side. A 1600×1000 @ DPR 2 figure (24 MB/frame) over a local socket goes from 7.4 to 18.7 fps, leaving matplotlib's own render as the dominant per-frame cost; remote WebSocket clients keep the compact PNG full+diff pipeline. The format is auto-selected via the new Connection.local_data_transport capability flag (set by the socket, dart_bridge and Pyodide transports). Also fixes O(n²) length-prefixed packet reassembly in the Dart socket transport — multi-MB frames arrive in dozens of chunks and previously re-flattened the accumulation buffer on every chunk (#6673) by @FeodorFitsner.
    • flet build web and flet publish now default the web renderer to canvaskit instead of auto. With auto, Chromium selects the dart2wasm/skwasm renderer, whose JS↔Dart typed-data boundary costs make byte-streaming Pyodide apps (matplotlib frames, RawImage) ~6–7x slower per frame; pass --renderer auto or set [tool.flet.web].renderer to restore the old behavior. Also fixes tool.flet.web.renderer being ignored by flet publish (shadowed by an argparse default) (#6673) by @FeodorFitsner.
    • Faster mobile cold start: import flet is now lazy. The flet package previously executed its full ~270-module public API eagerly on import flet; it now resolves public names on first access via a module-level __getattr__ (PEP 562), so an app loads only the modules it actually uses. On a mid-range Android device this cut import flet from ~2.0s to ~0.15s. The eager subsystem clusters that Page pulled in (auth, components/hooks, Cupertino controls) are deferred too. Type checkers, IDEs, and from flet import * are unaffected (#6597) by @FeodorFitsner.

    Breaking changes

    • App files now ship unpacked in a read-only bundle, and the storage directories were reworked (requires serious_python >= 4.0.0, now pinned in the flet build template). Your Python sources ship unpacked inside the app bundle next to the stdlib/site-packages (no first-launch app.zip extraction) on macOS/iOS/Windows/Linux; on Android they ship as a stored app.zip asset unpacked once on first launch; web is unchanged. The app directory is now read-only, so the Python program's working directory moved to a writable, app-private data dir. FLET_APP_STORAGE_DATA now maps to the OS application support dir (a data subdir) instead of the user's Documents folder and is the cwd; FLET_APP_STORAGE_TEMP now points to the OS temp dir (was the cache dir) and a new FLET_APP_STORAGE_CACHE exposes the cache dir. flet run sets the dev cwd to a hidden, git-ignored <project>/.flet/storage/data. Relative reads of bundled files (open("seed.json")) must move to __file__/importlib.resources or assets/. See the app files unpacked / storage dirs guide (#6608) by @FeodorFitsner.
    • flet build and flet publish now bundle CPython 3.14 by default (previously 3.12, implicit via the old single-version serious_python). Existing apps that depend on native wheels without 3.14 binaries should pin explicitly with --python-version 3.12 (CLI), requires-python = ">=3.12,<3.13" (pyproject), or SERIOUS_PYTHON_VERSION=3.12 in the build environment (#6577) by @FeodorFitsner.
    • Android builds now include only the ABIs the bundled Python supports, sourced per-version from python-build's manifest (pythons.<short>.android_abis) rather than hardcoded in flet. As of python-build 20260630, armeabi-v7a (32-bit ARM) is published for 3.12, 3.13 and 3.14, so all three build it by default; an explicit --arch <abi> is validated against the selected Python's supported set and fails with a clear error otherwise (#6578) by @ndonkoHenri.
    • flet build / flet publish now compile your app and packages to .pyc by default (previously off). This removes per-launch bytecode recompilation — a significant cold-start win, especially on mobile where pure Python is imported from a stored zip (zipimport) and can't cache bytecode back to disk, so every module would otherwise recompile from source on each launch. The CLI flags gain --no-compile-app / --no-compile-packages (via argparse.BooleanOptionalAction; the existing --compile-app / --compile-packages still work), and [tool.flet.compile].app / .packages now default to true. Pass --no-compile-* or set them to false to restore the old behavior (faster iterative builds, or keeping .py source in the bundle). Compiled web builds were verified to load in Pyodide (bundled CPython and Pyodide share the same minor version). See the compile-on-by-default guide (#6598) by @FeodorFitsner.
    • Flet protocol wire format on stream-oriented transports (UDS / TCP) is incompatible with pre-0.86 servers and clients. Every packet now starts with a 4-byte little-endian length prefix and a 1-byte type discriminator (0x00 = MsgPack control frame, 0x01 = raw DataChannel frame). WebSocket / postMessage / dart_bridge transports keep native message boundaries and only gain the type byte. The Flet CLI dev server and the in-process Python runtime are upgraded in lockstep — running flet run with mismatched flet versions across CLI and runtime is no longer supported. See the DataChannel protocol framing upgrade guide. The MatplotlibChartCanvas widget transports its full / diff / clear frames via a DataChannel rather than _invoke_method arguments — visually identical, but custom code that subclassed it and overrode the apply methods may need updating (#6601) by @FeodorFitsner.

    Deprecations

    • Deprecate the --clear-cache flag of flet build and flet debug; use the new flet clean command instead. The flag remains functional but now emits a deprecation warning, and is scheduled for removal in 0.89.0 (#6233) by @ndonkoHenri.

    Bug fixes

    • Fix a debug-mode '!_dirty': is not true assertion (EXCEPTION CAUGHT BY WIDGETS LIBRARY in _BootOverlay) thrown by apps built or debugged from the flet build template when the app becomes ready. With the default boot_screen.fade_out_duration of 0 the overlay's zero-duration AnimatedOpacity completed synchronously, firing onEnd — and its setState — in the middle of the overlay's own rebuild. The overlay is now removed in a single state update when no fade is configured; non-zero fade durations still animate as before. Debug-mode only: the assertion is compiled out of release builds (#6666) by @FeodorFitsner.
    • Fix flet build failing on Windows when a dependency is pulled in via [tool.flet.<platform>].dev_packages (or any local-path install): the rewritten <pkg> @ file://<path> URL now uses Path.as_uri(), producing the correct file:///D:/... three-slash form instead of file://D:\..., which pip on Windows parsed as a UNC path and aborted with OSError: [Errno 2] No such file or directory: '\\\\D:\\a\\...' (#6577) by @FeodorFitsner.
    • Fix flet build web --python-version 3.13 failing to match any Pyodide-built native wheel. The 3.13 row in the Python version registry was set to Pyodide platform tag pyodide-2025.0-wasm32, but Pyodide actually publishes 0.29 wheels under pyemscripten_2025_0_wasm32 (the pyodide_pyemscripten_ prefix transition happened at 0.28/0.29, not at 314.0). Corrected to pyemscripten-2025.0-wasm32 so pip's wheel selection picks up the correct tags (#6601) by @FeodorFitsner.
    • flet build now cleans the build directory when the bundled Python version changes between builds, preventing stale compiled bytecode from the previous version crashing the app at runtime with ImportError: bad magic number (#6601) by @FeodorFitsner.
    • Fix locating Flet controls by their user-assigned key in tests. ValueKey(control.key) was constructed as ValueKey<Object>, and Flutter's runtimeType-strict ValueKey.== never matches that against the ValueKey<String> the rendered widget carries — so find.byKey(Key('foo')) (flutter_test) and find_by_key('foo') (Flet tester) located 0 widgets. The ValueKey is now built with the value's concrete type (String → ValueKey<String>, int → ValueKey<int>, …) on both the Dart and Python sides (#6601) by @FeodorFitsner.
    • Fix flet build apk / flet build aab with --arch packaging native libraries for all Android ABIs instead of only the requested ones. The requested architectures are now forwarded to Flutter as --target-platform (so --split-per-abi builds only the requested splits), unrequested ABI directories are excluded from the artifact via packaging.jniLibs.excludes, Android --arch values are validated against the bundled Python's supported ABIs, multiple --arch values now correctly reach serious_python (comma-joined), and stale artifacts from previous builds are no longer copied into the output directory (#6567, #6578) by @ndonkoHenri.
    • Fix repeated --arch, --source-packages and --permissions flags in flet build keeping only the values of the last occurrence (action="extend" on each) (#6578) by @ndonkoHenri.
    • Fix flet build apk failing at mergeDebugNativeLibs with N files found with path 'lib/<abi>/libc++_shared.so' when an app combines serious_python_android with another Flutter plugin that also bundles the NDK C++ runtime (#6570, #6571) by @ndonkoHenri.
    • Specify handler signatures in subscribe and subscribe_topic methods of PubSubClient for better type checking (#6549) by @Iaw4tch
    • Fix FilePicker.pick_files() on web for slow network shares or slow machines: pass cancel_upload_on_window_blur=False to prevent valid file selections from being reported as cancelled when the browser window loses focus during file picking (#771, #6573) by @ndonkoHenri.
    • Support PagePlatform.ANDROID_TV in Page.get_device_info() retrieval (#6604) by @bl1nch.
    • Fix ProgressRing.year_2023 being ignored, so the control correctly switches between the latest and 2023 Material Design appearances (#6614) by @ndonkoHenri.
    • flet build ipa / ios apps that ship ctypes packages with plain .dylib shared libraries (e.g. llama-cpp-python) now load them on the iOS simulator instead of failing at launch with a dlopen platform mismatch (have 'iOS', need 'iOS-simulator'); the iOS runtime also now bundles the _multiprocessing extension (importable, not spawnable). Bumps the pinned bundle to serious_python 4.2.1 / python-build 20260701 (serious_python#223) by @ndonkoHenri, @FeodorFitsner.
    • Improve performance of checking added/removed controls in Session.patch_control from O(N²) to O(N) (#6651) by @davidlawson.
    • Fix stateful controls inside ResponsiveRow (video players, WebViews, scroll positions) losing their state whenever a window resize crossed a breakpoint and the layout switched between a single row and wrapping (#6661, #6663) by @FeodorFitsner.

    Documentation

    • Improve FilePicker.save_file() documentation: on desktop, passing src_bytes writes those bytes to the selected file (#6573) by @ndonkoHenri.
    Open source →
    Release notes

    No changes in the flet Dart package; version bumped for release coordination with the multi-version bundled CPython support on the Python side (#6577).

    Open source →
  7. 0.85.3 08 Jun 2026
    Release notes

    What's Changed

    Improvements

    • Allow [tool.flet.android.permission] values to be TOML inline tables in addition to booleans — each key = "value" entry adds an android:<key>="<value>" attribute to the generated <uses-permission> element, unlocking modifiers like android:maxSdkVersion and android:usesPermissionFlags that real-world Android permissions (e.g. Bluetooth LE) require. The boolean form and the --android-permissions CLI flag are unchanged; a non-empty inline table is always emitted, an empty table ({}) is treated as false, and invalid value types fail the build with a clear error (#6550, #6551) by @FeodorFitsner.
    • Add [tool.flet.android.provider] for declaring custom <provider> entries in the generated AndroidManifest.xml. Each table key is the provider's android:name; entries become android:<key>="<value>" attributes on the generated element. A reserved meta_data sub-table emits nested <meta-data> children (scalar values render as android:value="…"; inline-table values render as android:<k>="<v>" so android:resource="@xml/…" works). false / {} skip the entry; true and invalid value types fail the build with a clear error. The built-in androidx.core.content.FileProvider block is unchanged (#6556, #6559) by @FeodorFitsner.
    • Upgrade the bundled Pyodide runtime in the flet build web template from 0.27.5 to 0.27.7 (includes micropip 0.9.0) (#6549) by @FeodorFitsner.
    • Drop generated web/canvaskit/ build artifacts (canvaskit.js/.wasm/.symbols and the chromium/ and skwasm/skwasm_st variants) from the flet build web template — these are produced by the Flutter web build and should not have been committed into the cookiecutter template (#6549) by @FeodorFitsner.
    • Cache the downloaded flet-build-template.zip across builds. The build template is bound to an exact Flet version and is immutable, so on every flet build / flet debug after the first, the CLI now uses a previously-downloaded zip from $FLET_CACHE_DIR/build-template/v<flet-version>/ (defaulting to ~/.flet/cache/build-template/v<flet-version>/) instead of re-fetching it via cookiecutter. The CLI also exports FLET_CACHE_DIR into the child Gradle process, so serious_python_android >= 1.0.1 lands its Python dist tarballs (python-android-dart-<py>-<abi>.tar.gz) in the same cache root by default — fixing the multi-minute "Creating app shell" / downloadDistArchive_* delay on every Android debug build. Custom --template URLs and the local-dev template path are unchanged (#6555, #6558) by @FeodorFitsner.
    • Bump the bundled build template's serious_python dependency from 1.0.0 to 1.0.1 so Android builds pick up the new persistent Python-tarball cache + conditional-GET revalidation introduced in serious_python 1.0.1 (#6558) by @FeodorFitsner.

    Bug fixes

    • Fix flet.Router's default on_view_pop navigating to the wrong URL when an outlet=True layout sits between two views in manage_views=True mode. Popping such a view now targets the previous view entry's resolved URL — skipping outlet layouts and componentless grouping routes — instead of chain[-2], which could equal the current view's URL and strand the page route, making the next navigation to it a no-op (#6533) by @FeodorFitsner.
    • Fix flet-audio.Audio.play()/seek() timing out when replaying after playback had completed: under the default ReleaseMode.RELEASE the source is freed on completion and is now re-prepared on replay (#6536, #6538) by @ndonkoHenri.
    • Fix ft.run(view=ft.AppView.FLET_APP_HIDDEN) briefly flashing the native window in the top-left corner during Windows desktop startup. The Windows runner now respects FLET_HIDE_WINDOW_ON_START and skips the first-frame Show() call so the window stays hidden until page.window.visible = True, matching the Linux desktop behavior; the same fix is applied to the flet build windows template runner so generated apps behave consistently. On Linux, pre-show window placement actions (page.window.center(), page.window.alignment) are now deferred until the window first becomes visible to avoid an analogous flash, and the window's focused state is preserved when a prevent_close handler cancels a close attempt (#5897, #5914, #6527) by @ihmily.

    Full Changelog: v0.85.2...v0.85.3

    Open source →
    Release notes

    Improvements

    • Allow [tool.flet.android.permission] values to be TOML inline tables in addition to booleans — each key = "value" entry adds an android:<key>="<value>" attribute to the generated <uses-permission> element, unlocking modifiers like android:maxSdkVersion and android:usesPermissionFlags that real-world Android permissions (e.g. Bluetooth LE) require. The boolean form and the --android-permissions CLI flag are unchanged; a non-empty inline table is always emitted, an empty table ({}) is treated as false, and invalid value types fail the build with a clear error (#6550, #6551) by @FeodorFitsner.
    • Add [tool.flet.android.provider] for declaring custom <provider> entries in the generated AndroidManifest.xml. Each table key is the provider's android:name; entries become android:<key>="<value>" attributes on the generated element. A reserved meta_data sub-table emits nested <meta-data> children (scalar values render as android:value="…"; inline-table values render as android:<k>="<v>" so android:resource="@xml/…" works). false / {} skip the entry; true and invalid value types fail the build with a clear error. The built-in androidx.core.content.FileProvider block is unchanged (#6556, #6559) by @FeodorFitsner.
    • Upgrade the bundled Pyodide runtime in the flet build web template from 0.27.5 to 0.27.7 (includes micropip 0.9.0) (#6549) by @FeodorFitsner.
    • Drop generated web/canvaskit/ build artifacts (canvaskit.js/.wasm/.symbols and the chromium/ and skwasm/skwasm_st variants) from the flet build web template — these are produced by the Flutter web build and should not have been committed into the cookiecutter template (#6549) by @FeodorFitsner.
    • Cache the downloaded flet-build-template.zip across builds. The build template is bound to an exact Flet version and is immutable, so on every flet build / flet debug after the first, the CLI now uses a previously-downloaded zip from $FLET_CACHE_DIR/build-template/v<flet-version>/ (defaulting to ~/.flet/cache/build-template/v<flet-version>/) instead of re-fetching it via cookiecutter. The CLI also exports FLET_CACHE_DIR into the child Gradle process, so serious_python_android >= 1.0.1 lands its Python dist tarballs (python-android-dart-<py>-<abi>.tar.gz) in the same cache root by default — fixing the multi-minute "Creating app shell" / downloadDistArchive_* delay on every Android debug build. Custom --template URLs and the local-dev template path are unchanged (#6555, #6558) by @FeodorFitsner.
    • Bump the bundled build template's serious_python dependency from 1.0.0 to 1.0.1 so Android builds pick up the new persistent Python-tarball cache + conditional-GET revalidation introduced in serious_python 1.0.1 (#6558) by @FeodorFitsner.

    Bug fixes

    • Fix flet.Router's default on_view_pop navigating to the wrong URL when an outlet=True layout sits between two views in manage_views=True mode. Popping such a view now targets the previous view entry's resolved URL — skipping outlet layouts and componentless grouping routes — instead of chain[-2], which could equal the current view's URL and strand the page route, making the next navigation to it a no-op (#6533) by @FeodorFitsner.
    • Fix flet-audio.Audio.play()/seek() timing out when replaying after playback had completed: under the default ReleaseMode.RELEASE the source is freed on completion and is now re-prepared on replay (#6536, #6538) by @ndonkoHenri.
    • Fix ft.run(view=ft.AppView.FLET_APP_HIDDEN) briefly flashing the native window in the top-left corner during Windows desktop startup. The Windows runner now respects FLET_HIDE_WINDOW_ON_START and skips the first-frame Show() call so the window stays hidden until page.window.visible = True, matching the Linux desktop behavior; the same fix is applied to the flet build windows template runner so generated apps behave consistently. On Linux, pre-show window placement actions (page.window.center(), page.window.alignment) are now deferred until the window first becomes visible to avoid an analogous flash, and the window's focused state is preserved when a prevent_close handler cancels a close attempt (#5897, #5914, #6527) by @ihmily.
    Open source →
    Release notes

    Bug fixes

    • Defer pre-show window placement on Linux (centerWindow(), setWindowAlignment()) until the window first becomes visible, so page.window.center() / page.window.alignment set before page.window.visible = True no longer flash the window during startup. Also preserve the focused state when a prevent_close handler cancels a close attempt (#5897, #5914, #6527) by @ihmily.
    Open source →
  8. 0.85.2 25 May 2026
    Release notes

    New features

    • Add Route(modal=True) to flet.Router for fullscreen-dialog modal overlays that don't replace the underlying view stack — closing the modal pops it without rebuilding the views underneath. Two flavours by placement: top-level modals are global (the base stack is rebuilt from the Router's last non-modal location), nested-child modals are local (the base stack is the chain above the modal in the route tree, so deep-link works from URL alone) (#6516) by @FeodorFitsner.
    • Add Route(recursive=True) to flet.Router so a route can match itself as its own descendant — one View per consumed URL segment, ideal for tree-shaped URLs of unbounded depth (/folder/a/b/c produces a 4-View stack; back-swipe walks one segment at a time). Non-recursive children are tried before self-recursion at every depth, so a specific sibling (e.g. example/:gp*) wins over the recursive :slug without duplicating it at every level (#6516) by @FeodorFitsner.

    Improvements

    • flet.Router's default on_view_pop now navigates to the matched chain's parent (chain[-2].resolved_path) instead of views[-2].route, which is robust against apps that share a View.route value between sibling tab roots to suppress switch transitions. Apps that install their own page.on_view_pop before page.render_views() still take precedence. Each sub-chain (base + modal) renders with its own LocationInfo, so is_route_active(...) inside a base view sees the base URL while a global modal is open over it (#6516) by @FeodorFitsner.

    Bug fixes

    • Fix cross-tab session contamination on Flet web: opening the same app URL in a duplicated browser tab no longer steals the original tab's output connection via sessionStorage-cloned _flet_session_id. REGISTER_CLIENT now rejects session reuse when the existing session still has a live connection, allocating a fresh session for the second tab while preserving legitimate single-tab reconnect after refresh or network blip (where connection is already None) (#6512, #6513) by @ihmily.
    Open source →
    Release notes

    No changes in the flet Dart package; version bumped for release coordination with flet.Router enhancements on the Python side (modal/recursive route flags, chain-based default pop).

    Open source →
  9. 0.85.1 13 May 2026
    Release notes

    Bug fixes

    • Fix TooltipTheme.decoration so it applies to controls using ft.Tooltip(...) when the tooltip does not explicitly set decoration or bgcolor (#6432, #6482) by @ndonkoHenri.
    • Fix flet-geolocator.Geolocator reliability on web and desktop: get_last_known_position() no longer crashes with TypeError: argument after ** must be a mapping, not NoneType and now returns Optional[GeolocatorPosition]; get_current_position() no longer hangs forever on web (Dart-side workaround for the upstream geolocator_web 4.1.3 inMicroseconds/inMilliseconds timeout typo) and uses sensible web defaults (time_limit: 30s, maximum_age: 5m); the previously-dropped configuration argument now actually reaches getCurrentPosition on the Dart side; the position stream is gated behind a registered on_position_change/on_error handler (with cancel-on-update to prevent leaks); and platform exceptions (LocationServiceDisabledException, PermissionDeniedException, PermissionDefinitionsNotFoundException, PermissionRequestInProgressException, PositionUpdateException, TimeoutException) are now translated into actionable error messages and surfaced to Python as RuntimeError without the default Exception: prefix (#6487) by @FeodorFitsner.
    • Fix PEP 508 markers on flet's oauthlib/httpx deps not actually excluding those packages under Pyodide: the flet build web package platform has been renamed from Pyodide to Emscripten to match platform.system() inside the Pyodide runtime, and the markers now use platform_system != 'Emscripten', so the exclusion works both via flet build and a direct micropip.install("flet") in a Pyodide REPL. Requires serious_python >= 1.0.0, which is now pinned in the flet build template (#6492) by @FeodorFitsner.
    Open source →
    Release notes

    No changes in the flet Dart package; version bumped for release coordination with flet-geolocator fixes on the Python side.

    Open source →
  10. 0.85.0 08 May 2026
    Release notes

    New features

    • Add configurable built-in, custom, hidden, and normal/fullscreen-specific controls to flet-video; Video.take_screenshot() for capturing video frames; and Video.on_position_change/Video.on_duration_change events (#6463) by @ndonkoHenri.
    • Add declarative ft.Router component for @ft.component apps with nested routes, layout routes with outlets, dynamic segments, optional segments, splats, custom regex constraints, data loaders, active link detection, authentication patterns, and manage_views=True mode for view-stack navigation with swipe-back gestures and AppBar back button on mobile (#6406) by @FeodorFitsner.
    • Add ft.use_dialog() hook for declarative dialog management from within @ft.component functions, with frozen-diff reactive updates and automatic open/close lifecycle (#6335) by @FeodorFitsner.
    • Add scrollable, pin_leading_to_top, and pin_trailing_to_bottom properties to NavigationRail for scrollable content with optional pinned leading/trailing controls (#1923, #6356) by @ndonkoHenri.
    • Add scroll support to ResponsiveRow for responsive layouts whose content exceeds the available height (#2590, #6417) by @ndonkoHenri.
    • Add issues property to CodeEditor (along with Issue and IssueType types) for displaying code analysis error markers in the gutter, with analysis performed on the Python side (#6407) by @FeodorFitsner.
    • Add Page.pop_views_until() to pop multiple views and return a result to the destination view (#6326, #6347) by @brunobrown.
    • Make NavigationDrawerDestination.label accept custom controls and add NavigationDrawerTheme.icon_theme (#6379, #6395) by @ndonkoHenri.
    • Add local_position and global_position to DragTargetEvent for target-relative and global pointer coordinates (#6387, #6401) by @ndonkoHenri.
    • Added PCM16 streaming to AudioRecorder, including on_stream chunks and direct upload support via AudioRecorderUploadSettings (#5858, #6423) by @ndonkoHenri.
    • Add Page.theme_animation_style for customizing the duration and curve of the theme cross-fade between theme and dark_theme (or disabling it with AnimationStyle.no_animation()), exposing Flutter's MaterialApp.themeAnimationStyle (#6476) by @FeodorFitsner.

    Breaking changes

    • Remove deprecated module-level margin, padding, border, and border_radius helper functions (all(), symmetric(), only(), horizontal(), vertical()) in favor of the corresponding Margin, Padding, Border, and BorderRadius classmethods (#6425) by @ndonkoHenri.

    Deprecations

    • Deprecate DragTargetEvent.x, DragTargetEvent.y, and DragTargetEvent.offset; use local_position for target-relative coordinates or global_position for global coordinates instead. These APIs are scheduled for removal in 0.88.0 (#6387, #6401) by @ndonkoHenri.
    • Deprecate Video.show_controls; set Video.controls to None to hide controls. This API is scheduled for removal in 0.88.0 (#6463) by @ndonkoHenri.
    • Deprecate Video.playlist_add() and Video.playlist_remove(); mutate Video.playlist directly with list methods such as append() and pop(). These APIs are scheduled for removal in 0.88.0 (#6463) by @ndonkoHenri.

    Bug fixes

    • Fix control diffing for controls nested inside @value dataclass objects so they keep the nearest control parent/page context, and restore optional structured properties that are cleared to None and later set again (#6463) by @ndonkoHenri.
    • Fix Page and View vertical centering when scrolling is enabled, including hidden scrollbars, so short content remains centered in the viewport (#6446, #6450) by @ndonkoHenri.
    • Reduce Linux memory retention when repeatedly removing flet_video.Video controls by linking media_kit video apps against mimalloc in run and build flows (#6164, #6416) by @ndonkoHenri.
    • Fix flet build and flet publish dependency parsing for project.dependencies and Poetry constraints with </<=, and add coverage for normalized requirement handling (#6332, #6340) by @td3447.
    • Fix CodeEditor background not filling the entire area when expand=True (#6407) by @FeodorFitsner.
    • Handle unbounded width in ResponsiveRow with an explicit error, treat child controls with col=0 as hidden, and clarify Container expansion behavior when alignment is set (#1951, #3805, #5209, #6354) by @ndonkoHenri.
    • Fix find_platform_image selecting incompatible icon formats (e.g. .icns on Windows) by ranking glob results per target platform (#6381) by @HG-ha.
    • Fix page.window.destroy() taking several seconds to close Windows desktop apps when prevent_close is enabled (#5459, #6428) by @ndonkoHenri.
    • Fix Page.show_drawer(), close_drawer(), and root/top view accessors (appbar, drawer, navigation_bar, controls, ...) failing with TypeError under Page.render_views() by unwrapping component-wrapped views and normalizing single-view returns (#6413, #6414) by @FeodorFitsner.
    • Fix auto_scroll on scrollable controls silently doing nothing unless scroll was also explicitly set (#6397, #6404) by @ndonkoHenri.
    • Fix Flet web returning index.html with a 200 OK for missing asset files; requests for paths with a file extension other than .html now return a proper 404, while route-like paths still fall back to index.html for SPA routing (#6425) by @ndonkoHenri.
    • Fix Lottie failing to load local asset files on Windows desktop (and unreliably on other desktop platforms), so animations referenced by src="file.json" from the app's assets/ directory now display correctly (#6386, #6426) by @ndonkoHenri.
    • Fix Page.on_resize and Page.on_media_change not firing after mobile orientation changes (#6457, #6423) by @ndonkoHenri.
    • Fix flet pack desktop packaging so Windows and Linux bundles include the expected client archive, and Windows taskbar pins point to the packed app instead of the cached flet.exe (#5151, #6403) by @ndonkoHenri.
    • Fix environment variable priority in flet build template: inherit from Platform.environment and use putIfAbsent for FLET_* variables so pre-set system env vars are not overwritten (#6394) by @Bahtya.
    • Fix NavigationBarDestination.selected_icon rendering wrongly when provided as an Icon control (#6460, #6468) by @ndonkoHenri.
    • Fix 3- and 4-digit hex color shorthand (e.g. #c00, #fc00) rendering as invisible by expanding them to their full 6/8-digit forms (#6419, #6421) by @ndonkoHenri.
    • Fix LineChartEvent.spots returning undecoded MessagePack extension values instead of LineChartEventSpot objects (#6443, #6468) by @ndonkoHenri.
    • Fix LineChart (and other charts) silently dropping custom ChartAxisLabel entries whose value matched a tick only after floating-point rounding (e.g. 0.1, 0.2, 0.3) by switching label lookup to a tolerance-based comparison scaled to the axis interval (#6445, #6459) by @KangZhaoKui.
    • Fix absolute-path src (e.g. Image(src="/images/foo.svg")) breaking on web when the app is mounted at a non-root URL, pass data:/blob: URIs through the asset resolver unchanged, preserve origin-relative semantics when assets_dir is unset, and add a window.flet.assetsDir JS-interop bridge so embedding hosts can supply assets_dir to the top-level FletApp (#6470) by @FeodorFitsner.
    • Fix unbounded browser memory growth in MatplotlibChart on Flutter web (CanvasKit/WASM) during animations by replacing the Canvas + capture() rendering path with a dedicated MatplotlibChartCanvas widget that composites matplotlib diff frames in CPU memory; also fixes Safari async PNG decode (EncodingError: Loading error.), a render/figure.savefig() race that crashed the toolbar Download, and pan/zoom playback lag from buffered pointer events (#6473) by @FeodorFitsner.
    • Fix Duration fields (and other int-typed properties) silently decoding to 0 when given a Python float (e.g. Duration(seconds=2.0) causing Page.theme_animation_style to end instantly) by coercing double to int in the Dart-side parseInt (#6478, #6480) by @FeodorFitsner.

    Documentation

    • Improve CrocoDocs API reference rendering with formatted signatures, modern type annotations, and cleaner cross-reference labels for extension packages (#6442) by @ndonkoHenri.
    • Add crocodocs watch command for hot-reload docs development with file-watching, debounced regeneration, and optional child process management (#6402) by @ndonkoHenri.

    Other changes

    • Add a declarative ReorderableListView app example showing add, remove, and reorder flows with stable item identity (#6374) by @FeodorFitsner.
    • Centralize Linux apt dependencies in flet.utils.linux_deps and update CI workflows and publish docs to consume them dynamically (#6357, #6383) by @ndonkoHenri.
    • Bump serious_python to 0.9.12 in the flet build template (#6461) by @FeodorFitsner.
    Open source →
    Release notes

    New features

    • Add parseControlWidget() and parseControlWidgets() utilities for converting Flet controls in protocol values to Flutter widgets (#6463) by @ndonkoHenri.

    Bug fixes

    • Preserve viewport minimum constraints for short scrollable View, Column, and Row content so main-axis alignment still applies (#6446, #6450) by @ndonkoHenri.
    • Handle unbounded width in ResponsiveRow with an explicit error and treat child controls with col=0 as hidden at the current breakpoint (#1951, #3805, #6354) by @ndonkoHenri.
    • Fix page.window.destroy() taking several seconds to close Windows desktop apps when prevent_close is enabled (#5459, #6428) by @ndonkoHenri.
    • Fix flet pack desktop packaging so Windows and Linux bundles include the expected client archive, and Windows taskbar pins point to the packed app instead of the cached flet.exe (#5151, #6403) by @ndonkoHenri.
    • Resolve absolute-path src (e.g. Image(src="/images/foo.svg")) against assets_dir on web so embedded apps mounted at non-root URLs load assets correctly, pass data:/blob: URIs through unchanged, preserve origin-relative semantics when assets_dir is unset, and add a window.flet.assetsDir JS-interop bridge so embedding hosts can supply assets_dir to the top-level FletApp (#6470) by @FeodorFitsner.
    • Coerce double to int in parseInt so float values passed into int-typed protocol fields (e.g. Duration(seconds: 2.0)) decode correctly instead of falling back to the default (#6478, #6480) by @FeodorFitsner.
    Open source →
  11. 0.84.0 01 Apr 2026
    Release notes

    Improvements

    • Migrate Flet docs from MkDocs to Docusaurus for a more maintainable documentation pipeline (#6359) by @FeodorFitsner.
    • Migrate examples into standalone projects with metadata, dependencies, and assets to improve discovery and make every sample runnable as-is (#6281, #6355) by @InesaFitsner.

    Bug fixes

    • Fix flet pack on macOS after the move to GitHub Releases by handling extracted app bundles, matching the cached tarball name, and cleaning up loose frameworks during packaging (#6358, #6361) by @FeodorFitsner.
    Open source →
  12. 0.83.1 29 Mar 2026
    Release notes

    Bug fixes

    • Fix solitaire tutorial and drag examples to use local_delta.x and local_delta.y instead of removed delta_x and delta_y (#6317, #6344) by @Krishnachaitanyakc.
    • Fix inherited dataclass field validation rules applying to overridden subclass fields and breaking flet-datatable2 on 0.83.0 (#6349, #6350) by @ndonkoHenri.
    Open source →
  13. 0.83.0 26 Mar 2026
    Release notes

    New features

    Improvements

    • Speed up control diffing and nested value tracking with sparse Prop updates and @value types (#6098, #6270, #6117, #6296) by @FeodorFitsner.
    • Consolidate app/build templates into the monorepo and publish pre-release flet packages and template artifacts from CI (#6306, #6331) by @FeodorFitsner.
    • Move desktop client binaries from PyPI wheels to GitHub Releases and unify desktop packaging around flet-desktop (#6290, #6309) by @FeodorFitsner.
    • Lightweight dataclass validation and deprecation with Annotated + auto-added deprecation admonitions in docs (#6278) by @ndonkoHenri.

    Bug fixes

    Open source →
    Release notes

    New features

    Improvements

    • Speed up control diffing and nested value tracking with sparse Prop updates and @value types (#6098, #6270, #6117, #6296) by @FeodorFitsner.
    • Consolidate app/build templates into the monorepo and publish pre-release flet packages and template artifacts from CI (#6306, #6331) by @FeodorFitsner.
    • Move desktop client binaries from PyPI wheels to GitHub Releases and unify desktop packaging around flet-desktop (#6290, #6309) by @FeodorFitsner.

    Bug fixes

    Open source →
  14. 0.82.2 10 Mar 2026
    Release notes

    Bug fixes

    • Lazy-load optional auth dependencies to avoid import-time failures in web/Pyodide startup (#6258, #6280) by @ndonkoHenri.
    • Pin binaryornot below 0.5 to fix build-template UTF-8 decode errors (#6276, #6279) by @ndonkoHenri.
    Open source →
  15. 0.82.1 09 Mar 2026

    Nothing published for this version

  16. 0.82.0 04 Mar 2026
    Release notes

    New features

    • Add Auth0 audience support through OAuth authorization_params (#3775, #6205).
    • Add Map.get_camera(), MapEventType, and richer MapEvent payloads in flet-map (#6196, #6208).

    Improvements

    • Refactor ads controls: InterstitialAd is now a Service, and BannerAd is now a LayoutControl (#6194, #6235).
    • Improve CodeEditor with Chinese pinyin input support and aligned gutter rendering (#6211, #6243, #6244).
    • Add the Trolli app declarative example rewrite (#6242).

    Bug fixes

    • Fix disabled-state handling across Tabs, TabBar, Tab, and TabBarView (#6220, #6224).
    • Fix a WebView null-check crash (Null check operator used on a null value) (#6238).

    Other changes

    • Pin internal Flet package dependencies across all Flet packages (#6222, #6247).
    • Update Flutter to 3.41.4 and refresh dependencies (#6245).
    Open source →
    Release notes

    Improvements

    • Refactor ads controls: InterstitialAd is now a Service, and BannerAd is now a LayoutControl (#6194, #6235).
    • Improve CodeEditor with Chinese pinyin input support and aligned gutter rendering (#6211, #6243, #6244).

    Bug fixes

    • Fix disabled-state handling across Tabs, TabBar, Tab, and TabBarView (#6220, #6224).
    Open source →
  17. 0.81.0 24 Feb 2026
    Release notes

    New features

    • Add Camera control (#6190).
    • Add CodeEditor control (#6162).
    • Add PageView control (#6158).
    • Add color picker controls based on flutter_colorpicker (#6109).
    • Add Matrix4-based LayoutControl.transform and RotatedBox control (#6198).
    • Add LayoutControl.on_size_change event for size-aware layouts (#6099).
    • Add Hero animations (#6157).
    • Add clipboard image/file set and get APIs (#6141).
    • Add web FilePicker with_data support for file content (#6199).
    • Add platform locale info and locale change events (#6191).
    • Add ignore_up_down_keys to TextField and CupertinoTextField (#6183).
    • Add flet build --artifact and iOS simulator build targets (#6074, #6188).

    Improvements

    • Optimize object_patch memory churn (#6204).
    • Skip component migrate/diff when function signatures differ (#6181).

    Bug fixes

    • Fix memory leaks in Flet web app (#6186).
    • Fix desktop window frameless/titlebar update sync and progress bar clearing (#6114).
    • Fix first-time button style patching and clear stale style state (#6119).
    • Fix map layer rebuilds on marker updates (#6113).
    • Fix AlertDialog and CupertinoAlertDialog barrier color updates (#6097).
    • Fix ControlEvent runtime type hints (#6102).

    Other changes

    • Bump Flutter to 3.41.2.
    • Register MIME types for .mjs and .wasm (#6140).
    Open source →
    Release notes

    New features

    • Add Camera control (#6190).
    • Add CodeEditor control (#6162).
    • Add PageView control (#6158).
    • Add color picker controls based on flutter_colorpicker (#6109).
    • Add Matrix4-based LayoutControl.transform and RotatedBox control (#6198).
    • Add LayoutControl.on_size_change event for size-aware layouts (#6099).
    • Add Hero animations (#6157).
    • Add clipboard image/file set and get APIs (#6141).
    • Add web FilePicker with_data support for file content (#6199).
    • Add platform locale info and locale change events (#6191).
    • Add ignore_up_down_keys to TextField and CupertinoTextField (#6183).

    Improvements

    • Optimize object_patch memory churn (#6204).
    • Skip component migrate/diff when function signatures differ (#6181).

    Bug fixes

    • Fix memory leaks in Flet web app (#6186).
    • Fix desktop window frameless/titlebar update sync and progress bar clearing (#6114).
    • Fix first-time button style patching and clear stale style state (#6119).
    • Fix map layer rebuilds on marker updates (#6113).
    • Fix AlertDialog and CupertinoAlertDialog barrier color updates (#6097).
    • Fix ControlEvent runtime type hints (#6102).

    Other changes

    • Bump Flutter to 3.41.2.
    • Register MIME types for .mjs and .wasm (#6140).
    Open source →
  18. 0.80.5 29 Jan 2026
    Release notes
    • Fix memory leak in Flet web apps (#6089).
    • feat: add LaTeX support in ft.Markdown (#6069).
    • Avoid FletApp control messing with root app routing (#6086).
    • Include material and cupertino icon data in PyInstaller hook (#6072).
    Open source →
  19. 0.80.4 23 Jan 2026
    Release notes
    • fix: Enable TextButton style and full-width Dropdown (#6048).
    • flet-video: add mpv_properties to VideoConfiguration (#6041).
    • Refactor Icons and CupertinoIcons proxies for member caching and iteration (#6055).
    • Flutter 3.38.7.
    Open source →
  20. 0.80.3 22 Jan 2026
    Release notes
    • Lazy loading of icons, theme for faster app startup (#6043).
    • feat: add locale prop to CupertinoDatePicker, DatePicker, DateRangePicker, TimePicker (#6030).
    • Allow installing Flet packages in runtime with uv (#6037).
    • Python wheels for Ubuntu 20.04-24.04 (#6035).
    • Disable Rive in desktop client light (#6032).
    • Fix desktop light package versioning (#6031).
    • Rive 0.14.0 (#6025).
    • fix: Convert datetime instances to UTC while passing over the wire (#6023).
    • feat(flet-charts): Allow badge_position and title_position of PieChartSection accept values >= 1.0 (#6024).
    • Add position details to GestureDetector.on_tap event (#6016).
    • Fix Android platform check to exclude web (#6013).
    Open source →
    Release notes
    • feat: add locale prop to CupertinoDatePicker, DatePicker, DateRangePicker, TimePicker (#6030).
    • Rive 0.14.0 (#6025).
    • feat(flet-charts): Allow badge_position and title_position of PieChartSection accept values >= 1.0 (#6024).
    • Add position details to GestureDetector.on_tap event (#6016).
    • Fix Android platform check to exclude web (#6013).
    • feat: parseEnum utility function.
    Open source →
  21. 0.80.2 14 Jan 2026
    Release notes
    • OAuth fixes and updated examples (#5996).
    • Examples cleanup (#5997).
    • Fix wrong LinearGradient alignment defaults + allow multiple use of --exclude option in flet build (#5986).
    • Update TypeVar definition for covariant typing in Ref class (#5994).
    • feat: add on_long_press and on_hover events to IconButton (#5984).
    • replace all asyncio.iscoroutinefunction with inspect.iscoroutinefunction (#5928).
    • Fix: Control with ID xxx is not registered for flet_permission_handler when using Python 3.14 (#5896).
    Open source →
  22. 0.80.1 02 Jan 2026
    Release notes
    • Fix flet publish to sub-directories, Icons Browser and other Gallery examples updated #5964.
    Open source →
  23. 0.80.0 25 Dec 2025
    Release notes
    Open source →
  24. 0.28.3 20 May 2025
    Release notes
    • New: Multiple subscribers can subscribe to a published topic by send_all_on_topic (#5303)
    • Fixed: Local Images Not Rendering in Android App using Flet 0.27.6 (#5198)
    • Fixed: FilePicker.save_file() opens blank gray screen in APK build (works fine in VS) (#5301)
    • Fixed: Routing / Navigation broken since flet 0.28.2 (#5302)
    Open source →
  25. 0.28.2 10 May 2025
    Release notes
    • Fixed missing imports in __init__.py (#5292).
    • Fixed: GestureDetector should have at least one event handler defined (#5293).
    Open source →
  26. 0.28.1 08 May 2025

    Nothing published for this version

  27. 0.28.0 08 May 2025
    Release notes
    • feat(cli): flet -V as alternative to flet --version (#4791)
    • New Features and Flutter 3.29 (#4891)
    • Fixed: Dropdown.expand has no effect (#5042)
    • feat: expose events (on_double_tap, on_pan_start) in WindowDragArea (#5043)
    • feat: custom ReorderableListView drag handle listeners (#5051)
    • Fixed: LineChartDataPoint.tooltip not properly rendered (#5105)
    • Fixed: broken code in Page.__on_authorize_async (#5154)
    • Remove Flet v0.25 deprecations (#5155)
    • Prevent platform back button from popping a route with pop confirmation event (#5280)
    • Fixed: SearchBar does not handle capitalization correctly (#5014)
    • Fixed: FilePicker upload fails if original filename is modified (#5037)
    Open source →
  28. 0.27.6 11 Mar 2025
    Release notes
    • Fix flet build: allow dependencies with commas (#5033)
    • Show app startup screen by default (#5036)
    • fix: Textfield cursor position changes when modifying field content in on_change (#5019)
    • Remove deprecated Control.update_async() method (#5005)
    • fix: incorrect positioning of non-FAB controls assigned to page.floating_action_button (#5049)
    Open source →
  29. 0.27.5 05 Mar 2025
    Release notes
    • Added FletApp.showAppStartupScreen and FletApp.appStartupScreenMessage properties.
    • Added tool.flet.splash.icon_bgcolor and tool.flet.splash.icon_dark_bgcolor settings for Android splash screen icon image.
    • Added tool.flet.app.boot_screen and tool.flet.app.startup_screen settings for customizing Flet app "loading" screens.
    • feat: Dropdown.menu_width property (#5007)
    • PBKDF2 iteration count increased to 600,000 (#5023)
    Open source →
  30. 0.27.4 01 Mar 2025
    Release notes
    • Fix: do not remove flutter-packages on re-build if dev_packages configured.
    Open source →
  31. 0.27.3 28 Feb 2025
    Release notes
    • Fixes to make flet build work in CI environment (#4993)
    Open source →
  32. 0.27.2 26 Feb 2025
    Release notes
    • Error on second flet build run "Because {app} depends on flet_{package} from path which doesn't exist" (#4955)
    • Editable packages in pyproject.toml to install from a path by flet build command (#4963)
    • Setting Android manifest <application> element properties in pyproject.toml (#4977)
    • Fixed regression: Added back Control.build() method.
    Open source →
  33. 0.27.1 22 Feb 2025
    Release notes
    • Fixed: binary file operations should not specify encoding.
    Open source →
  34. 0.27.0 22 Feb 2025
    Release notes
    • DropdownMenu control (#1088)
    • feat: ReorderableListView Control (#4865)
    • Remove v0.24.0 deprecations #4932)
    • Implement Container.dark_theme property (#4857)
    • Upgrade to Pyodide 0.27 for httpx Support (#4840)
    • Remove CupertinoCheckbox.inactive_color in favor of fill_color (#4837)
    • flet build: use Provisioning Profile to sign iOS app archive (.ipa), deprecate --team option (#4869)
    • feat: flet doctor CLI command (#4803)
    • feat: implement button themes (for ElevatedButton, OutlinedButton, TextButton, FilledButton, IconButton ) (#4872)
    • ControlEvent.data should be of type Optional[str] and default to None (#4786)
    • flet build: add --source-packages to allow installing certain Python packages from source distros (#4762)
    • disable markup for flet-cli stdout logs (#4796)
    • Fixed: Disable rich's Markup for stdout logs (#4795)
    • Fixed: Setting SearchBar.bar_border_side isn't visually honoured (#4767)
    • Fixed: Dropdown: Long options cause the down-arrow to overflow (#4838)
    • Fixed: CupertinoSlider initialisation does not allow values less then zero/greater then 1 (#4853)
    • Fixed: Same code shows different appearance in Flet APP/Web/PC local. (#4855)
    • Fixed: Transforming scale renders a grey screen (#4759)
    • Fixed: UnicodeDecodeError when using accented characters in manifest.json (#4713)
    • Fixed: Implement SearchBar.blur() to programmatically unfocus the bar (#4827)
    Open source →
  35. 0.26.0 26 Jan 2025
    Release notes
    • Flutter extensions: flet_* packages moved to separate repositories (#4721)
    • Automatic installation of Flutter, JDK and Android SDK (#4721)
    • Migrated to Flutter 3.27.0 (#4593)
    • New control properties, Flutter 3.27 fixes (#4703)
    • Optional on-demand creation of ListView.controls (#3931)
    • Reset InteractiveViewer transformations (#4391)
    • Passthrough of mouse events from main window to other applications (#1438)
    • Remove v0.26.0-related deprecations (#4456)
    • Implemented Window.ignore_mouse_events (#4465)
    • Adding Google/Android TV platform support (#4581)
    • Remove Optional[] from predefined typing *Values (#4702)
    • Throttle InteractiveViewer update events (#4704)
    • Fixed: Update project_dependencies.py (#4459)
    • Fixed: SafeArea object has no attribute _SafeArea__minimum (#4500)
    • Fixed: Tooltip corruption in Segment and BarChartRod on update() (#4525)
    • Fixed: Setting CheckBox.border_side.stroke_align to an Enum fails (#4526)
    • Fixed: ControlState should be resolved based on user-defined order (#4556)
    • Fixed: broken Dismissible.dismiss_direction (#4557)
    • Fixed: Fix Rive not updating (#4582)
    • Fixed: DatePicker regression with first and last dates (#4661)
    • flet build command: Copy flutter-packages, support for platform-specific dependencies (#4667)
    • Fixed: CupertinoBottomSheet applies a red color and yellow underline to Text content (#4673)
    • Fixed: setting ButtonTheme displays a grey screen (#4731)
    • Fixed: Textfield input border color considers user-specified border_color property (#4735)
    • Fixed: make Tooltip.message a required parameter (#4736)
    Open source →
  36. 0.25.2 13 Dec 2024
    Release notes

    Bug fixes

    • Fix flet publish creates broken website if no requirements.txt or pyproject.toml found (#4493).
    • Fix PyInstaller hook to avoid download Flet app bundle on first run (#4549).
    • Support git, path, url Poetry-style dependencies in pyproject.toml (#4554).
    • Fixed broken Map.center_on() and default animations (#4519).
    • Fixed Tooltip corruption in Segment and BarChartRod on update() (#4525).
    • Fixed Setting CheckBox.border_side.stroke_align to an Enum fails (#4526).
    • Fixed ControlState should be resolved based on user-defined order (#4556).
    • Fixed broken Dismissible.dismiss_direction (#4557).
    Open source →
  37. 0.25.1 29 Nov 2024
    Release notes

    Changes

    • Added InteractiveViewer programmatic transformations (#4451).

    Bug fixes

    • Fixed flet build creates bundle but running it gives ImportError: No module named main error (#4444).
    • Fixed hook-flet with wrong import module (#4447).
    • Fixed "flutter/runtime/dart_vm_initializer.cc" error on Linux (#4443).
    Open source →
  38. 0.25.0 28 Nov 2024
    Release notes

    New controls

    • Mobile Ads (Banner and Interstitial) (details and example).
    • Button control (#4265) - which is just an alias for ElevatedButton control.

    Breaking changes

    • Refactor Badge Control to a Dataclass; added new badge property to all controls (#4077).

    Other changes

    • Added {value_length}, {max_length}, and {symbols_left} placeholders to TextField.counter_text (#4403).
    • Added --skip-flutter-doctor to build cli command (#4388).
    • WebView enhancements (#4018).
    • Map control enhancements (#3994).
    • Exposed more Theme props (#4278, #4278).
    • Exposed more properties in multiple Controls (#4105)
    • Added __contains__ methods in container-alike Controls (#4374).
    • Added a custom Markdown code theme (#4343).
    • Added barrier_color prop to dialogs (#4236).
    • Merged icon and icon_content props into icon: str | Control (#4305).
    • Migrated colors and icons variables to Enums (#4180).
    • TextField: suffix_icon, prefix_icon and icon can be Control or str (#4173).
    • Added --pyinstaller-build-args to flet pack CLI command (#4187).
    • Made SearchBar's view height adjustable; added new properties (#4039).
    • Bumped Rive version and fixed Linux app build template for rive_common.

    Bug fixes

    • Fixed Icon rotation (#4384).
    • Fixed regression in Markdown.code_theme when using MarkdownCodeTheme enum (#4373).
    • Fixed Segment and NavigationBarDestination accept only string tooltips (#4326).
    • Display informative message when date has wrong format (#4019).
    • Fixed MapConfiguration.interaction_configuration is not honoured (#3976).
    • Fixed Video.jump_to() fails with negative indexes (#4294).
    • Fixed condition in AppBar.tooltip_opacity (#4280).
    • Fixed wrong type (asyncio.Future -> concurrent.futures.Future) and handle CancelledError (#4268).
    • Fixed clicking on CupertinoContextMenuAction doesn't close context menu (#3948).
    • Fixed dropdown max_menu_height (#3974).
    • Fixed prevent button style from being modified in before_update() (#4181).
    • Fixed disabling filled buttons is not visually respected (#4090).
    • when label is set, use MainAxisSize.min for the Row (#3998).
    • Fixed NavigationBarDestination.disabled has no visual effect (#4073).
    • Fixed autofill in CupertinoTextField (#4103).
    • Linechart: jsonDecode tooltip before displaying (#4069).
    • Fixed button's bgcolor, color and elevation (#4126).
    • Fixed scrolling issues on Windows (#4145).
    • Skip running flutter doctor on windows if no_rich_output is True (#4108).
    • Fixed TextField freezes on Linux Mint #4422](https://github.com/flet-dev/flet/pull/4422)).
    Open source →
  39. 0.24.1 03 Sep 2024
    Release notes
    • FIXED: Tooltip displays wrong message when used with IconButton, FloatingActionButton and PopupMenuButton (#3922)
    • FIXED: Image.src.base64 (#3919)
    Open source →
  40. 0.24.0 30 Aug 2024
    Release notes
    • NEW: Placeholder Control (#3646)
    • NEW: InteractiveViewer Control (#3645)
    • NEW: Adding Background/Foreground Services to GeoLocator UPDATE (#3803)
    • NEW: Container.ignore_interactions property (#3639)
    • NEW: Add rtl prop to more controls (#3641)
    • NEW: TextField.counter property (#3676)
    • NEW: window.icon: make the usage of relative paths possible (#3825)
    • NEW: Add event to flet_video to know what song is playing (#3772)
    • NEW: adds floating_action_button_theme property to Theme (#3771)
    • NEW: Added on_completed event to flet_video (#3758)
    • NEW: Add focus, on_focus, on_blur to SearchBar (#3417, #3752)
    • NEW: --no-rich-output flag to prevent rich output (#3708)
    • CHANGED: make Tooltip a dataclass which can be used in Control.tooltip (#3837)
    • CHANGED: wrap Views into a background container (#3820)
    • FIXED: export BottomSheetTheme (#3858)
    • FIXED: setting SearchBar.value to an empty string is not respected (#3872)
    • FIXED: add full-screen events to WindowEventType (#3857)
    • FIXED: snackbar margin (#3856)
    • FIXED: not error on inputfield when errorText is empty (#3855)
    • FIXED: flet.map is not available after building app (#3845)
    • FIXED: InputFilter clears TextField when an invalid character is entered (#3779)
    • FIXED: Dropdown.alignment not respected (#3737)
    • FIXED: scrolling issues in CupertinoPicker (#3678)
    • FIXED: scrolling controls are not able to scroll due to wrong super class call (#3702)
    • FIXED: Dismissible (#3690)
    • FIXED: PieChartEvent.type on web (#3611)
    • FIXED: Switch.width and height properties (#3670)
    • FIXED: parsing issues in TextStyle and *Event classes (#3551)
    • FIXED: issues with *Buttons (#3582)
    • Handle Multiple Trailing Controls in CupertinoAppBar (#3603)
    • Event: implement str and repr magic methods (#3601)
    • CHORE: remove handler-subscription and enhance event typing (#3808)
    • CHORE: improve type hint for OptionalEventCallable (#3659)
    • CHORE: Using Sequence instead of list (#3661)
    • CHORE: Bump Flutter packages (#3719)
    • CHORE: Cleanup (#3640)
    Open source →
  41. 0.23.2 25 Jun 2024
    Release notes
    • CHANGED: Enhance Typing of Event Handlers (#3523)
    • CHANGED: Delete Page.window.on_resize | deprecate Page.on_resize in favor of Page.on_resized (#3516)
    • CHANGED: View is not opened on tap (#3513)
    • FIXED: Slider.value defaults to min (#3503)
    • FIXED: add "hide" and "show" to WindowEventType enum (#3505)
    • FIXED: TypeError raised for isinstance check with Union in before_update method (#3499)
    • FIXED: Corrected isinstance check in SnackBar.before_update to use a tuple of types instead of Union, resolving TypeError: "Subscripted generics cannot be used with class and instance checks".
    • FIXED: Page.open() breaking after multiple calls.
    • FIXED: Typo in on_resized setter decorator
    Open source →
  42. 0.23.1 20 Jun 2024
    Release notes
    • FIX: Fix parseFloatingActionButtonLocation() to work on desktop (#3496)
    • FIX: Flet 0.23 crashes on Ubuntu 22.04 (#3495)
    • FIX: View.floating_action_button_location: conditionally use _set_attr.
    • FIX: Import ParamSpec from typing for Python >3.10.
    • FIX: replace len(list(filter(...))) by any(...).
    • FIX: Make window and browser_context_menu private, and expose respective getters.
    Open source →
  43. 0.23.0 18 Jun 2024
    Release notes
    • NEW: PermissionHandler control (#3276)
    • NEW: Map control (#3093)
    • NEW: Geolocator control (#3179)
    • NEW: AutoFillGroup Control (#3047)
    • NEW: Migrated to Flutter 3.22 (#3396)
    • NEW: An ability to access PubSubHub from outside Flet app (#3446)
    • NEW: TextStyle props: overflow, word_spacing, baseline (#3435)
    • NEW: Enable/disable browser context menu (#3434)
    • NEW: Container.color_filter property (#3392)
    • NEW: dropdown.Option.text_style property (#3293)
    • NEW: dropdown.Option.content property (#3456)
    • NEW: Video.configuration property (#3074)
    • NEW: Enable Impeller on Android and macOS (#3458)
    • NEW: AutoComplete: add selected_index read-only property (#3298)
    • NEW: Renamed NavigationDestination to NavigationBarDestination (#3172)
    • CHANGED: Prettify "build" command cli output (#3407)
    • CHANGED: Set colorScheme.primary as defaultSideColor (#3421)
    • CHANGED: feat(map): add missing py-events, better typing (#3464)
    • CHORE: Refactor numbers.dart utils (#3263)
    • CHORE: Global Code Refactoring/Clean-up (#3186)
    • CHORE: Cleanup (#3406)
    • CHORE: Error handling enhancements (#3175)
    • CHORE: Improve type hint for run_task and run_thread (#3459)
    • CHORE: Move page.window_* and page.browser_context_menu_* properties to Window and BrowserContextMenu classes (#3463)
    • FIX: Container.on_tap_down not called when on_click is not provided (#3442)
    • FIX: SnackBar bug #3311 (#3313)
    Open source →
  44. 0.22.2 09 May 2024 withdrawn

    Nothing published for this version

  45. 0.22.1 09 May 2024
    Release notes
    • AutoComplete control (#3003)
    • Added --exclude option to flet build command (#3125)
    • CupertinoTimePicker.alignment property (#3036)
    • Bump file_picker dependency to 8.0.3.
    • Fix latest flet-build-template version in development mode (#3021)
    • Fix flet --version command for source checkout.
    • LineChart: fix regression (#3033)
    • Fixed: OAuth expiry of token will hang fastapi server (#3150)
    • Fixed: Disabled the dropwown, but the color isnot gray (#2989)
    • Fixed: pubspec.yaml for adding custom Flutter packages requires dependency_overrides (#3187)
    • Fixed disabled dropdown (#3183)
    • Fixed default value for scrollbar thickness (#3147)
    • Fixed: autoreload, restrict eventhandler from restart on open (#3098)
    • Fixed (#3035) switch Flutter RichText to Text.rich (#3066)
    • Fixed: Markdown code block is not selectable (#1753)
    Open source →
  46. 0.22.0 10 Apr 2024
    Release notes
    • Controls enhancement (see #2882 for details).
    • Theme Enhancement (#2955).
    • Rive Control (#2841).
    • Control.parent property (#2906).
    • Container.on_tap_down event.
    • Add upload_endpoint_path into flet.fastapi.app (#2954).
    • Add checkbox border side state (#2973).
    • Global context for session (#2934).
    • Fix silent error in page.run_task (#2959).
    • Web: patch html title with app_name (#2909).
    • Container: fix triggered both on_click and on_long_press events (#2914).
    Open source →
  47. 0.21.2 18 Mar 2024
    Release notes
    • Add --android-adaptive-icon-background to flet build command.
    • Fix for mobile Safari: Store session ID in SessionStorage instead of window.name.
    • Fix _FletSocketServer__receive_loop_task error on Linux.
    • Replace deprecated (in Python 3.12) datetime.utcnow() with datetime.now(timezone.utc).
    • Fix a call to self.__executor.shutdown for Python 3.8.
    • Add client IP and user agent to a session ID.
    • Generate crypto-strong strings across the framework.
    Open source →
  48. 0.21.1 07 Mar 2024
    Release notes
    • Python dependencies bumped and loosen.
    • Fixed: "No supported WebSocket library detected." when running web app with Flet 0.21.0 (#2818).
    • Fix EventHandler: do not call it when converter returned None.
    Open source →
  49. 0.21.0 06 Mar 2024
    Release notes
    • FastAPI instead of built-in Fletd server. Mixed async/sync apps. (#2700).
    • CupertinoActivityIndicator Control (#2762).
    • LottieControl and Video v2 (#2673).
    • CupertinoActionSheet and CupertinoActionSheetAction controls (#2763).
    • CupertinoSlidingSegmentedButton and CupertinoSegmentedButton controls (#2767).
    • CupertinoTimerPicker and CupertinorPicker Controls (#2743).
    • CupertinoContextMenu and CupertinoContextMenuAction controls (#2772).
    • CupertinoDatePicker Control (#2795).
    • Page.on_app_lifecycle_state_change event (#2800).
    • More Semantics properties and SemanticsService control (#2731).
    • Fix container.dart for issue #2628 (#2701).(#2701)
    • Adaptive fixes (#2720).
    • label_style property for Checkbox, Switch, and Radio (#2730).
    • Additional properties (#2736).
    • Reorder __init__ (#2724).
    Open source →
  50. 0.20.2 18 Feb 2024
    Release notes
    • Move system_overlay_style from AppBar to Theme (#2667).
    • flet build command checks minimal Flutter SDK version.
    • Buttons turn to CupertinoDialogAction controls inside adaptive dialogs.
    • FletApp control takes control create factories from a parent app.
    Open source →
  51. 0.20.1 17 Feb 2024
    Release notes
    • Migrated to Flutter 3.19
    • Fixed scrolling behavior changes in scrollable controls.
    • Remove Page.design and replace with Page.adaptive (#2650).
    • Rename Control.on_update to Control.before_update (#2642).
    Open source →
  52. 0.20.0 14 Feb 2024
    Release notes
    • AppBar.system_overlay_style property (#2615).
    • New CupertinoButton props: filled, style.bgcolor, style.padding, text, icon, icon_color.
    • Added NavigationBar.border property which is used in adaptive mode only.
    • Page.design and Pagelet.design properties to force Material, Cupertino or Adaptive design language on entire app (#2607).
    • Page.media property with the data about obstructed spaces on the device (#2613).
    • Adaptive buttons (#2591).
    • Control.on_update() method for better custom controls.
    • --include-packages option and support for pubspec.yaml for custom Flutter packages plus API for adding custom Flutter packages.
    • Add rtl property to multiple controls (#2582).
    • Fix: Material icon is shown instead of Cupertino icon if its name is thesame (#2581).
    • TextStyle.letter_spacingproperty (#2574).
    • Audio, AudioRecorder, Video and WebView controls moved into separate Flutter packages (#2579).
    • Introduced Control.on_update() overridable method (#2578).
    • New AlertDialog properties: icon, bgcolor, elevation.
    • expand_loose property for Control and all controls that have expand property (#2561).
    • Pyodide v0.25.0.
    • flet create command to show verbose output (#2544).
    • AudioRecorder control (#2494).
    • Bugfix: flet pack --distpath deletes dist directory (#2500).
    • Added recursive adaptive property to all container-alike controls.
    • TextField.text_vertical_align property (#2496).
    • CupertinoButton Control (#2495).
    • CupertinoListTile control (#2487).
    • Support for custom Flutter controls (#2482).
    • Pagelet control (#2469).
    • Add AppBar.adaptive (#2458).
    • Cupertino Icons and Colors (#2433).
    • CupertinoTextfield control (#2417).
    • FloatingActionButtonLocation offset (#2411).
    Open source →
  53. 0.19.0 15 Jan 2024
    Release notes
    • flet build to apply Python SSL fix when packaging for iOS and Android (#2349).
    • Upgrade Android Gradle in flet build app template (#2350).
    • flet build -vv should run pip install with verbose output (#2351).
    • Add Python output/logging to troubleshoot empty screens on startup of built app (#2352).
    • flet build should raise an error when trying to package an app with native modules for iOS or Android (#2356).
    • flet build to add timestamp (hash) asset with Flet Python app to re-extract when code changes (#2289).
    • Handle/bypass if __name__ == "__main__" check on Android.
    • Support reading dependencies from pyproject.toml.
    • flet build to fix --base-url with surrounding slashes (#2369).
    • CupertinoAlertDialog, CupertinoDialogAction, adaptive property for AlertDialog (#2365).
    • Dismissible.confirmDismiss prop (#2359).
    • ListView.reverse and GridView.reverse props (#2335).
    • Text.style type Deprecation warning (#2286).
    • Add LineChartData.prevent_curve_over_shooting and LineChartData.prevent_curve_over_shooting_threshold props (#2354).
    • flet build to add checks to allow certain build commands according to "build_on" platform (#2343).
    • Fixed: flet build gives "OSError: [WinError 193] %1 is not a valid Win32 application" for some users (#2318).
    • Fixed: PubSub is not shared between pages in the same FastAPI app (#2368).
    • Fixed: check for DISPLAY instead of XDG_CURRENT_DESKTOP to check if linux machine is GUIless or not (#2373).
    Open source →
  54. 0.18.0 30 Dec 2023
    Release notes
    • flet build command to package Flet app for any platform (docs).
    • Added TextStyle for the Text control (#2270).
    • Refactor code, add Enum deprecation utils (#2259).
    • CupertinoAppBar control (#2278).
    • Fix AlertDialog content updating (#2277).
    • Fix FLET_VIEW_PATH ignored on linux (#2244).
    • MenuBar, SubMenuButton and MenuItemButton controls (#2252).
    • convert 'key' to a super parameter (#2258).
    Open source →
  55. 0.17.0 18 Dec 2023
    Release notes
    • SearchBar control (#2212).
    • CupertinoNavigationBar control (#2241).
    Open source →
  56. 0.16.0 14 Dec 2023
    Release notes
    • CupertinoSlider control and Slider.adaptive (#2224).
    • CupertinoRadio control and Radio.adaptive (#2225).
    • Fix NavigationBar.label_behavior (#2229).
    • CupertinoSwitch control (docs).
    • Disable fade-in effect on Flet app start.
    • Tab alignment bug fix (#2208).
    • Tab visibility (#2213).
    • Dark window title for Windows (#2204).
    • Fix ValueError on web page resize (#1564).
    Open source →
  57. 0.15.0 04 Dec 2023
    Release notes
    • ExpansionPanel and ExpansionPanelList controls (docs).
    • CupertinoCheckBox control, adaptive CheckBox (docs).
    • Additional control props (#2182):
      • Card.shape.
      • NavigationDestination.tooltip.
      • NavigationRail: elevation, indicator_color, indicator_shape.
      • BottomSheet: bgcolor, elevation.
    • Added Dropdown.Option.visible property.
    • Fix AlertDialog broken content when testing in Flet app (#2192).
    Open source →
  58. 0.14.0 29 Nov 2023
    Release notes
    • SelectionArea control (docs).
    • SegmentedButton control (docs).
    • ExpansionTile control (docs).
    • BottomAppBar control (docs).
    • Add console as a build argument (#2146).
    • --uac-admin flag added to flet pack command (#2149).
    • Bump Flutter dependencies.
    Open source →
  59. 0.13.0 24 Nov 2023
    Release notes
    • Dismissible Control (#2124).
    • TimePicker control (#2129).
    • Fixed: verify value limits (#2121).
    • Added thumb_icon to Switch (#2116).
    • Feature: TextField Input validation (#2101).
    Open source →
  60. 0.12.2 17 Nov 2023
    Release notes
    • Flutter 3.16.0
    • Added ´repr´ to Control class (#2091).
    • Added ´skip_route_change_event´ to ´page.go_async´ (#2092).
    Open source →

Every package, every release, already written down.

The archive is open and free. Watching your own project is what we are building next.

Browse the archive