Flet review workflow
Skill brunobrown/claude-flet-plugin/.agents/skills/flet-review-workflow
Checklist-driven review for Flet apps and extensions (Flet 0.85.x+).From its SKILL.md
npx -y skills add brunobrown/claude-flet-plugin --skill flet-review-workflowAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
5.7 KB, as published. Nobody here has run it
Flet Review Workflow
You are performing a comprehensive code review of Flet code. First, determine whether the code is a Flet app or a Flet extension, then apply the appropriate checklist.
Step 1: Identify Code Type
Scan the codebase to determine:
- App: Contains
ft.run(main),@ft.component,page.render_views() - Extension: Contains
@ft.control("Name"),ft.Serviceorft.LayoutControl - Both: App that uses a custom extension
Step 2: App Checklist
If reviewing a Flet app, check all of these:
Entry Point & Rendering
- Uses
ft.run(main)— NOTft.app() - Uses
page.render_views()orpage.render()— NOTpage.add() - Does NOT call
page.update()manually (declarative mode handles this) -
page.render(Component)passes reference, NOTpage.render(Component())
State Management
-
@ft.observablecomes BEFORE@dataclass(order matters) -
ft.use_state()used for local form fields (not@ft.observable) - Observable lists use
.append()/.clear()to trigger re-renders - State created outside components in
main()when handlers need access - No direct mutation of observable list elements (
items[0] = x)
Hooks
- All hooks called inside
@ft.componentonly (never in regular functions) - Hooks NOT inside conditionals or loops (fixed order required)
-
use_effectcleanup usescleanup=parameter (NOT return value) -
use_effectdependencies array is correct ([] for mount-only) -
use_refused for mutable refs that shouldn't trigger re-renders
Components
- All components use
@ft.componentdecorator - Context accessed via
ft.use_context(AppCtx)(not passingpageas prop) - Factory functions used in loops to avoid closure traps
- Async handlers use try/except for error handling
Navigation
-
view_ref[0].show_drawer()used (NOTpage.show_drawer()) - PAGE_BUILDERS dict maps page IDs to component functions
- Router clears
page.viewsbefore adding new views -
on_view_pophandler implemented for router-based navigation
Styling
- Uses
ft.Colors.NAME(uppercase) notft.colors.NAME - Uses
ft.Icons.NAME(uppercase) notft.icons.NAME - Theme uses
color_scheme_seedorcolor_scheme(notprimary_swatch)
Breaking Changes (0.83.x)
- No
ft.padding.all()/ft.padding.symmetric()/ft.padding.only()(removed in 0.83.0 — use class methods) - SharedPreferences
.set()validates types (str, int, float, bool, list[str] only) - Scrollbar configuration uses
Scrollbar(...)instance
Flet 0.85.x checks
- New apps prefer
ft.Routerover hand-rolledon_route_changefor nested routes / loaders -
ft.Router(manage_views=True)paired withpage.render_views(App)(notpage.render) -
View(route=ft.use_view_path())in view-stack mode -
use_route_outlet()only used inside layout-route components (routes withchildren) - No
page.go(route)— usepage.navigate(route)(sync) /await page.push_route(route)(async) -
pop_views_untilpaired withon_views_pop_until(noton_view_pop) - Declarative components use
ft.use_dialog(dialog | None)(call every render) -
DragTargetEvent: uselocal_position/global_position(.x/.y/.offsetdeprecated 0.85.0) -
page.enable_screenshots = Trueset beforetake_screenshot/take_animation/Screenshot.capture
Step 3: Extension Checklist
If reviewing a Flet extension, check all of these:
Python Side
-
@ft.control("PascalCaseName")has explicit string name - Correct base class:
ft.Service(no UI) orft.LayoutControl(visual) - Internal fields use
field(default=None, init=False, metadata={"skip": True}) - Events typed as
Optional[ft.EventHandler[EventType]] - Event classes extend
ft.Event["ControlClassName"] - Enums use
Enum(str, Enum)orclass Name(Enum)with string values - Platform validated in
_invoke_methodoverride (notbefore_update) -
__init__.pyhas__all__with all public exports - No imports from
flet.core.*(useimport flet as ft) - No
_set_attr()usage (use dataclass fields)
Dart Side
-
control.typecase matches@ft.control("Name")exactly -
control.addInvokeMethodListenercalled ininit() - Args converted:
Map<String, dynamic>.from(args)before use - Booleans returned as
.toString()(Python expects "true"/"false") - All listeners wrapped in try/catch →
_handleError() - Listener setup guarded with
_listenersSetupflag -
control.triggerEvent("name", data)names match Pythonon_name -
_handleErrorreports toFlutterError.reportError -
dispose()cleans up resources and subscriptions - Service:
createService()in extension.dart - UI Control:
createWidget()in extension.dart
Project Configuration
-
pyproject.tomlhas[tool.setuptools.package-data]for Flutter code -
pubspec.yamlhaspublish_to: none - Example app has
[tool.flet.app] path = "src"if using src/ layout - Extension registered in app's
[tool.flet.extensions]
Step 4: Report
Generate a review report with:
- Summary — Overall assessment (pass / needs fixes)
- Issues Found — List each issue with:
- Severity: Critical / Warning / Info
- File and line number
- What's wrong
- How to fix it
- Good Practices — Note things done correctly
- Suggestions — Optional improvements
Present the report in a clear, actionable format. Offer to fix critical issues automatically.