TL;DR: Install FletX with pip install fletxr[dev], create your first app in 5 minutes with fletx new my_app, run it with fletx run, and you're building! FletX is a framework for building reactive, modular desktop and web apps with Flet.
FletX is a reactive application framework built on top of Flet. It brings modern app architecture patterns (dependency injection, routing, state management, controllers) to Flet applications.
# Pure Flet - manual, scattered logicimportfletasftdefmain(page:ft.Page):page.title="Counter"counter={"value":0}# State scattered everywheredefincrement(_):counter["value"]+=1text.value=str(counter["value"])page.update()text=ft.Text(counter["value"])page.add(text,ft.ElevatedButton("Increment",on_click=increment))ft.app(target=main)
FletX organizes your app with controllers, routing, DI, and reactive state:
importfletasftfromfletximportFletXAppfromfletx.coreimportFletXPage,FletXController,RxIntfromfletx.navigationimportrouter_configfromfletx.decoratorsimportobx# Step 1: Create a controller to manage stateclassCounterController(FletXController):def__init__(self):self.count=RxInt(0)# Step 2: Create a page that uses the controllerclassCounterPage(FletXPage):ctrl=CounterController()# @obx makes this widget reactive - it rebuilds when count changes@obxdefcounter_text(self):returnft.Text(value=f'Count: {self.ctrl.count}',size=50,weight="bold",color='red'ifnotself.ctrl.count.value%2==0else'white')defbuild(self):returnft.Column(controls=[self.counter_text(),ft.ElevatedButton("Increment",on_click=lambdae:self.ctrl.count.increment()# Auto UI update)])# Step 3: Register the routerouter_config.add_route(path="/",component=CounterPage)# Step 4: Create and run the appif__name__=="__main__":app=FletXApp(title="My First FletX App",initial_route="/")app.run()
# app/pages/todo_page.pyimportfletasftfromfletx.coreimportFletXPagefromfletx.decoratorsimportobxfromapp.controllers.todo_controllerimportTodoControllerclassTodoPage(FletXPage):ctrl=TodoController()defbuild(self):input_field=ft.TextField(label="Add a todo",width=300)defadd_todo(_):ifinput_field.value.strip():self.ctrl.add_todo(input_field.value)input_field.value=""self.update()add_button=ft.ElevatedButton("Add",on_click=add_todo)@obxdeftodo_list():returnft.Column([ft.Checkbox(label=todo.title,value=todo.completed,on_change=lambda_:self.ctrl.toggle_todo(todo.id))fortodoinself.ctrl.todos])returnft.Column([ft.Text("My Todos",size=32,weight="bold"),ft.Row([input_field,add_button]),todo_list()])
# main.pyfromfletximportFletXAppfromapp.routesimportsetup_routesif__name__=="__main__":setup_routes()app=FletXApp(title="My Todo App",initial_route="/")app.run()
# Create a new projectfletxnewmy_app--author"Your Name"--description"My awesome app"# Generate a new pagefletxgeneratepageproducts_page
# Generate a new controllerfletxgeneratecontrollerproducts_controller--with-test
# Run with hot reload (in development)fletxrun--debug
# Build for webfletxrun--web
# Run testsfletxtest