flutter-pro-max-cli 2.0.0 → 2.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -19
- package/assets/scripts/__pycache__/core.cpython-312.pyc +0 -0
- package/assets/scripts/__pycache__/design_system.cpython-312.pyc +0 -0
- package/assets/scripts/core.py +52 -45
- package/assets/scripts/design_system.py +1074 -0
- package/assets/scripts/search.py +72 -1
- package/assets/templates/base/quick-reference.md +67 -5
- package/assets/templates/base/skill-content-10k.md +220 -0
- package/assets/templates/base/skill-content-4k.md +110 -0
- package/assets/templates/base/skill-content.md +283 -19
- package/assets/templates/platforms/agent.json +3 -2
- package/assets/templates/platforms/claude.json +4 -3
- package/assets/templates/platforms/codebuddy.json +12 -8
- package/assets/templates/platforms/codex.json +6 -5
- package/assets/templates/platforms/continue.json +5 -4
- package/assets/templates/platforms/copilot.json +7 -6
- package/assets/templates/platforms/cursor.json +6 -5
- package/assets/templates/platforms/gemini.json +5 -4
- package/assets/templates/platforms/junie.json +19 -0
- package/assets/templates/platforms/kiro.json +6 -5
- package/assets/templates/platforms/opencode.json +6 -5
- package/assets/templates/platforms/qoder.json +12 -8
- package/assets/templates/platforms/roocode.json +7 -6
- package/assets/templates/platforms/trae.json +6 -5
- package/assets/templates/platforms/vscode.json +19 -0
- package/assets/templates/platforms/windsurf.json +7 -6
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.js +3 -1
- package/dist/utils/detect.js +4 -0
- package/dist/utils/template.js +5 -2
- package/package.json +1 -1
package/assets/scripts/search.py
CHANGED
|
@@ -3,9 +3,15 @@
|
|
|
3
3
|
"""
|
|
4
4
|
Flutter Pro Max Search - CLI for Flutter knowledge base search
|
|
5
5
|
Usage: python search.py "<query>" [--domain <domain>] [--stack <stack>] [--top 5]
|
|
6
|
+
python search.py "<query>" --design-system [-p "Project Name"]
|
|
7
|
+
python search.py "<query>" --design-system --persist [-p "Project Name"] [--page "dashboard"]
|
|
6
8
|
|
|
7
9
|
Domains: widget, package, pattern, architect, chart, color, typography, style, ux, icon, landing, naming, product, prompt, performance, ui-reasoning, accessibility
|
|
8
10
|
Stacks: riverpod, bloc, provider
|
|
11
|
+
|
|
12
|
+
Persistence (Master + Overrides pattern):
|
|
13
|
+
--persist Save design system to design-system/MASTER.md
|
|
14
|
+
--page Also create a page-specific override file in design-system/pages/
|
|
9
15
|
"""
|
|
10
16
|
|
|
11
17
|
import argparse
|
|
@@ -18,9 +24,11 @@ from core import (
|
|
|
18
24
|
search,
|
|
19
25
|
search_with_stack
|
|
20
26
|
)
|
|
27
|
+
from design_system import generate_design_system, persist_design_system
|
|
28
|
+
from typing import Any
|
|
21
29
|
|
|
22
30
|
|
|
23
|
-
def format_output(result):
|
|
31
|
+
def format_output(result: dict[str, Any]) -> str:
|
|
24
32
|
"""Format results for human-readable output (token-optimized for AI)"""
|
|
25
33
|
if "error" in result:
|
|
26
34
|
return f"❌ Error: {result['error']}"
|
|
@@ -86,9 +94,72 @@ Examples:
|
|
|
86
94
|
action="store_true",
|
|
87
95
|
help="Output as JSON"
|
|
88
96
|
)
|
|
97
|
+
# Design system generation
|
|
98
|
+
parser.add_argument(
|
|
99
|
+
"--design-system", "-ds",
|
|
100
|
+
action="store_true",
|
|
101
|
+
help="Generate complete design system recommendation"
|
|
102
|
+
)
|
|
103
|
+
parser.add_argument(
|
|
104
|
+
"--project-name", "-p",
|
|
105
|
+
type=str,
|
|
106
|
+
default=None,
|
|
107
|
+
help="Project name for design system output"
|
|
108
|
+
)
|
|
109
|
+
parser.add_argument(
|
|
110
|
+
"--format", "-f",
|
|
111
|
+
choices=["ascii", "markdown"],
|
|
112
|
+
default="ascii",
|
|
113
|
+
help="Output format for design system"
|
|
114
|
+
)
|
|
115
|
+
# Persistence (Master + Overrides pattern)
|
|
116
|
+
parser.add_argument(
|
|
117
|
+
"--persist",
|
|
118
|
+
action="store_true",
|
|
119
|
+
help="Save design system to design-system/MASTER.md (creates hierarchical structure)"
|
|
120
|
+
)
|
|
121
|
+
parser.add_argument(
|
|
122
|
+
"--page",
|
|
123
|
+
type=str,
|
|
124
|
+
default=None,
|
|
125
|
+
help="Create page-specific override file in design-system/pages/"
|
|
126
|
+
)
|
|
127
|
+
parser.add_argument(
|
|
128
|
+
"--output-dir", "-o",
|
|
129
|
+
type=str,
|
|
130
|
+
default=None,
|
|
131
|
+
help="Output directory for persisted files (default: current directory)"
|
|
132
|
+
)
|
|
89
133
|
|
|
90
134
|
args = parser.parse_args()
|
|
91
135
|
|
|
136
|
+
# Design system takes priority
|
|
137
|
+
if args.design_system:
|
|
138
|
+
result = generate_design_system(
|
|
139
|
+
args.query,
|
|
140
|
+
args.project_name,
|
|
141
|
+
args.format,
|
|
142
|
+
persist=args.persist,
|
|
143
|
+
page=args.page,
|
|
144
|
+
output_dir=args.output_dir
|
|
145
|
+
)
|
|
146
|
+
print(result)
|
|
147
|
+
|
|
148
|
+
# Print persistence confirmation
|
|
149
|
+
if args.persist:
|
|
150
|
+
project_slug = args.project_name.lower().replace(' ', '-') if args.project_name else "default"
|
|
151
|
+
print("\n" + "=" * 60)
|
|
152
|
+
print(f"✅ Design system persisted to design-system/{project_slug}/")
|
|
153
|
+
print(f" 📄 design-system/{project_slug}/MASTER.md (Global Source of Truth)")
|
|
154
|
+
if args.page:
|
|
155
|
+
page_filename = args.page.lower().replace(' ', '-')
|
|
156
|
+
print(f" 📄 design-system/{project_slug}/pages/{page_filename}.md (Screen Overrides)")
|
|
157
|
+
print("")
|
|
158
|
+
print(f"📖 Usage: When building a screen, check design-system/{project_slug}/pages/[screen].md first.")
|
|
159
|
+
print(f" If exists, its rules override MASTER.md. Otherwise, use MASTER.md.")
|
|
160
|
+
print("=" * 60)
|
|
161
|
+
return
|
|
162
|
+
|
|
92
163
|
# Perform search
|
|
93
164
|
if args.stack:
|
|
94
165
|
result = search_with_stack(args.query, args.stack, args.domain, args.top)
|
|
@@ -3,6 +3,25 @@
|
|
|
3
3
|
|
|
4
4
|
## Quick Reference
|
|
5
5
|
|
|
6
|
+
### AI Tools Commands
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
# Format code (ALWAYS run after changes)
|
|
10
|
+
dart format .
|
|
11
|
+
|
|
12
|
+
# Auto-fix common issues
|
|
13
|
+
dart fix --apply
|
|
14
|
+
|
|
15
|
+
# Analyze with lints
|
|
16
|
+
flutter analyze .
|
|
17
|
+
|
|
18
|
+
# Run tests
|
|
19
|
+
flutter test .
|
|
20
|
+
|
|
21
|
+
# Build runner for code generation
|
|
22
|
+
dart run build_runner build --delete-conflicting-outputs
|
|
23
|
+
```
|
|
24
|
+
|
|
6
25
|
### Search Commands
|
|
7
26
|
|
|
8
27
|
```bash
|
|
@@ -12,16 +31,32 @@ python3 {{SCRIPT_PATH}}/search.py "ListView" --top 5
|
|
|
12
31
|
# Specific domain
|
|
13
32
|
python3 {{SCRIPT_PATH}}/search.py "network http" --domain package --top 5
|
|
14
33
|
|
|
15
|
-
# Stack filter
|
|
16
|
-
python3 {{SCRIPT_PATH}}/search.py "state" --stack
|
|
34
|
+
# Stack filter (native-first: valuenotifier, changenotifier)
|
|
35
|
+
python3 {{SCRIPT_PATH}}/search.py "state" --stack provider --top 5
|
|
17
36
|
|
|
18
37
|
# JSON output
|
|
19
38
|
python3 {{SCRIPT_PATH}}/search.py "login" --json --top 3
|
|
20
39
|
```
|
|
21
40
|
|
|
41
|
+
### Package Management
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Add dependency
|
|
45
|
+
flutter pub add <package_name>
|
|
46
|
+
|
|
47
|
+
# Add dev dependency
|
|
48
|
+
flutter pub add dev:<package_name>
|
|
49
|
+
|
|
50
|
+
# Add override
|
|
51
|
+
flutter pub add override:<package_name>:<version>
|
|
52
|
+
|
|
53
|
+
# Remove dependency
|
|
54
|
+
dart pub remove <package_name>
|
|
55
|
+
```
|
|
56
|
+
|
|
22
57
|
### Example Workflow
|
|
23
58
|
|
|
24
|
-
**User Request:** "Tạo màn hình đăng nhập
|
|
59
|
+
**User Request:** "Tạo màn hình đăng nhập"
|
|
25
60
|
|
|
26
61
|
1. **Search widgets:**
|
|
27
62
|
```bash
|
|
@@ -35,7 +70,34 @@ python3 {{SCRIPT_PATH}}/search.py "login" --json --top 3
|
|
|
35
70
|
|
|
36
71
|
3. **Search packages:**
|
|
37
72
|
```bash
|
|
38
|
-
python3 {{SCRIPT_PATH}}/search.py "validation" --domain package --
|
|
73
|
+
python3 {{SCRIPT_PATH}}/search.py "validation" --domain package --top 5
|
|
39
74
|
```
|
|
40
75
|
|
|
41
|
-
4. **Apply results**
|
|
76
|
+
4. **Apply results** với native state management (ValueNotifier/ChangeNotifier)
|
|
77
|
+
|
|
78
|
+
5. **Validate:**
|
|
79
|
+
```bash
|
|
80
|
+
dart format . && flutter analyze . && flutter test .
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Quick Code Templates
|
|
84
|
+
|
|
85
|
+
```dart
|
|
86
|
+
// Structured Logging (use instead of print)
|
|
87
|
+
import 'dart:developer' as developer;
|
|
88
|
+
developer.log('Message', name: 'app.module', error: e, stackTrace: s);
|
|
89
|
+
|
|
90
|
+
// JSON Model
|
|
91
|
+
@JsonSerializable(fieldRename: FieldRename.snake)
|
|
92
|
+
class User {
|
|
93
|
+
final String firstName;
|
|
94
|
+
User({required this.firstName});
|
|
95
|
+
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// GoRouter Setup
|
|
99
|
+
final _router = GoRouter(routes: [
|
|
100
|
+
GoRoute(path: '/', builder: (_, __) => const HomeScreen()),
|
|
101
|
+
]);
|
|
102
|
+
MaterialApp.router(routerConfig: _router);
|
|
103
|
+
```
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
````markdown
|
|
2
|
+
# {{TITLE}}
|
|
3
|
+
|
|
4
|
+
{{DESCRIPTION}}
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 🏛️ ROLE: Flutter Expert
|
|
9
|
+
|
|
10
|
+
Expert Flutter & Dart Developer. Build **beautiful, performant, maintainable** applications.
|
|
11
|
+
|
|
12
|
+
### 🛠️ AI Tools Integration
|
|
13
|
+
|
|
14
|
+
| Tool | Purpose | Usage |
|
|
15
|
+
|------|---------|-------|
|
|
16
|
+
| `dart_format` | Format code | ALWAYS run after changes |
|
|
17
|
+
| `dart_fix` | Auto-fix errors | Run before commit |
|
|
18
|
+
| `flutter analyze` | Lint check | Catch issues early |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 📐 CORE PHILOSOPHIES
|
|
23
|
+
|
|
24
|
+
### SOLID Principles (Mandatory)
|
|
25
|
+
|
|
26
|
+
| Principle | Rule | Example |
|
|
27
|
+
|-----------|------|---------|
|
|
28
|
+
| **S - Single Responsibility** | 1 class = 1 job | `LoginUseCase` only handles login |
|
|
29
|
+
| **O - Open/Closed** | Extend, don't modify | Use `abstract class` over `if-else` |
|
|
30
|
+
| **L - Liskov Substitution** | Subtypes replace base | `GoogleAuth extends AuthProvider` |
|
|
31
|
+
| **I - Interface Segregation** | No forced dependencies | Split `Readable` and `Writable` |
|
|
32
|
+
| **D - Dependency Inversion** | Depend on abstractions | Inject interface, not implementation |
|
|
33
|
+
|
|
34
|
+
### Pragmatic Rules
|
|
35
|
+
|
|
36
|
+
| Rule | Action |
|
|
37
|
+
|------|--------|
|
|
38
|
+
| **DRY** | Logic repeated >2x → Extract |
|
|
39
|
+
| **KISS** | Prefer simplest solution |
|
|
40
|
+
| **YAGNI** | Build only what's needed now |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## ⛔ HARD CONSTRAINTS
|
|
45
|
+
|
|
46
|
+
### NO God Classes/Files
|
|
47
|
+
|
|
48
|
+
| Constraint | Limit | Action |
|
|
49
|
+
|------------|-------|--------|
|
|
50
|
+
| Public methods | ≤10 | 🔴 REFACTOR |
|
|
51
|
+
| Lines of logic | ≤200 | 🔴 REFACTOR |
|
|
52
|
+
| File size | ≤300 lines | 🔴 SPLIT |
|
|
53
|
+
| Classes per file | 1 main | 🔴 SEPARATE |
|
|
54
|
+
|
|
55
|
+
### Code Quality Standards
|
|
56
|
+
|
|
57
|
+
| Rule | Standard |
|
|
58
|
+
|------|----------|
|
|
59
|
+
| Line length | ≤80 characters |
|
|
60
|
+
| Naming | `PascalCase` types, `camelCase` members, `snake_case` files |
|
|
61
|
+
| Functions | <20 lines, single purpose |
|
|
62
|
+
| Null Safety | Sound. Avoid `!` unless guaranteed |
|
|
63
|
+
| Logging | `dart:developer` log(), NEVER print() |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 🎯 DART BEST PRACTICES
|
|
68
|
+
|
|
69
|
+
### Async/Await
|
|
70
|
+
```dart
|
|
71
|
+
Future<User> fetchUser() async {
|
|
72
|
+
try {
|
|
73
|
+
final response = await api.getUser();
|
|
74
|
+
return User.fromJson(response);
|
|
75
|
+
} catch (e, s) {
|
|
76
|
+
developer.log('Failed', error: e, stackTrace: s);
|
|
77
|
+
rethrow;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Pattern Matching (Dart 3+)
|
|
83
|
+
```dart
|
|
84
|
+
// Records
|
|
85
|
+
(String name, int age) getUserInfo() => ('John', 25);
|
|
86
|
+
|
|
87
|
+
// Switch expressions
|
|
88
|
+
String describe(Shape s) => switch (s) {
|
|
89
|
+
Circle(radius: var r) => 'Circle $r',
|
|
90
|
+
Rectangle(w: var w, h: var h) => 'Rect ${w}x$h',
|
|
91
|
+
};
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 🔧 FLUTTER STANDARDS
|
|
97
|
+
|
|
98
|
+
### State Management (Native-First)
|
|
99
|
+
```dart
|
|
100
|
+
// ValueNotifier for simple state
|
|
101
|
+
final counter = ValueNotifier<int>(0);
|
|
102
|
+
ValueListenableBuilder<int>(
|
|
103
|
+
valueListenable: counter,
|
|
104
|
+
builder: (_, value, __) => Text('Count: $value'),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// ChangeNotifier for complex state
|
|
108
|
+
class CartNotifier extends ChangeNotifier {
|
|
109
|
+
final List<Item> _items = [];
|
|
110
|
+
void addItem(Item item) {
|
|
111
|
+
_items.add(item);
|
|
112
|
+
notifyListeners();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
> ⚠️ NO Riverpod/Bloc/GetX unless explicitly requested
|
|
117
|
+
|
|
118
|
+
### Routing (GoRouter)
|
|
119
|
+
```dart
|
|
120
|
+
final router = GoRouter(routes: [
|
|
121
|
+
GoRoute(path: '/', builder: (_, __) => const HomeScreen()),
|
|
122
|
+
GoRoute(
|
|
123
|
+
path: 'details/:id',
|
|
124
|
+
builder: (_, state) => DetailScreen(id: state.pathParameters['id']!),
|
|
125
|
+
),
|
|
126
|
+
]);
|
|
127
|
+
MaterialApp.router(routerConfig: router);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### JSON Serialization
|
|
131
|
+
```dart
|
|
132
|
+
@JsonSerializable(fieldRename: FieldRename.snake)
|
|
133
|
+
class User {
|
|
134
|
+
final String firstName;
|
|
135
|
+
User({required this.firstName});
|
|
136
|
+
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 🎨 THEMING (Material 3)
|
|
143
|
+
|
|
144
|
+
```dart
|
|
145
|
+
final lightTheme = ThemeData(
|
|
146
|
+
colorScheme: ColorScheme.fromSeed(
|
|
147
|
+
seedColor: Colors.deepPurple,
|
|
148
|
+
brightness: Brightness.light,
|
|
149
|
+
),
|
|
150
|
+
useMaterial3: true,
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
final darkTheme = ThemeData(
|
|
154
|
+
colorScheme: ColorScheme.fromSeed(
|
|
155
|
+
seedColor: Colors.deepPurple,
|
|
156
|
+
brightness: Brightness.dark,
|
|
157
|
+
),
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
MaterialApp(
|
|
161
|
+
theme: lightTheme,
|
|
162
|
+
darkTheme: darkTheme,
|
|
163
|
+
themeMode: ThemeMode.system,
|
|
164
|
+
);
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Network Images
|
|
168
|
+
```dart
|
|
169
|
+
Image.network(
|
|
170
|
+
'https://example.com/img.png',
|
|
171
|
+
loadingBuilder: (ctx, child, prog) =>
|
|
172
|
+
prog == null ? child : const CircularProgressIndicator(),
|
|
173
|
+
errorBuilder: (ctx, err, stack) => const Icon(Icons.error),
|
|
174
|
+
);
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## ⚡ PERFORMANCE
|
|
180
|
+
|
|
181
|
+
| Practice | Guideline |
|
|
182
|
+
|----------|-----------|
|
|
183
|
+
| `const` constructors | Use everywhere possible |
|
|
184
|
+
| `ListView.builder` | For long lists |
|
|
185
|
+
| `compute()` | For heavy tasks (JSON parsing) |
|
|
186
|
+
| `SizedBox` | Prefer over `Container` for spacing |
|
|
187
|
+
| Build methods | Keep pure, no side effects |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## ♿ ACCESSIBILITY
|
|
192
|
+
|
|
193
|
+
| Requirement | Standard |
|
|
194
|
+
|-------------|----------|
|
|
195
|
+
| Contrast | Minimum 4.5:1 for text |
|
|
196
|
+
| Large Text | Minimum 3:1 |
|
|
197
|
+
| Dynamic Scaling | Test up to 200% |
|
|
198
|
+
| Semantics | Label all interactive elements |
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## ✅ PRE-DELIVERY CHECKLIST
|
|
203
|
+
|
|
204
|
+
### Architecture
|
|
205
|
+
- [ ] No God Class (≤10 methods, ≤200 lines)
|
|
206
|
+
- [ ] No God File (≤300 lines)
|
|
207
|
+
- [ ] SOLID compliance
|
|
208
|
+
|
|
209
|
+
### Code Quality
|
|
210
|
+
- [ ] `const` constructors
|
|
211
|
+
- [ ] Sound Null Safety
|
|
212
|
+
- [ ] `dart_format` applied
|
|
213
|
+
- [ ] `flutter analyze` passed
|
|
214
|
+
|
|
215
|
+
### Testing
|
|
216
|
+
- [ ] Unit tests for domain
|
|
217
|
+
- [ ] Widget tests for UI
|
|
218
|
+
- [ ] Integration tests for E2E
|
|
219
|
+
{{QUICK_REFERENCE}}
|
|
220
|
+
````
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
````markdown
|
|
2
|
+
# {{TITLE}}
|
|
3
|
+
|
|
4
|
+
{{DESCRIPTION}}
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Role: Flutter Expert
|
|
9
|
+
|
|
10
|
+
Expert Flutter & Dart Developer. Build **beautiful, performant, maintainable** apps.
|
|
11
|
+
|
|
12
|
+
### AI Tools
|
|
13
|
+
- `dart_format` - ALWAYS format code
|
|
14
|
+
- `dart_fix` - Auto-fix errors
|
|
15
|
+
- `flutter analyze` - Lint check
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Core Rules
|
|
20
|
+
|
|
21
|
+
### SOLID (Mandatory)
|
|
22
|
+
| Principle | Rule |
|
|
23
|
+
|-----------|------|
|
|
24
|
+
| **S** | 1 class = 1 responsibility |
|
|
25
|
+
| **O** | Open for extension, closed for modification |
|
|
26
|
+
| **L** | Subtypes replaceable for base types |
|
|
27
|
+
| **I** | No forced unused dependencies |
|
|
28
|
+
| **D** | Depend on abstractions |
|
|
29
|
+
|
|
30
|
+
### Hard Limits
|
|
31
|
+
| Constraint | Limit |
|
|
32
|
+
|------------|-------|
|
|
33
|
+
| God Class | ≤10 methods, ≤200 lines |
|
|
34
|
+
| God File | ≤300 lines |
|
|
35
|
+
| Functions | <20 lines |
|
|
36
|
+
| Line length | ≤80 chars |
|
|
37
|
+
|
|
38
|
+
### Naming
|
|
39
|
+
- `PascalCase` - Types/Classes
|
|
40
|
+
- `camelCase` - Members/Variables
|
|
41
|
+
- `snake_case` - Files
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Flutter Standards
|
|
46
|
+
|
|
47
|
+
### State Management (Native-First)
|
|
48
|
+
```dart
|
|
49
|
+
// ValueNotifier for simple state
|
|
50
|
+
final counter = ValueNotifier<int>(0);
|
|
51
|
+
ValueListenableBuilder(
|
|
52
|
+
valueListenable: counter,
|
|
53
|
+
builder: (_, value, __) => Text('$value'),
|
|
54
|
+
);
|
|
55
|
+
```
|
|
56
|
+
> ⚠️ NO Riverpod/Bloc/GetX unless requested
|
|
57
|
+
|
|
58
|
+
### Routing (GoRouter)
|
|
59
|
+
```dart
|
|
60
|
+
final router = GoRouter(routes: [
|
|
61
|
+
GoRoute(path: '/', builder: (_, __) => HomeScreen()),
|
|
62
|
+
]);
|
|
63
|
+
MaterialApp.router(routerConfig: router);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Theming (Material 3)
|
|
67
|
+
```dart
|
|
68
|
+
ThemeData(
|
|
69
|
+
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
|
70
|
+
useMaterial3: true,
|
|
71
|
+
);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Performance
|
|
75
|
+
- `const` constructors everywhere
|
|
76
|
+
- `ListView.builder` for lists
|
|
77
|
+
- `compute()` for heavy tasks
|
|
78
|
+
- `SizedBox` over `Container`
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Code Quality
|
|
83
|
+
|
|
84
|
+
### Logging
|
|
85
|
+
```dart
|
|
86
|
+
import 'dart:developer' as dev;
|
|
87
|
+
dev.log('Message', name: 'app.module', error: e);
|
|
88
|
+
```
|
|
89
|
+
> ❌ NEVER use `print()`
|
|
90
|
+
|
|
91
|
+
### JSON Model
|
|
92
|
+
```dart
|
|
93
|
+
@JsonSerializable(fieldRename: FieldRename.snake)
|
|
94
|
+
class User {
|
|
95
|
+
final String name;
|
|
96
|
+
User({required this.name});
|
|
97
|
+
factory User.fromJson(Map<String, dynamic> j) => _$UserFromJson(j);
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Checklist
|
|
104
|
+
- [ ] No God Class/File
|
|
105
|
+
- [ ] `const` constructors
|
|
106
|
+
- [ ] Sound null safety
|
|
107
|
+
- [ ] `dart_format` applied
|
|
108
|
+
- [ ] Tests written
|
|
109
|
+
{{QUICK_REFERENCE}}
|
|
110
|
+
````
|