Back to Flet

SKILL

.agents/skills/create-flet-example-projects/SKILL.md

0.85.0.dev29.2 KB
Original Source

When to use

Use this skill when a user asks to:

  • create one control/example folder (for example examples/controls/chip) in the project-per-example format
  • migrate existing flat examples to the project-per-example format
  • normalize a partially converted folder so all examples follow the same structure

Goal

Ensure each runnable example is a standalone project containing:

  • main.py
  • pyproject.toml with Gallery/MCP metadata
  • assets/ (if the example uses local assets)

Workflow

  1. Inspect source folder.
  • Detect current state per example:
    • flat file: foo.py
    • project folder: foo/main.py
    • mixed/partial conversion: both styles present or missing metadata files
  • Find candidate flat modules: *.py in the target folder (exclude helper files such as __init__.py).
  • Keep existing media/ unless an example needs local assets copied into its own assets/.
  1. Convert or normalize examples.
  • For foo.py, create foo/ and move file to foo/main.py.
  • If foo/main.py already exists, keep it and do not recreate/move files.
  • If folder exists but main.py is missing, repair structure only when there is a clear source file.
  • Do not create foo/__init__.py; import example modules directly in tests/docs (for example import examples.controls.foo.bar.main as bar or import examples.controls.foo.bar as bar when using namespace-package imports).
  • When a control folder has been fully converted to project-per-example layout, delete the control-level examples/controls/<control>/__init__.py too. The converted folders should behave like namespace packages, matching prior migrations such as commit 7e65ad566.
  1. Add pyproject.toml for each example project.
  • Infer from path and code.
  • Create missing pyproject.toml files for existing project folders.
  • Update obviously stale metadata when migrating existing examples (for example wrong title/description/categories).
  • Verify platform support before adding or omitting [tool.flet].platforms:
    • Check the local implementation and docs for explicit platform guards, support tables, or platform-specific exceptions.
    • If support is limited, add [tool.flet].platforms with only the supported platforms.
    • If support is broad/all-platform, omit [tool.flet].platforms.
  • Required fields:
    • [project]: name, version, description, requires-python, keywords, authors, dependencies
    • [dependency-groups].dev: include flet-cli, flet-desktop, flet-web
    • [tool.flet.gallery].categories
    • [tool.flet.metadata]: title, controls, layout_pattern, complexity, features
    • [tool.flet]: org, company, copyright
  • Add [tool.flet].platforms only when the example is platform-limited.
  • Add permissions blocks only when code actually needs them.
  1. Infer metadata.
  • Title: readable version of file/folder intent.
  • Short description: one line of what the example demonstrates.
  • [project].description must be meaningful and example-specific; avoid generic placeholders like "Example N" or "<name> example for <control>".
  • Description should mention the concrete behavior or interaction shown (for example: hover highlight, live updates, custom axes, event handling).
  • Categories: typically control-based, e.g. Input/Chip, plus optional Apps/Basic controls.
  • Tags: from control/topic/behavior words.
  • Controls used: list key controls from code.
  • Layout pattern: choose closest practical value (e.g. filter-bar, inline-actions, dashboard, list-detail).
  • Complexity: basic unless logic/state/architecture is non-trivial.
  • Features: notable behaviors only (click handling, selection, async loading, drag-and-drop, etc.).
  • If an example supports exporting or downloading output, include "save to file" in [tool.flet.metadata].features.
  • If an example module contains async def handlers or async control flow, append "async" to keywords.
  1. Infer dependencies from imports.
  • Always include flet for standard examples.
  • Include extra packages if imported (for example extension packages).
  • Do not add unused dependencies.
  1. Make examples mobile-safe.
  • If ft.context.disable_auto_update() is not used, do not add explicit page.update() unless strictly necessary.

  • Apply this page.update() rule to all examples in the touched folder (new, migrated, and already converted).

  • Wrap app content in ft.SafeArea so example renders correctly on mobile.

  • Add expand=True to ft.SafeArea only when needed for correct layout/sizing (for example to avoid Infinity/NaN sizing issues), and avoid adding it when not necessary.

  • When converting legacy page.add(a, b, ...) style examples, wrap the controls in ft.Column(controls=[...]) inside ft.SafeArea(content=...) rather than ft.Row, unless the original code explicitly used a row layout.

  • Apply this to all examples in the touched folder (new, migrated, and already converted), not only files changed by moves.

  • During validation, confirm every <example>/main.py in scope includes a top-level ft.SafeArea around rendered content.

  • For declarative examples using @ft.component, do not pass component instances as regular control children (for example SafeArea(content=App())) because this can raise runtime attribute errors.

  • In declarative examples, ensure the component itself returns regular controls (including SafeArea when needed) and render it at page level with page.render(App) in main().

  1. Prefer @ft.control for custom controls in examples.
  • If an example defines a custom control class inheriting from a Flet control (for example class MyThing(ft.Column)), prefer @ft.control style.
  • Move constructor-style setup to declarative fields + init() where practical.
  • Keep behavior unchanged and avoid refactors that alter public usage unless needed for compatibility.
  1. Remove deprecated Material 3 toggle usage.
  • If use_material3 appears in example code, remove it and simplify the example to current API usage.
  • Remove related Material 3 toggle logic/UI that exists only to switch use_material3.
  • Update example metadata (pyproject.toml) to remove stale Material 3 references when code is changed.
  1. Ensure runnable entrypoint.
  • Every example main.py should end with:
    • if __name__ == "__main__":
    • ft.run(main)
  • Apply this to all examples in the touched folder (new, migrated, and already converted).
  1. Update references.
  • Docs code includes: change from .../example.py to .../example/main.py.
  • Inspect the relevant docs pages for each touched control/service/example area (for example sdk/python/packages/flet/docs/controls/<control>.md) and update any --8<-- includes or direct file-path references to the new main.py path.
  • Tests/imports: use direct module imports and avoid relying on package-level __init__.py re-exports.
  • For already-converted examples, only update references that are stale; avoid unnecessary churn.
  • If removing a control-level __init__.py, confirm no remaining imports rely on from examples.controls.<control> import ....
  1. Validate.
  • Run python -m compileall on changed main.py files.
  • Run uv run ruff check on changed example files and fix violations until it passes (respecting repository pyproject.toml under [tool.ruff]).
  • Search for stale paths to old flat files.
  • Search docs and package sources for stale references to the migrated flat example paths and fix any hits in scope.
  • Check git status to confirm expected moves and edits.
  • When integration tests exist for the touched control, run the targeted test file(s).
  • Confirm all in-scope main.py files include both top-level ft.SafeArea wrapping and the if __name__ == "__main__": ft.run(main) entrypoint.
  • Confirm in-scope ft.SafeArea wrappers use expand=True only where needed for correct behavior and sizing; avoid forcing it by default.
  • Confirm there are no unnecessary page.update() calls in in-scope examples (unless explicitly required by isolated-control or non-auto-update behavior).
  • Confirm no in-scope examples use use_material3.
  • Confirm each in-scope pyproject.toml has a meaningful, example-specific [project].description (not generic or templated text).
  • Confirm metadata features include "save to file" when the example code supports file export/save behavior.
  • Confirm there is no stale control-level __init__.py left behind once a touched control folder has been fully converted.
  • Confirm the relevant docs pages were updated to reference main.py and that no stale doc includes remain for the touched examples.

Code style

  • When writing wrapped controls (SafeArea, Column, Row, Container, etc.), keep content= or controls= as the last named argument in that control call.
  • Apply this ordering consistently when creating or refactoring examples.
  • Follow code style and linting rules defined in the repository pyproject.toml under [tool.ruff] for all edits.

Command checklist

  • Discover files: rg --files <target_dir>
  • Find docs links/imports: rg -n "<old_path_or_module>" packages examples
  • Syntax check: python -m compileall <changed_main_files>
  • Ruff check: uv run ruff check <changed_example_files>

Output expectations

Report:

  • created example projects
  • metadata added
  • docs/tests updates
  • validation results