# Flet: cross-platform Python apps with no frontend code

> Flet builds web, desktop and mobile apps from a single Python codebase, with 150+ built-in controls and `flet build` for packaging. It fits Python developers who need a real UI, not a notebook.

**flet-dev/flet** — Build realtime web, mobile and desktop apps in Python only. No frontend experience required.

- Repository: https://github.com/flet-dev/flet
- Website: https://flet.dev
- Stars: 17,204 · Forks: 718
- Language: Python
- License: Apache-2.0
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/flet-dev-flet

## The problem Flet solves, and who it is for

Most Python developers can write a data pipeline or a model in an afternoon. Turning that into something a non-technical colleague can open on a phone is where the work stops. The usual answers are a web framework plus HTML templates, or a desktop toolkit that only runs on one operating system. Flet takes a third route: the interface is described in Python, and the framework renders it on iOS, Android, Windows, macOS, Linux and the web.

The README is explicit about the target reader: "Build cross-platform apps in Python. No frontend experience required." That means backend engineers, data scientists and tool authors who want a GUI without hiring a frontend developer or learning Dart, Swift, Kotlin, HTML or JavaScript. The repository's topics list confirms the scope: android, cross-platform, desktop, flutter, ios, python, server-driven-ui, web.

The project is Apache-2.0 licensed, and the last push to the default branch was on 2026-09-20, one day before the v1.0.0 release cycle settled. That is a recent push, so describing it as actively developed is fair on the evidence available. The README does not document a support window or an LTS policy, so plan upgrades yourself.

## How Flet works: Python on one side, Flutter on the other

Flet is a server-driven UI framework. Your Python process holds the control tree, and a client renders it. The repository layout reflects this split: `client/` holds the rendering side, `sdk/` the Python package, `packages/` the shared pieces, and `docker/` deployment assets. One of the project's own topics is literally server-driven-ui.

The README describes two deployment shapes. In the first, "Run Python directly in the browser with Pyodide and WebAssembly, with no Python server required." The whole interpreter ships to the browser. In the second, "keep your Python code on a server and deliver real-time UI updates to the browser." Here the Python process stays on your machine or your server and pushes updates over a connection.

That distinction decides your architecture. A Pyodide app has no backend to secure and no server bill, but it inherits the browser's memory limits and the download size of the interpreter plus your dependencies. A server-driven app keeps heavy libraries server-side, which is the only practical option if you depend on a database or a large model, but it makes the server a single point of failure and puts latency between a tap and the response.

The README also mentions that the imperative style is supported alongside the declarative one: "Prefer changing controls directly? The imperative style is supported too." The counter example below is imperative, mutating `counter.value` and `counter.data` directly rather than rebuilding a component tree.

## Installing Flet and running the counter app

The README installs the framework with an extras group. The `[all]` extra pulls the full set of dependencies rather than a minimal core, which is what the getting-started path assumes.

```bash
pip install 'flet[all]'
```

The README notes that Flet requires Python >= 3.10, so a 3.9 environment will not work. After installation, save the counter example as `counter.py`. It builds a `ft.Text` control, wires a `FloatingActionButton` to an `on_click` handler, and passes a `main` function to `ft.run`.

```python
import flet as ft


def main(page: ft.Page):
    counter = ft.Text("0", size=50, data=0)

    def increment_click(e):
        counter.data += 1
        counter.value = str(counter.data)

    page.floating_action_button = ft.FloatingActionButton(
        icon=ft.Icons.ADD, on_click=increment_click
    )
    page.add(
        ft.SafeArea(
            expand=True,
            content=ft.Container(
                content=counter,
                alignment=ft.Alignment.CENTER,
            ),
        )
    )


ft.run(main)
```

Launch it with the CLI. According to the README, this opens the app in a native desktop window.

```bash
flet run counter.py
```

To run the same file in a browser instead, the README adds a flag. Nothing else in the code changes, which is the point of the abstraction.

```bash
flet run --web counter.py
```

If you would rather not install anything first, the README points to Flet Studio at studio.flet.dev, where apps can be created, run and shared in the browser. That is a reasonable way to check whether the control set suits your interface before committing to a local toolchain.

## Where Flet gets in the way

The mobile story has a hard dependency the README states plainly. Flet provides "prebuilt binary packages" for iOS and Android through pypi.flet.dev, "so you don't have to compile native dependencies yourself." That phrasing cuts both ways. If your app needs NumPy, pandas, Pillow or cryptography, the prebuilt route exists. If it needs a package that is not in that index, you are back to compiling native dependencies for mobile, which is exactly the work Flet was meant to remove.

