The open-source GetX-inspired Python Framework for Building Reactive, Cross-Platform Apps with Flet
FletX brings Flutter's beloved GetX patterns to Python, combining Flet's UI capabilities with:
- β‘ Reactive state management
- π§ Declarative routing
- π Dependency injection
- π§© Modular architecture
- π¨ Widget library
Perfect for building desktop, web, and mobile apps with Python at lightning speed.
NOTE: FletX currently supports Python 3.12 only. Compatibility with newer versions is in progress β we're actively working to expand support soon.
pip install FletXr==0.1.4.dev1
fletx new my_project --no-install
my_project/
βββ app/
β βββ controllers/ # Business logic controllers
β βββ services/ # Business services and API calls
β βββ models/ # Data models
β βββ components/ # Reusable widgets
β βββ pages/ # Application pages
β βββ routes.py # App routing modules
βββ assets/ # Static assets (images, fonts, etc.)
βββ tests/ # Test files
βββ .python-version # Python version
βββ pyproject.toml # Python dependencies
βββ README.md # Quick start README
βββ main.py # Application entry point
To run the project, just navigate to the project folder and run this command
fletx run --web # Will open app in a navigator
# --desktop to open app in a desktop window
# --android to open app on Android device
# --ios to open app on a iOs device
# --help for more option
import flet as ft
from fletx.app import FletXApp
from fletx.core import (
FletXPage, FletXController, RxInt, RxStr
)
from fletx.navigation import router_config
from fletx.decorators import (
simple_reactive
)
class CounterController(FletXController):
def __init__(self):
count = RxInt(0) # Reactive state
super().__init__()
@simple_reactive(
bindings={
'value': 'text'
}
)
class MyReactiveText(ft.Text):
def __init__(self, rx_text: RxStr, **kwargs):
self.text: RxStr = rx_text
super().__init__(**kwargs)
class CounterPage(FletXPage):
ctrl = CounterController()
def build(self):
return ft.Column(
controls = [
MyReactiveText(rx_text=self.ctrl.count, size=200, weight="bold"),
ft.ElevatedButton(
"Increment",
on_click = lambda e: self.ctrl.count.increment() # Auto UI update
)
]
)
def main():
# Defining route
router_config.add_route(
**{'path': '/', 'component': CounterPage}
)
app = FletXApp(
title = "My Counter",
initial_route = "/",
debug = True
).with_window_size(400, 600).with_theme(
ft.Theme(color_scheme_seed=ft.Colors.BLUE)
)
# Run sync
app.run()
if __name__ == "__main__":
main()
class SearchController(FletXController):
"""Search controller"""
def __init__(self):
self.query = RxStr("")
self.results = RxList([])
self.is_loading = RxBool(False)
self.is_enabled = RxBool(True)
super().__init__()
# Configure reactives effects
self._setup_reactive_effects()
def _setup_reactive_effects(self):
"""Configure reactive effects"""
# Search with debounce
@reactive_debounce(0.5)
@reactive_when(self.is_enabled)
def search_handler():
if self.query.value.strip():
self.perform_search(self.query.value)
# Listen query changes
self.query.listen(search_handler)
# Cache expensive search results
@reactive_memo(maxsize=50)
def expensive_search(query: str):
# Expensive search simulation
import time
time.sleep(0.1) # Simulate
return [f"Result {i} for '{query}'" for i in range(5)]
self.expensive_search = expensive_search
# Other actions here...
# Define routes
from flex.navigation import router_config, navigate
# 1. simple routing
router_config.add_routes([
{"path": "/", "component": HomePage},
{"path": "/settings", "component": SettingsPage}
])
# 2. Dynamic routes with parameters
router_config.add_routes([
{
"path": "/users/:id",
"component": lambda route: UserDetailPage(route.params['id'])
},
{
"path": "/products/*category",
"component": lambda route: ProductsPage(route.params['category'])
}
])
# Navigate programmatically
navigate("/users/123")
# Register services
FletX.put(AuthService(), tag="auth")
# Retrieve anywhere
auth_service = FletX.find(AuthService, tag="auth")
FletX allows you to quickly create reactive widgets from flet Controls by using reactive widget decorators.
from fletx.decorators import (
reactive_control, simple_reactive,
reactive_state_machine, reactive_form,
two_way_reactive, reactive_list,
...
)
- Basic usage
# Create a separate router for admin module
admin_module = ModuleRouter()
admin_module.name = 'admin'
# Define routes for admin_module
admin_module.add_routes([
{"path": "/", "component": AdminHomePage},
{"path": "/users", "component": AdminUsersPage},
{"path": "/settings", "component": AdminSettingsPage}
])
# Register the admin routing module to the main router config
router_config.add_module_routes("/admin", admin_module)
# URLs become:
# /admin/ -> AdminHomePage
# /admin/users -> AdminUsersPage
# /admin/settings -> AdminSettingsPage
- Advanced Usage (OOP)
admin_routes = [
{"path": "/", "component": AdminHomePage},
{"path": "/users", "component": AdminUsersPage},
{"path": "/settings", "component": AdminSettingsPage}
]
@register_router
class AdminRouter(ModuleRouter):
"""My Admin Routing Module."""
name = 'Admin'
base_path = '/admin'
is_root = false
routes = admin_routes
sub_routers = []
@register_router
class MyAppRouter(ModuleRouter):
"""My Application Routing Module."""
name = 'MyAppRouter'
base_path = '/'
is_root = True
routes = []
sub_routers = [AdminRouter]
from fletx.core.navigation.transitions import (
RouteTransition, TransitionType
)
routes = [
{
'path': '/login',
'component': LoginPage,
'meta':{
'transition': RouteTransition(
transition_type = TransitionType.ZOOM_IN,
duration = 350
)
}
},
{
'path': '/dashboard',
'component': DashboardHomePage,
'meta':{
'transition': RouteTransition(
transition_type = TransitionType.FLIP_HORIZONTAL,
duration = 350
)
}
},
]
routes = [
{
'path': '/dashboard',
'component': DashboardHomePage,
'guards': [AuthGuard()],
'middlewares': [AnalyticsMiddleware()],
'meta':{
'transition': RouteTransition(
transition_type = TransitionType.FLIP_HORIZONTAL,
duration = 350
)
}
},
...
]
...
Operation | FletX | Pure Flet |
---|---|---|
State Update | 0.2ms | 1.5ms |
Route Navigation | 5ms | 15ms |
DI Resolution | 0.1ms | N/A |
- Documentation π (under contructions.)
- Discord Community π¬
- Issue Tracker π
We welcome contributions from the community! Please see the CONTRIBUTING.md guide for more information.
MIT Β© 2025 AllDotPy
# Happy coding!
# Let's build amazing apps with Python π
Made with β€οΈ By AllDotPy