Releases: flet-dev/flet
Releases · flet-dev/flet
Release list
v0.86.1
Improvements
flet-mcp'sget_apitool 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 returnednot foundbecause only classes were indexed. A newfunctionsbucket in the API builder extracts each package's re-exported public callables and renders them with asignature:line.get_apialso resolves enum member lookups inline:get_api("Colors", query="RED")now returns the matching members instead of erroring with a redirect tosearch_enum_members. Both changes remove wasted agent round-trips observed in production usage by @FeodorFitsner.
Bug fixes
- Fix
flet build windowsfailing on non-UTF-8 system locales (e.g. Simplified-Chinese Windows, code page 936/GBK) withwarning C4819escalated toerror C2220while 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 bumpsserious_pythonto 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 filefailure in web apps when the app package download fails. The Pyodide worker piped thepyfetch(app_package_url)response straight intounpack_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 checksresponse.okand raises a readableFailed 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 theflet buildtemplate (#6680) by @FeodorFitsner. - Remove unused
BasePagereturn type and import fromBaseControlandControlEvent(#6606) by @Iaw4tch. - Fix
GestureDetector.allowed_devicescrashing withtype 'List<dynamic>' is not a subtype of type 'List<String?>?'and preventing the control from rendering. Property values are deserialized from JSON asList<dynamic>, but the value was read viaget<List<String?>>(...), whose reified cast fails because aList<dynamic>is not aList<String?>. It's now read asList<dynamic>and each entry is converted to a string before parsing, restoringsupportedDevicesfiltering for Flutter'sGestureDetector(#6684) by @TURBODRIVER.
New Contributors
- @TURBODRIVER made their first contribution in #6684
Full Changelog: v0.86.0...v0.86.1
v0.86.0
New features
- Add support for Python
multiprocessingin packaged Flet desktop apps built withflet build macos,flet build windows, andflet build linux.multiprocessingAPIs such asProcess,ProcessPoolExecutor, thespawn/forkserverstart methods, and the resource tracker now work in packaged desktop apps. Previously, worker processes re-executedsys.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 viadart_bridge1.5.0+. The Python bootstrap also runs the app module as the realsys.modules["__main__"]withpython -msemantics, so top-level worker functions inmain.pycan be pickled correctly. When usingmultiprocessing, your app must follow normal Python multiprocessing rules: guardft.run(...)withif __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 buildandflet publish. Pick the runtime your app ships with via the new--python-versionflag (3.12 / 3.13 / 3.14), or let it be derived from[project].requires-pythonin yourpyproject.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 fromflet-dev/python-build's date-keyed manifest. Adding a future pre-release CPython line (e.g. 3.15 beta) is a one-row append withprerelease=True— opt-in only via an explicit--python-version 3.15orrequires-python = "==3.15.*", never the auto-resolved default. Requiresserious_python>= 4.0.0, now pinned in theflet buildtemplate. 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 viaFletBackend.of(context).openDataChannel()and announces it to Python by firing adata_channel_opencontrol event with{channel_name, channel_id}; the Python side declareson_data_channel_open: Optional[ft.EventHandler[ft.DataChannelOpenEvent]]and captures the channel viaself.get_data_channel(e.channel_id). Backed by a dedicatedPythonBridgeper channel in embedded native mode (4–7 GiB/s on M2 Pro) and by the defaultProtocolMuxedDataChannelFactoryin 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 viapostMessageTransferable ArrayBuffer. First consumer:flet-chartsMatplotlibChartCanvas, migrated from_invoke_methodPNG dispatch to a 1-byte-opcode data channel by @FeodorFitsner. - In-process Python transport (
dart_bridgeFFI).package:fletgains a third protocol transport alongside the UDS / TCP socket servers: it can run Flet's MsgPack protocol over an in-processdart_bridgebyte channel via aFletApp(channelBuilder: …)seam (thefletpackage stays Python-independent — it doesn't depend onserious_pythonor know aboutPythonBridge; 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 theflet buildtemplate 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'sdart_bridgeports 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 fromREGISTER_CLIENTby @FeodorFitsner. - Add
flet cleancommand that deletes thebuilddirectory of a Flet app — the Flutter bootstrap project, cached artifacts, and generated output — in a single step (#6233) by @ndonkoHenri. - Add
compression_qualitytoFilePicker.pick_files()for selecting the image compression quality used by supported platforms (#6573) by @ndonkoHenri. - Add
ConsentManagertoflet-adsfor 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 dedicatedft.DataChannelinstead of the control protocol: raw premultiplied RGBA straight to a GPU texture on local transports (desktop,flet run, Pyodide), automatic PNG fallback on remoteflet-websessions. The awaitablerender(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 plainwhile 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, mirroringImage.src. Ships with five gallery examples (photo viewer, plasma, Pillow paint, Mandelbrot explorer, Game of Life) and a docs page withRawImagevsImageguidance (#6674) by @FeodorFitsner.
Improvements
- Swift Package Manager for iOS/macOS builds (on by default).
flet build/flet debugnow 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 — currentlyflet-video(media_kit) — since Flutter then builds the whole app with CocoaPods. Force CocoaPods for other non-SPM packages with--no-swift-package-manager(orswift_package_manager = falseunder[tool.flet]). Flet does not change Flutter's global SPM configuration; the setting only selects howserious_pythonstages the runtime to match. When SPM is used (it has nopod installhook),flet buildsetsSERIOUS_PYTHON_DARWIN_SPMsoserious_python'spackagestep stages the runtime (Python/dart_bridge xcframeworks, the iOS native extensions, and the stdlib/site-packages/app resources) into the plugin'sPackage.swiftlayout on the host beforeflutter build, and exports theSP_NATIVE_SETcache-bust key into the build. Requires the SPM-capableserious_pythonrelease. - Smaller Android apps with no native-packaging config.
flet build apk/aabconsume 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 viazipimport, so the standard library is no longer duplicated per ABI. Apps no longer needuseLegacyPackaging/keepDebugSymbols— theflet buildAndroid template drops them; just useminSdk 23+. New--android-extract-packagesflag and[tool.flet.android].extract_packagesship "path-hungry" packages — those that read bundled data via__file__/pkg_resourcesinstead ofimportlib.resources— extracted to disk instead of inside the zip (most packages, includingcertifi, are zip-safe and need no entry). Requiresserious_pythonwith the native-mmap packaging (dart_bridge 1.4.0). - Pyodide is no longer pre-baked into the
flet buildtemplate. Eachflet build web/flet publishrun downloads the matchingpyodide-core-<version>.tar.bz2(plus the runtimemicropipandpackagingwheels) into a per-version cache at~/.flet/pyodide/<version>/and copies the files into the build output. Subsequent builds reuse the cache; the older0.27.5bundle 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-keyedmanifest.json(fetched once and cached under~/.flet/cache), the single source of truth shared withserious_python— replacing flet's hand-mirrored version table.flet buildforwards onlySERIOUS_PYTHON_VERSIONand letsserious_pythonderive the full version / build date / dart_bridge version from its own committed snapshot. The module exposesget_supported_python_versions()/get_default_python_version()(the previousSUPPORTED_PYTHON_VERSIONS/DEFAULT_PYTHON_VERSIONconstants are removed) (#6577) by @FeodorFitsner. flet --versionshows just the Flet and Flutter versions; the staticPyodide: …line and the globalflet.version.pyodide_versionexport are removed (the supported Python / Pyodide set now lives in python-build's manifest, not the CLI output) (#6577) by @FeodorFitsner.flet --version --jsonemits a machine-readable document — Flet/Flutter versions and the Linux build dependencies — for CI to read viajqinstead of importing Flet internals with `pyt...
v0.86.0.dev2
What's Changed
- Make auto_scroll follow in-place content growth by @FeodorFitsner in #6637
- fix(build): keep web apps on path routing through boot (no /#/, deep links survive) by @FeodorFitsner in #6639
- Fix auto_scroll end-following past code blocks / nested scrollables by @FeodorFitsner in #6642
- Fix O(N²) mount/unmount scans in Session.patch_control by @davidlawson in #6651
- Minor fix of changelog entry by @davidlawson in #6653
- flet-mcp: token-efficient get_api, ranked icon search, agent tool fixes by @FeodorFitsner in #6654
- Preserve ResponsiveRow child state across Row/Wrap layout switches by @FeodorFitsner in #6663
- feat: Multiprocessing support in packaged desktop apps by @ndonkoHenri in #6662
- Fix integration test failures caused by render overflow errors by @FeodorFitsner in #6664
New Contributors
- @davidlawson made their first contribution in #6651
Full Changelog: v0.86.0.dev1...v0.86.0.dev2
v0.86.0.dev1
What's Changed
- fix(ci): version flet-mcp like the other packages on publish by @FeodorFitsner in #6633
- fix(build): preserve flutter-packages on incremental builds (--skip-site-packages) by @FeodorFitsner in #6634
Full Changelog: v0.86.0.dev0...v0.86.0.dev1
v0.86.0.dev0
What's Changed
- Multi-version Python support (3.12 / 3.13 / 3.14) by @FeodorFitsner in #6577
- fix(flet-secure-storage): bump flutter_secure_storage 10.0.0 -> 10.3.1 to fix macOS data-protection keychain (-34018) on unsigned/dev apps by @EH-MLS in #6591
- feat(cli):
flet cleancommand + deprecate--clear-cacheflag offlet buildby @ndonkoHenri in #6590 - fix(typing): explicit handler signatures in
PubSubClientby @Iaw4tch in #6564 - chore: More docs + code improvements by @ndonkoHenri in #6589
- fix(android):
pickFirstslibc++_shared.soto unblock multi-plugin Flet apps by @ndonkoHenri in #6571 - Update CONTRIBUTING.md hello.py example to use modern
ft.run()andft.Page/ft.Textinstead of deprecated `flet.app by @Federicorao in #6582 - feat(
FilePicker): addcompression_qualityandcancel_upload_on_window_blurtopick_files()by @ndonkoHenri in #6573 - feat: add flet-spinkit extension package wrapping flutter_spinkit ^5.2.2 by @InesaFitsner in #6596
- Integrate dart-bridge into flet-0.86 (in-process FFI transport, multi-version Python, native-mmap, DataChannel) by @FeodorFitsner in #6601
- Lift app packaging into serious_python + SPM-by-default darwin builds by @FeodorFitsner in #6608
- Support Android TV in device info retrieval by @bl1nch in #6604
- 在android_sdk.py中令cmdline-tools-url检测到windows使用arm64架构时返回与x64相同的下载链接 by @xiaocai2011 in #6617
- Custom boot screen by @FeodorFitsner in #6616
- feat(flet-ads):
ConsentManagerfor AdMob UMP consent by @ndonkoHenri in #6615 - Rich progress bars for client and pyodide downloads by @FeodorFitsner in #6618
- feat:
flet teston-device integration testing + CI matrix by @FeodorFitsner in #6623 - Pin python-build 20260630 (armeabi-v7a for 3.13/3.14); serious_python 4.2.0 by @FeodorFitsner in #6628
- Add flet-mcp: MCP server for LLM agents by @FeodorFitsner in #6624
- ci: zizmor security checks by @ndonkoHenri in #6602
- Bump serious_python 4.2.1 / python-build 20260701 by @FeodorFitsner in #6630
New Contributors
- @EH-MLS made their first contribution in #6591
- @Iaw4tch made their first contribution in #6564
- @Federicorao made their first contribution in #6582
- @xiaocai2011 made their first contribution in #6617
Full Changelog: v0.85.3...v0.86.0.dev0
v0.85.3
What's Changed
Improvements
- Allow
[tool.flet.android.permission]values to be TOML inline tables in addition to booleans — eachkey = "value"entry adds anandroid:<key>="<value>"attribute to the generated<uses-permission>element, unlocking modifiers likeandroid:maxSdkVersionandandroid:usesPermissionFlagsthat real-world Android permissions (e.g. Bluetooth LE) require. The boolean form and the--android-permissionsCLI flag are unchanged; a non-empty inline table is always emitted, an empty table ({}) is treated asfalse, 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 generatedAndroidManifest.xml. Each table key is the provider'sandroid:name; entries becomeandroid:<key>="<value>"attributes on the generated element. A reservedmeta_datasub-table emits nested<meta-data>children (scalar values render asandroid:value="…"; inline-table values render asandroid:<k>="<v>"soandroid:resource="@xml/…"works).false/{}skip the entry;trueand invalid value types fail the build with a clear error. The built-inandroidx.core.content.FileProviderblock is unchanged (#6556, #6559) by @FeodorFitsner. - Upgrade the bundled Pyodide runtime in the
flet build webtemplate from0.27.5to0.27.7(includesmicropip0.9.0) (#6549) by @FeodorFitsner. - Drop generated
web/canvaskit/build artifacts (canvaskit.js/.wasm/.symbolsand thechromium/andskwasm/skwasm_stvariants) from theflet build webtemplate — 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.zipacross builds. The build template is bound to an exact Flet version and is immutable, so on everyflet build/flet debugafter 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 exportsFLET_CACHE_DIRinto the child Gradle process, soserious_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--templateURLs and the local-dev template path are unchanged (#6555, #6558) by @FeodorFitsner. - Bump the bundled build template's
serious_pythondependency from1.0.0to1.0.1so Android builds pick up the new persistent Python-tarball cache + conditional-GET revalidation introduced inserious_python1.0.1 (#6558) by @FeodorFitsner.
Bug fixes
- Fix
flet.Router's defaulton_view_popnavigating to the wrong URL when anoutlet=Truelayout sits between two views inmanage_views=Truemode. Popping such a view now targets the previous view entry's resolved URL — skipping outlet layouts and componentless grouping routes — instead ofchain[-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 defaultReleaseMode.RELEASEthe 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 respectsFLET_HIDE_WINDOW_ON_STARTand skips the first-frameShow()call so the window stays hidden untilpage.window.visible = True, matching the Linux desktop behavior; the same fix is applied to theflet build windowstemplate 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'sfocusedstate is preserved when aprevent_closehandler cancels a close attempt (#5897, #5914, #6527) by @ihmily.
Full Changelog: v0.85.2...v0.85.3
v0.85.3.dev1
What's Changed
- feat(build): cache flet-build-template.zip; share FLET_CACHE_DIR with Gradle by @FeodorFitsner in #6558
- feat(build): support custom entries in AndroidManifest via pyproject.toml by @FeodorFitsner in #6559
Full Changelog: v0.85.3.dev0...v0.85.3.dev1
v0.85.3.dev0
What's Changed
- docs(studio): add Flet Studio landing page and docs section by @FeodorFitsner in #6523
- docs(studio): give Studio its own footer column by @FeodorFitsner in #6524
- Tests and screenshots for Featured apps; fix for palette editor color picker by @InesaFitsner in #6521
- fix: add CMake definition to silence MSVC coroutine deprecation error by @ihmily in #6525
- docs(studio): Flet Studio launch post + updated gallery links by @FeodorFitsner in #6534
- Flet Studio update and skip builds for website/tools-only changes by @FeodorFitsner in #6537
- fix(router): pop to previous view, not the outlet layout URL by @FeodorFitsner in #6533
- Renamed titles of basic examples by @InesaFitsner in #6535
- docs: inject example headings dynamically from pyproject.toml metadata by @InesaFitsner in #6544
- Fix build web template: drop canvaskit artifacts, bump Pyodide to 0.27.7 by @FeodorFitsner in #6549
- refactor: rename and normalize example folder and package names by @InesaFitsner in #6545
- fix: honor AppView.FLET_APP_HIDDEN in Windows and Linux desktop runners by @ihmily in #6527
- feat(build): allow attributes on Android entries by @FeodorFitsner in #6551
- fix(flet-audio): replaying
Audioafter completion underReleaseMode.RELEASEraisesTimeoutExceptionby @ndonkoHenri in #6538
Full Changelog: v0.85.2...v0.85.3.dev0
v0.85.2
What's Changed
- fix: reject session reuse when existing connection is still active by @ihmily in #6513
- feat(router): add
modal/recursiveRoute flags + chain-based pop by @FeodorFitsner in #6516 - docs: add 0.85.2 changelog entry for #6513 session reuse fix by @FeodorFitsner in #6518
- docs: add release migration-guide page for breaking changes and deprecations by @ndonkoHenri in #6517
New Contributors
Full Changelog: v0.85.1...v0.85.2
v0.85.1
Bug fixes
- Fix
TooltipTheme.decorationso it applies to controls usingft.Tooltip(...)when the tooltip does not explicitly setdecorationorbgcolor(#6432, #6482) by @ndonkoHenri. - Fix
flet-geolocator.Geolocatorreliability on web and desktop:get_last_known_position()no longer crashes withTypeError: argument after ** must be a mapping, not NoneTypeand now returnsOptional[GeolocatorPosition];get_current_position()no longer hangs forever on web (Dart-side workaround for the upstreamgeolocator_web4.1.3inMicroseconds/inMillisecondstimeout typo) and uses sensible web defaults (time_limit: 30s,maximum_age: 5m); the previously-droppedconfigurationargument now actually reachesgetCurrentPositionon the Dart side; the position stream is gated behind a registeredon_position_change/on_errorhandler (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 asRuntimeErrorwithout the defaultException:prefix (#6487) by @FeodorFitsner. - Fix PEP 508 markers on
flet'soauthlib/httpxdeps not actually excluding those packages under Pyodide: theflet build webpackage platform has been renamed fromPyodidetoEmscriptento matchplatform.system()inside the Pyodide runtime, and the markers now useplatform_system != 'Emscripten', so the exclusion works both viaflet buildand a directmicropip.install("flet")in a Pyodide REPL. Requiresserious_python>= 1.0.0, which is now pinned in theflet buildtemplate (#6492) by @FeodorFitsner.