Packaging is the second constraint. `flet build` produces desktop, mobile and web artifacts, and configuration lives in `pyproject.toml` for dependencies, icons and platform settings. That is convenient until you need a platform setting the build tool does not expose. The README does not document an escape hatch for arbitrary native configuration, so treat any unusual signing or entitlement requirement as unverified until you try it.

There is also a category error worth naming. Flet renders with Flutter, so your UI is Flutter widgets, not native platform controls. If a reviewer expects a macOS app to look and behave like a macOS app down to the menu bar and window chrome, the abstraction is working against you. And if your interface is a dense data grid with thousands of rows, or a chart with custom interaction, a web framework with a mature component library will likely get you there faster than composing Flet controls.

## Flet compared with Streamlit

Streamlit is the tool most Python developers reach for first when they want a UI, and the two projects answer different questions. Streamlit reruns your script from top to bottom when a widget changes, and the session state is the framework's problem. Its output is a web page, and only a web page. Flet keeps a live control tree and mutates it, and it targets six platforms including iOS, Android and native desktop windows.

That difference shows up in the code you write. A Streamlit app is a script with calls in sequence; a Flet app is a program with a `main(page)` entry point and handlers that run when events arrive. For a quick internal dashboard, Streamlit's model is less to think about. For a distributed app with a floating action button, navigation and a phone build, Flet is the one with the packaging step.

The overlap is real, though. Both let a Python developer ship a UI without a frontend hire, and both hide the browser from you. The deciding question is the delivery target, not the language. If the answer is a URL, Streamlit is simpler. If the answer includes an app store or an installer, Flet is the one that has a `flet build` command.

## Testing, packaging and what you are taking on

The README documents integration testing with pytest, run against a packaged app with `flet test`. Tests can tap buttons, enter text and verify user flows on desktop and mobile, with screenshot comparisons on Android and iOS. That is a stronger testing story than most Python UI frameworks offer, and it is worth reading before you design your app, because the test harness works against the packaged artifact rather than a mocked renderer.

Upgrade cost is the open question. The project reached v1.0.0 on 2026-09-14 after two dev releases in the same month, and the changelog lives at `CHANGELOG.md` at the repository root. The README does not document a deprecation policy or a compatibility guarantee across minor versions, so a pin in your dependency file is the only control you have. Budget time for reading the changelog on each upgrade rather than assuming the API is frozen now that 1.0 exists.

On licensing, Flet is Apache-2.0, which permits commercial and closed-source use and includes a patent grant. The README does not discuss the licences of the underlying Flutter runtime or of the prebuilt binary packages on pypi.flet.dev, and the client and package directories may carry their own notices. Check the LICENSE file and the dependency metadata if your legal team needs a complete picture; this is a description of what the repository states, not legal advice.

## Conclusion

Adopt Flet if your team already writes Python and you want one codebase for desktop, web and mobile without learning Dart, Swift, Kotlin or JavaScript. Do not adopt it if you need hand-tuned native widgets or a UI stack your designers already own in a web framework. Before committing, verify that the Python packages you depend on have prebuilt binaries on pypi.flet.dev, and run your app in a browser with `flet run --web` to confirm the rendering mode matches your deployment target.

## FAQ

### What is Flet in Python?

Flet is a Python framework for building web, desktop and mobile apps without prior frontend experience. The interface and application logic are written in Python, and the same codebase is described as running on iOS, Android, Windows, macOS, Linux and the web.

### What is the current version of Flet?

The most recent release listed is v1.0.0, published on 2026-09-14, following v1.0.0.dev2 and v1.0.0.dev0 earlier the same month.

### What are the key differences between Flet and Streamlit?

Streamlit produces a web page and reruns your script when a widget changes, while Flet keeps a live control tree you can mutate and targets desktop and mobile as well as the browser. Flet also ships a `flet build` command for packaging apps, which a web-only tool does not need.

## Sources

- [flet-dev/flet on GitHub](https://github.com/flet-dev/flet)
- [License: Apache-2.0](https://github.com/flet-dev/flet/blob/main/LICENSE)
- [Project website](https://flet.dev)
- [README](https://github.com/flet-dev/flet/blob/main/README.md)
- [Releases](https://github.com/flet-dev/flet/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/flet-dev-flet
