25d895d 🐛 fix(gitea_workflow): clean up temp repos after job steps 2bc3b11 🐛 fix(gitea_workflow): clean up temporary repo dirs in workflows 98c3f30 📝 docs(agent_rules): allow plan execution on current branch 16c7230 📝 docs(prompts): define custom verify layering 8efc4dd 🐛 fix(skills): quote commit-message description bc8498f 🐛 fix(ci): install tomli for gitea tests 55cda3b 🐛 fix(tests): report missing toml parser clearly c0729c7 🐛 fix(playbook): import Optional for cli compatibility 63e24bf 📦 deps(skills): sync thirdparty skills d2f9356 🐛 fix(ci): isolate gitea workflow repos 588b81d 🐛 fix(ci): inline gitea workflow bootstrap e0b1c3a ♻️ refactor(skills): standardize first-party skill contracts 2c5050d ♻️ refactor(skills): rename repo skills source dir f049dfb 📦 deps(skills): drop duplicate first-party superpowers skills 234b335 ✨ feat(workflow): add superpowers planning and execution state tracking c1702a6 📝 docs(markdown): format tracked markdown and drop stale templates 2325409 📝 docs(markdown): clarify optional markdownlint usage 214c44e 🔧 chore(markdown): add markdownlint baseline and lint fixes a22b324 📝 docs(templates): add execution and memory-bank prompt templates 223a797 📝 docs(templates): update README for Claude Code and current features 4ac8672 📝 docs: simplify README + platform-agnostic tools + auto-create local rules 2431c9d 📝 docs: add claude_md config and use cross-platform paths d64b248 📝 docs: fix README.md inaccuracies and add Claude Code info c8d6bf2 🐛 fix(playbook): use relative paths in CLAUDE.md when not at project root 6518f0f ✨ feat(playbook): auto-create CLAUDE.md with path discovery 6ec9a45 ✨ feat(skills): add skill_link symlink support + platform-agnostic prompt 9f8b6b5 📝 docs: update README and config example for Claude Code support 79cff6c 📝 docs(skills): add Claude Code platform support 452c6f5 ✨ feat(playbook): auto-inject AGENTS.md into CLAUDE.md e1dbf3c 🐛 fix(skills): remove dual-path from commit-message skill f3a7259 🔧 chore(ci): use prepare_repo.sh in both workflows da08212 🔧 chore(ci): extract prepare_repo.sh and clean up workflows 7ade85e 🗑️ remove(tsl): drop syntax_book/, data/ source and build script f94dba0 ♻️ refactor(skills): update playbook.py and tests for thirdparty/ layout b3df412 ♻️ refactor(skills): separate thirdparty skills into thirdparty/ subdirectory 64950e7 📦 deps(skills): sync thirdparty skills a2e3cb0 ✨ feat(playbook): add no_backup deploy controls 8609d59 🐛 fix(docs): repair reference catalog source links 956da11 🐛 fix(playbook): publish hidden ci test fixes 3f67754 📦 deps(skills): sync thirdparty skills 08ca87b 📦 deps(skills): add karpathy thirdparty sync 96b705b 📝 docs(tsl): rebuild canonical syntax and routing manual 3ed5052 📦 deps(skills): sync thirdparty skills 60108dd 📦 deps(skills): sync thirdparty skills da85d4e 🐛 fix(thirdparty): prune nested project snapshots a2a697e 📦 deps(skills): sync thirdparty skills 9df610a 🐛 fix(thirdparty): exclude duplicated superpowers skills 33dd5bb 🐛 fix(thirdparty): preserve optional manifest fields 91b0ea7 🐛 fix(thirdparty): preserve manifest during snapshot update 2e26f98 🔧 chore(thirdparty): generalize skills sync pipeline 5b9c1e3 📦 deps(skills): sync superpowers 2f2d34a 📝 docs(readme): normalize subtree command spacing 62db7db 🐛 fix(ci): serialize superpowers update and sync 3463223 🐛 fix(ci): use literal superpowers sync paths 48f6de8 📦 deps(skills): sync superpowers 4b23529 🔧 chore(ci): merge superpowers update and sync workflow a56d75b 📦 deps(skills): sync superpowers 84bcefa 🔧 chore(ci): use ci[bot] commit author name 00a07e5 📦 deps(skills): sync superpowers 7b84daf 🐛 fix(templates): enforce main loop progress tracking 51373d7 🔧 chore(ci): automate superpowers sync workflow eaaa39c 🐛 fix(ci): prevent stale superpowers sync from restoring skills block 79755c6 📦 deps(skills): sync superpowers 836d878 📦 deps(skills): sync superpowers 8216c9f 📦 deps(skills): sync superpowers 9439505 🐛 fix(playbook): address reported repo issues git-subtree-dir: docs/standards/playbook git-subtree-split: 25d895d8b3f56624ccfe99ad7289e9eb49e0f316
10 KiB
10 KiB
| 1 | No | Category | Guideline | Description | Do | Don't | Code Good | Code Bad | Severity | Docs URL |
|---|---|---|---|---|---|---|---|---|---|---|
| 2 | 1 | Widgets | Use StatelessWidget when possible | Immutable widgets are simpler | StatelessWidget for static UI | StatefulWidget for everything | class MyWidget extends StatelessWidget | class MyWidget extends StatefulWidget (static) | Medium | https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html |
| 3 | 2 | Widgets | Keep widgets small | Single responsibility principle | Extract widgets into smaller pieces | Large build methods | Column(children: [Header() Content()]) | 500+ line build method | Medium | |
| 4 | 3 | Widgets | Use const constructors | Compile-time constants for performance | const MyWidget() when possible | Non-const for static widgets | const Text('Hello') | Text('Hello') for literals | High | https://dart.dev/guides/language/language-tour#constant-constructors |
| 5 | 4 | Widgets | Prefer composition over inheritance | Combine widgets using children | Compose widgets | Extend widget classes | Container(child: MyContent()) | class MyContainer extends Container | Medium | |
| 6 | 5 | State | Use setState correctly | Minimal state in StatefulWidget | setState for UI state changes | setState for business logic | setState(() { _counter++; }) | Complex logic in setState | Medium | https://api.flutter.dev/flutter/widgets/State/setState.html |
| 7 | 6 | State | Avoid setState in build | Never call setState during build | setState in callbacks only | setState in build method | onPressed: () => setState(() {}) | build() { setState(); } | High | |
| 8 | 7 | State | Use state management for complex apps | Provider Riverpod BLoC | State management for shared state | setState for global state | Provider.of<MyState>(context) | Global setState calls | Medium | |
| 9 | 8 | State | Prefer Riverpod or Provider | Recommended state solutions | Riverpod for new projects | InheritedWidget manually | ref.watch(myProvider) | Custom InheritedWidget | Medium | https://riverpod.dev/ |
| 10 | 9 | State | Dispose resources | Clean up controllers and subscriptions | dispose() for cleanup | Memory leaks from subscriptions | @override void dispose() { controller.dispose(); } | No dispose implementation | High | |
| 11 | 10 | Layout | Use Column and Row | Basic layout widgets | Column Row for linear layouts | Stack for simple layouts | Column(children: [Text(), Button()]) | Stack for vertical list | Medium | https://api.flutter.dev/flutter/widgets/Column-class.html |
| 12 | 11 | Layout | Use Expanded and Flexible | Control flex behavior | Expanded to fill space | Fixed sizes in flex containers | Expanded(child: Container()) | Container(width: 200) in Row | Medium | |
| 13 | 12 | Layout | Use SizedBox for spacing | Consistent spacing | SizedBox for gaps | Container for spacing only | SizedBox(height: 16) | Container(height: 16) | Low | |
| 14 | 13 | Layout | Use LayoutBuilder for responsive | Respond to constraints | LayoutBuilder for adaptive layouts | Fixed sizes for responsive | LayoutBuilder(builder: (context constraints) {}) | Container(width: 375) | Medium | https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html |
| 15 | 14 | Layout | Avoid deep nesting | Keep widget tree shallow | Extract deeply nested widgets | 10+ levels of nesting | Extract widget to method or class | Column(Row(Column(Row(...)))) | Medium | |
| 16 | 15 | Lists | Use ListView.builder | Lazy list building | ListView.builder for long lists | ListView with children for large lists | ListView.builder(itemCount: 100, itemBuilder: ...) | ListView(children: items.map(...).toList()) | High | https://api.flutter.dev/flutter/widgets/ListView-class.html |
| 17 | 16 | Lists | Provide itemExtent when known | Skip measurement | itemExtent for fixed height items | No itemExtent for uniform lists | ListView.builder(itemExtent: 50) | ListView.builder without itemExtent | Medium | |
| 18 | 17 | Lists | Use keys for stateful items | Preserve widget state | Key for stateful list items | No key for dynamic lists | ListTile(key: ValueKey(item.id)) | ListTile without key | High | |
| 19 | 18 | Lists | Use SliverList for custom scroll | Custom scroll effects | CustomScrollView with Slivers | Nested ListViews | CustomScrollView(slivers: [SliverList()]) | ListView inside ListView | Medium | https://api.flutter.dev/flutter/widgets/SliverList-class.html |
| 20 | 19 | Navigation | Use Navigator 2.0 or GoRouter | Declarative routing | go_router for navigation | Navigator.push for complex apps | GoRouter(routes: [...]) | Navigator.push everywhere | Medium | https://pub.dev/packages/go_router |
| 21 | 20 | Navigation | Use named routes | Organized navigation | Named routes for clarity | Anonymous routes | Navigator.pushNamed(context '/home') | Navigator.push(context MaterialPageRoute()) | Low | |
| 22 | 21 | Navigation | Handle back button (PopScope) | Android back behavior and predictive back (Android 14+) | Use PopScope widget (WillPopScope is deprecated) | Use WillPopScope | PopScope(canPop: false, onPopInvoked: (didPop) => ...) | WillPopScope(onWillPop: ...) | High | https://api.flutter.dev/flutter/widgets/PopScope-class.html |
| 23 | 22 | Navigation | Pass typed arguments | Type-safe route arguments | Typed route arguments | Dynamic arguments | MyRoute(id: '123') | arguments: {'id': '123'} | Medium | |
| 24 | 23 | Async | Use FutureBuilder | Async UI building | FutureBuilder for async data | setState for async | FutureBuilder(future: fetchData()) | fetchData().then((d) => setState()) | Medium | https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html |
| 25 | 24 | Async | Use StreamBuilder | Stream UI building | StreamBuilder for streams | Manual stream subscription | StreamBuilder(stream: myStream) | stream.listen in initState | Medium | https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html |
| 26 | 25 | Async | Handle loading and error states | Complete async UI states | ConnectionState checks | Only success state | if (snapshot.connectionState == ConnectionState.waiting) | No loading indicator | High | |
| 27 | 26 | Async | Cancel subscriptions | Clean up stream subscriptions | Cancel in dispose | Memory leaks | subscription.cancel() in dispose | No subscription cleanup | High | |
| 28 | 27 | Theming | Use ThemeData | Consistent theming | ThemeData for app theme | Hardcoded colors | Theme.of(context).primaryColor | Color(0xFF123456) everywhere | Medium | https://api.flutter.dev/flutter/material/ThemeData-class.html |
| 29 | 28 | Theming | Use ColorScheme | Material 3 color system | ColorScheme for colors | Individual color properties | colorScheme: ColorScheme.fromSeed() | primaryColor: Colors.blue | Medium | |
| 30 | 29 | Theming | Access theme via context | Dynamic theme access | Theme.of(context) | Static theme reference | Theme.of(context).textTheme.bodyLarge | TextStyle(fontSize: 16) | Medium | |
| 31 | 30 | Theming | Support dark mode | Respect system theme | darkTheme in MaterialApp | Light theme only | MaterialApp(theme: light, darkTheme: dark) | MaterialApp(theme: light) | Medium | |
| 32 | 31 | Animation | Use implicit animations | Simple animations | AnimatedContainer AnimatedOpacity | Explicit for simple transitions | AnimatedContainer(duration: Duration()) | AnimationController for fade | Low | https://api.flutter.dev/flutter/widgets/AnimatedContainer-class.html |
| 33 | 32 | Animation | Use AnimationController for complex | Fine-grained control | AnimationController with Ticker | Implicit for complex sequences | AnimationController(vsync: this) | AnimatedContainer for staggered | Medium | |
| 34 | 33 | Animation | Dispose AnimationControllers | Clean up animation resources | dispose() for controllers | Memory leaks | controller.dispose() in dispose | No controller disposal | High | |
| 35 | 34 | Animation | Use Hero for transitions | Shared element transitions | Hero for navigation animations | Manual shared element | Hero(tag: 'image' child: Image()) | Custom shared element animation | Low | https://api.flutter.dev/flutter/widgets/Hero-class.html |
| 36 | 35 | Forms | Use Form widget | Form validation | Form with GlobalKey | Individual validation | Form(key: _formKey child: ...) | TextField without Form | Medium | https://api.flutter.dev/flutter/widgets/Form-class.html |
| 37 | 36 | Forms | Use TextEditingController | Control text input | Controller for text fields | onChanged for all text | final controller = TextEditingController() | onChanged: (v) => setState() | Medium | |
| 38 | 37 | Forms | Validate on submit | Form validation flow | _formKey.currentState!.validate() | Skip validation | if (_formKey.currentState!.validate()) | Submit without validation | High | |
| 39 | 38 | Forms | Dispose controllers | Clean up text controllers | dispose() for controllers | Memory leaks | controller.dispose() in dispose | No controller disposal | High | |
| 40 | 39 | Performance | Use const widgets | Reduce rebuilds | const for static widgets | No const for literals | const Icon(Icons.add) | Icon(Icons.add) | High | |
| 41 | 40 | Performance | Avoid rebuilding entire tree | Minimal rebuild scope | Isolate changing widgets | setState on parent | Consumer only around changing widget | setState on root widget | High | |
| 42 | 41 | Performance | Use RepaintBoundary | Isolate repaints | RepaintBoundary for animations | Full screen repaints | RepaintBoundary(child: AnimatedWidget()) | Animation without boundary | Medium | https://api.flutter.dev/flutter/widgets/RepaintBoundary-class.html |
| 43 | 42 | Performance | Profile with DevTools | Measure before optimizing | Flutter DevTools profiling | Guess at performance | DevTools performance tab | Optimize without measuring | Medium | https://docs.flutter.dev/tools/devtools |
| 44 | 43 | Accessibility | Use Semantics widget | Screen reader support | Semantics for accessibility | Missing accessibility info | Semantics(label: 'Submit button') | GestureDetector without semantics | High | https://api.flutter.dev/flutter/widgets/Semantics-class.html |
| 45 | 44 | Accessibility | Support large fonts | MediaQuery text scaling | MediaQuery.textScaleFactor | Fixed font sizes | style: Theme.of(context).textTheme | TextStyle(fontSize: 14) | High | |
| 46 | 45 | Accessibility | Test with screen readers | TalkBack and VoiceOver | Test accessibility regularly | Skip accessibility testing | Regular TalkBack testing | No screen reader testing | High | |
| 47 | 46 | Testing | Use widget tests | Test widget behavior | WidgetTester for UI tests | Unit tests only | testWidgets('...' (tester) async {}) | Only test() for UI | Medium | https://docs.flutter.dev/testing |
| 48 | 47 | Testing | Use integration tests | Full app testing | integration_test package | Manual testing only | IntegrationTestWidgetsFlutterBinding | Manual E2E testing | Medium | |
| 49 | 48 | Testing | Mock dependencies | Isolate tests | Mockito or mocktail | Real dependencies in tests | when(mock.method()).thenReturn() | Real API calls in tests | Medium | |
| 50 | 49 | Platform | Use Platform checks | Platform-specific code | Platform.isIOS Platform.isAndroid | Same code for all platforms | if (Platform.isIOS) {} | Hardcoded iOS behavior | Medium | |
| 51 | 50 | Platform | Use kIsWeb for web | Web platform detection | kIsWeb for web checks | Platform for web | if (kIsWeb) {} | Platform.isWeb (doesn't exist) | Medium | |
| 52 | 51 | Packages | Use pub.dev packages | Community packages | Popular maintained packages | Custom implementations | cached_network_image | Custom image cache | Medium | https://pub.dev/ |
| 53 | 52 | Packages | Check package quality | Quality before adding | Pub points and popularity | Any package without review | 100+ pub points | Unmaintained packages | Medium |