@bdayadev/flutter-ultra-mcp 1.12.0 → 1.13.0

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.
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: apply-architecture-best-practices
3
3
  description: Architects a Flutter application using the recommended layered approach (UI, Logic, Data). Use when structuring a new project or refactoring for scalability.
4
+ last_modified: Tue, 21 Apr 2026 20:11:20 GMT
4
5
  ---
5
6
 
6
7
  # Architecting Flutter Applications
@@ -14,28 +15,30 @@ description: Architects a Flutter application using the recommended layered appr
14
15
 
15
16
  ## Architectural Layers
16
17
 
17
- Enforce strict Separation of Concerns by dividing the application into distinct layers.
18
+ Enforce strict Separation of Concerns by dividing the application into distinct layers. Never mix UI rendering with business logic or data fetching.
18
19
 
19
20
  ### UI Layer (Presentation)
20
21
 
21
- Implement the MVVM (Model-View-ViewModel) pattern.
22
+ Implement the MVVM (Model-View-ViewModel) pattern to manage UI state and logic.
22
23
 
23
- - **Views:** Reusable, lean widgets. Restrict logic to UI-specific operations.
24
- - **ViewModels:** Manage UI state. Extend `ChangeNotifier`. Expose immutable state snapshots. Inject Repositories via constructor.
24
+ - **Views:** Write reusable, lean widgets. Restrict logic in Views to UI-specific operations (e.g., animations, layout constraints, simple routing). Pass all required data from the ViewModel.
25
+ - **ViewModels:** Manage UI state and handle user interactions. Extend `ChangeNotifier` (or use `Listenable`) to expose state. Expose immutable state snapshots to the View. Inject Repositories into ViewModels via the constructor.
25
26
 
26
27
  ### Data Layer
27
28
 
28
- Implement the Repository pattern for a single source of truth.
29
+ Implement the Repository pattern to isolate data access logic and create a single source of truth.
29
30
 
30
- - **Services:** Stateless classes wrapping external APIs. Return raw API models or `Result` wrappers.
31
- - **Repositories:** Consume Services. Transform raw models into Domain Models. Handle caching and retry logic.
31
+ - **Services:** Create stateless classes to wrap external APIs (HTTP clients, local databases, platform plugins). Return raw API models or `Result` wrappers.
32
+ - **Repositories:** Consume one or more Services. Transform raw API models into clean Domain Models. Handle caching, offline synchronization, and retry logic. Expose Domain Models to ViewModels.
32
33
 
33
34
  ### Logic Layer (Domain - Optional)
34
35
 
35
- - **Use Cases:** Only if complex business logic clutters the ViewModel, or logic must be reused across ViewModels.
36
+ - **Use Cases:** Implement this layer only if the application contains complex business logic that clutters the ViewModel, or if logic must be reused across multiple ViewModels. Extract this logic into dedicated Use Case (interactor) classes that sit between ViewModels and Repositories.
36
37
 
37
38
  ## Project Structure
38
39
 
40
+ Organize the codebase using a hybrid approach: group UI components by feature, and group Data/Domain components by type.
41
+
39
42
  ```text
40
43
  lib/
41
44
  ├── data/
@@ -55,37 +58,46 @@ lib/
55
58
 
56
59
  ## Workflow: Implementing a New Feature
57
60
 
61
+ Follow this sequential workflow when adding a new feature to the application. Copy the checklist to track progress.
62
+
58
63
  ### Task Progress
59
64
 
60
- - [ ] **Step 1:** Define Domain Models (immutable data classes).
61
- - [ ] **Step 2:** Implement Services (external API communication).
62
- - [ ] **Step 3:** Implement Repositories (consume Services, return Domain Models).
63
- - [ ] **Step 4:** Apply Conditional Logic:
64
- - Complex data transformation or cross-repository logic: Create a Use Case.
65
- - Simple CRUD: Skip to Step 5.
66
- - [ ] **Step 5:** Implement the ViewModel (extend `ChangeNotifier`, inject Repositories).
67
- - [ ] **Step 6:** Implement the View (use `ListenableBuilder` to listen to ViewModel).
68
- - [ ] **Step 7:** Inject Dependencies (register in DI container).
69
- - [ ] **Step 8:** Run tests. Feedback Loop: Run -> Review -> Fix -> Re-run.
65
+ - [ ] **Step 1: Define Domain Models.** Create immutable data classes for the feature using `freezed` or `built_value`.
66
+ - [ ] **Step 2: Implement Services.** Create or update Service classes to handle external API communication.
67
+ - [ ] **Step 3: Implement Repositories.** Create the Repository to consume Services and return Domain Models.
68
+ - [ ] **Step 4: Apply Conditional Logic (Domain Layer).**
69
+ - _If the feature requires complex data transformation or cross-repository logic:_ Create a Use Case class.
70
+ - _If the feature is a simple CRUD operation:_ Skip to Step 5.
71
+ - [ ] **Step 5: Implement the ViewModel.** Create the ViewModel extending `ChangeNotifier`. Inject required Repositories/Use Cases. Expose immutable state and command methods.
72
+ - [ ] **Step 6: Implement the View.** Create the UI widget. Use `ListenableBuilder` or `AnimatedBuilder` to listen to ViewModel changes.
73
+ - [ ] **Step 7: Inject Dependencies.** Register the new Service, Repository, and ViewModel in the dependency injection container (e.g., `provider` or `get_it`).
74
+ - [ ] **Step 8: Run Validator.** Execute unit tests for the ViewModel and Repository.
75
+ - _Feedback Loop:_ Run tests -> Review failures -> Fix logic -> Re-run until passing.
70
76
 
71
77
  ## Examples
72
78
 
73
79
  ### Data Layer: Service and Repository
74
80
 
75
81
  ```dart
82
+ // 1. Service (Raw API interaction)
76
83
  class ApiClient {
77
- Future<UserApiModel> fetchUser(String id) async { /* ... */ }
84
+ Future<UserApiModel> fetchUser(String id) async {
85
+ // HTTP GET implementation...
86
+ }
78
87
  }
79
88
 
89
+ // 2. Repository (Single source of truth, returns Domain Model)
80
90
  class UserRepository {
81
91
  UserRepository({required ApiClient apiClient}) : _apiClient = apiClient;
92
+
82
93
  final ApiClient _apiClient;
83
94
  User? _cachedUser;
84
95
 
85
96
  Future<User> getUser(String id) async {
86
97
  if (_cachedUser != null) return _cachedUser!;
98
+
87
99
  final apiModel = await _apiClient.fetchUser(id);
88
- _cachedUser = User(id: apiModel.id, name: apiModel.fullName);
100
+ _cachedUser = User(id: apiModel.id, name: apiModel.fullName); // Transform to Domain Model
89
101
  return _cachedUser!;
90
102
  }
91
103
  }
@@ -94,19 +106,23 @@ class UserRepository {
94
106
  ### UI Layer: ViewModel and View
95
107
 
96
108
  ```dart
109
+ // 3. ViewModel (State management and presentation logic)
97
110
  class ProfileViewModel extends ChangeNotifier {
98
111
  ProfileViewModel({required UserRepository userRepository})
99
112
  : _userRepository = userRepository;
113
+
100
114
  final UserRepository _userRepository;
101
115
 
102
116
  User? _user;
103
117
  User? get user => _user;
118
+
104
119
  bool _isLoading = false;
105
120
  bool get isLoading => _isLoading;
106
121
 
107
122
  Future<void> loadProfile(String id) async {
108
123
  _isLoading = true;
109
124
  notifyListeners();
125
+
110
126
  try {
111
127
  _user = await _userRepository.getUser(id);
112
128
  } finally {
@@ -116,8 +132,10 @@ class ProfileViewModel extends ChangeNotifier {
116
132
  }
117
133
  }
118
134
 
135
+ // 4. View (Dumb UI component)
119
136
  class ProfileView extends StatelessWidget {
120
137
  const ProfileView({super.key, required this.viewModel});
138
+
121
139
  final ProfileViewModel viewModel;
122
140
 
123
141
  @override
@@ -125,16 +143,24 @@ class ProfileView extends StatelessWidget {
125
143
  return ListenableBuilder(
126
144
  listenable: viewModel,
127
145
  builder: (context, _) {
128
- if (viewModel.isLoading) return const Center(child: CircularProgressIndicator());
146
+ if (viewModel.isLoading) {
147
+ return const Center(child: CircularProgressIndicator());
148
+ }
149
+
129
150
  final user = viewModel.user;
130
- if (user == null) return const Center(child: Text('User not found'));
131
- return Column(children: [
132
- Text(user.name),
133
- ElevatedButton(
134
- onPressed: () => viewModel.loadProfile(user.id),
135
- child: const Text('Refresh'),
136
- ),
137
- ]);
151
+ if (user == null) {
152
+ return const Center(child: Text('User not found'));
153
+ }
154
+
155
+ return Column(
156
+ children: [
157
+ Text(user.name),
158
+ ElevatedButton(
159
+ onPressed: () => viewModel.loadProfile(user.id),
160
+ child: const Text('Refresh'),
161
+ ),
162
+ ],
163
+ );
138
164
  },
139
165
  );
140
166
  }
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: build-cli-app
3
3
  description: Entrypoint structure, exit codes, cross-platform scripts. Use when building command line utilities, scripts, or applications.
4
+ last_modified: Fri, 04 May 2026 17:41:00 GMT
4
5
  ---
5
6
 
6
7
  # Building Dart CLI Applications
@@ -32,7 +33,7 @@ Import the `args` package to manage command-line arguments, flags, and subcomman
32
33
  - If building a complex, multi-command CLI (like `git`): Implement `CommandRunner` and extend `Command` for each subcommand.
33
34
  - Define global arguments on the `CommandRunner.argParser` and command-specific arguments on the individual `Command.argParser`.
34
35
  - Catch `UsageException` to gracefully handle invalid arguments and display the automatically generated help text.
35
- - **Validate Help Text Accuracy**: Ensure the help text provides all necessary information to run the tool.
36
+ - **Validate Help Text Accuracy**: Ensure the help text provides all necessary information to run the tool. If the help text references a compiled executable name, and the user needs to add it to their PATH to run it that way, provide clear instructions on how to do so in the help text or description.
36
37
 
37
38
  ## Execution & Error Handling
38
39
 
@@ -42,11 +43,14 @@ Leverage the `io` and `stack_trace` packages to build robust, production-ready C
42
43
  - Use `sharedStdIn` from the `io` package if multiple asynchronous listeners need sequential access to standard input.
43
44
  - Wrap the application execution in `Chain.capture()` from the `stack_trace` package to track asynchronous stack chains.
44
45
  - Format output stack traces using `Trace.terse` or `Chain.terse` to strip noisy core library frames and present readable errors to the user.
45
- - **Do not swallow exceptions** in lower-level logic unless recovery is possible. Let them bubble up.
46
- - **Fail fast and with non-zero exit codes**: Ensure operation failures result in descriptive error messages to `stderr` and appropriate non-zero exit codes.
46
+ - **Do not swallow exceptions** in lower-level logic or storage classes unless recovery is possible. Let them bubble up or rethrow them so higher-level commands know operations failed.
47
+ - **Fail fast and with non-zero exit codes**: Ensure operation failures result in descriptive error messages to `stderr` and appropriate non-zero exit codes (e.g., using `exit(1)` or triggering a 64 exit code after a caught `UsageException`).
47
48
 
48
49
  ## Testing CLI Applications
49
50
 
51
+ > [!IMPORTANT]
52
+ > **All new commands and significant features must be covered by automated tests.** Manual verification is not sufficient for testing logic. However, manual verification of help text and user experience (UX) is still required to ensure the interface is intuitive and correct.
53
+
50
54
  Use `test_process` and `test_descriptor` to write high-fidelity integration tests for your CLI.
51
55
 
52
56
  - Define expected filesystem states using `test_descriptor` (`d.dir`, `d.file`).
@@ -61,9 +65,25 @@ Use `test_process` and `test_descriptor` to write high-fidelity integration test
61
65
  Select the appropriate compilation target based on your distribution requirements.
62
66
 
63
67
  - **If testing locally during development:** Use `dart run bin/cli.dart`. This uses the JIT compiler for rapid iteration.
64
- - **If bundling code assets and dynamic libraries:** Use `dart build cli`.
65
- - **If distributing a standalone native executable:** Use `dart compile exe bin/cli.dart -o <output_path>`.
66
- - **If distributing multiple apps with strict disk space limits:** Use `dart compile aot-snapshot bin/cli.dart`.
68
+ - **If bundling code assets and dynamic libraries:** Use `dart build cli`. This runs build hooks and outputs to `build/cli/_/bundle/`.
69
+ - **If distributing a standalone native executable:** Use `dart compile exe bin/cli.dart -o <output_path>`. This bundles the Dart runtime and machine code into a single file.
70
+ - **If distributing multiple apps with strict disk space limits:** Use `dart compile aot-snapshot bin/cli.dart`. Run the resulting `.aot` file using `dartaotruntime`.
71
+
72
+ <details>
73
+ <summary>Cross-Compilation Targets (Linux Only)</summary>
74
+
75
+ Dart supports cross-compiling to Linux from macOS, Windows, or Linux hosts.
76
+ Use the `--target-os` and `--target-arch` flags with `dart compile exe` or `dart compile aot-snapshot`.
77
+
78
+ - `--target-os=linux` (Only Linux is currently supported as a cross-compilation target)
79
+ - `--target-arch=arm64` (64-bit ARM)
80
+ - `--target-arch=x64` (x86-64)
81
+ - `--target-arch=arm` (32-bit ARM)
82
+ - `--target-arch=riscv64` (64-bit RISC-V)
83
+
84
+ Example: `dart compile exe --target-os=linux --target-arch=arm64 bin/cli.dart`
85
+
86
+ </details>
67
87
 
68
88
  ## Workflows
69
89
 
@@ -74,9 +94,9 @@ Select the appropriate compilation target based on your distribution requirement
74
94
  - [ ] Register command-specific flags in the constructor using `argParser.addFlag()` or `argParser.addOption()`.
75
95
  - [ ] Implement the `run()` method with the core logic.
76
96
  - [ ] Register the new command in the `CommandRunner` instance in `bin/cli.dart` using `addCommand()`.
77
- - [ ] Create tests for the new command in the `test/` directory.
97
+ - [ ] Create tests for the new command in the `test/` directory using `test_process` or standard tests.
78
98
  - [ ] Run validator -> Execute `dart run bin/cli.dart help <command_name>` to verify help text generation.
79
- - [ ] Verify final UX: Compile the application using `dart compile exe` and run the resulting executable.
99
+ - [ ] Verify final UX: Compile the application using `dart compile exe` and run the resulting executable to verify the target user experience (e.g., `./bin/cli <command>`).
80
100
 
81
101
  ### Task Progress: Compile and Release Native Executable
82
102
 
@@ -84,6 +104,7 @@ Select the appropriate compilation target based on your distribution requirement
84
104
  - [ ] Run validator -> Execute `dart analyze` to ensure no static analysis errors.
85
105
  - [ ] Run validator -> Execute `dart test` to pass all integration tests.
86
106
  - [ ] Compile for host OS: `dart compile exe bin/cli.dart -o build/cli-host`
107
+ - [ ] Compile for Linux (if host is macOS/Windows): `dart compile exe --target-os=linux --target-arch=x64 bin/cli.dart -o build/cli-linux-x64`
87
108
 
88
109
  ## Examples
89
110
 
@@ -121,7 +142,7 @@ void main(List<String> args) {
121
142
  if (error is UsageException) {
122
143
  stderr.writeln(error.message);
123
144
  stderr.writeln(error.usage);
124
- exit(64);
145
+ exit(64); // ExitCode.usage.code
125
146
  } else {
126
147
  stderr.writeln('Fatal error: $error');
127
148
  stderr.writeln(chain.terse);
@@ -140,18 +161,24 @@ import 'package:test_descriptor/test_descriptor.dart' as d;
140
161
 
141
162
  void main() {
142
163
  test('CLI formats output correctly and modifies filesystem', () async {
164
+ // 1. Setup mock filesystem
143
165
  await d.dir('project', [
144
166
  d.file('config.json', '{"key": "value"}')
145
167
  ]).create();
146
168
 
169
+ // 2. Spawn the CLI process
147
170
  final process = await TestProcess.start(
148
171
  'dart',
149
172
  ['run', 'bin/cli.dart', 'process', '--path', '${d.sandbox}/project']
150
173
  );
151
174
 
175
+ // 3. Validate stdout stream
152
176
  await expectLater(process.stdout, emitsThrough('Processing complete.'));
177
+
178
+ // 4. Validate exit code
153
179
  await process.shouldExit(0);
154
180
 
181
+ // 5. Validate filesystem mutations
155
182
  await d.dir('project', [
156
183
  d.file('config.json', '{"key": "value"}'),
157
184
  d.file('output.log', 'Success')
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: build-responsive-layout
3
3
  description: Use `LayoutBuilder`, `MediaQuery`, or `Expanded/Flexible` to create a layout that adapts to different screen sizes. Use when you need the UI to look good on both mobile and tablet/desktop form factors.
4
+ last_modified: Tue, 21 Apr 2026 20:17:40 GMT
4
5
  ---
5
6
 
6
7
  # Implementing Adaptive Layouts
@@ -16,49 +17,64 @@ description: Use `LayoutBuilder`, `MediaQuery`, or `Expanded/Flexible` to create
16
17
 
17
18
  ## Space Measurement Guidelines
18
19
 
20
+ Determine the available space accurately to ensure layouts adapt to the app window, not just the physical device.
21
+
19
22
  - **Use `MediaQuery.sizeOf(context)`** to get the size of the entire app window.
20
- - **Use `LayoutBuilder`** to make layout decisions based on the parent widget's allocated space.
21
- - **Do not use `MediaQuery.orientationOf` or `OrientationBuilder`** near the top of the widget tree. Device orientation does not accurately reflect available space.
22
- - **Do not check for hardware types** ("phone" vs. "tablet"). Base all decisions strictly on available window space.
23
+ - **Use `LayoutBuilder`** to make layout decisions based on the parent widget's allocated space. Evaluate `constraints.maxWidth` to determine the appropriate widget tree to return.
24
+ - **Do not use `MediaQuery.orientationOf` or `OrientationBuilder`** near the top of the widget tree to switch layouts. Device orientation does not accurately reflect the available app window space.
25
+ - **Do not check for hardware types** (e.g., "phone" vs. "tablet"). Flutter apps run in resizable windows, multi-window modes, and picture-in-picture. Base all layout decisions strictly on available window space.
23
26
 
24
27
  ## Widget Sizing and Constraints
25
28
 
26
- - **`Expanded`**: Force a child to fill all remaining available space.
27
- - **`Flexible`**: Allow a child to size itself up to a limit while expanding/contracting. Use `flex` factor for sibling ratios.
28
- - **Constrain Width**: Wrap widgets in `ConstrainedBox` with `maxWidth` on large screens.
29
- - **Lazy Rendering**: Use `ListView.builder` or `GridView.builder` for long/unknown-length lists.
29
+ Understand and apply Flutter's core layout rule: **Constraints go down. Sizes go up. Parent sets position.**
30
+
31
+ - **Distribute Space:** Use `Expanded` and `Flexible` within `Row`, `Column`, or `Flex` widgets.
32
+ - Use `Expanded` to force a child to fill all remaining available space (equivalent to `Flexible` with `fit: FlexFit.tight` and a `flex` factor of 1.0).
33
+ - Use `Flexible` to allow a child to size itself up to a specific limit while still expanding/contracting. Use the `flex` factor to define the ratio of space consumption among siblings.
34
+ - **Constrain Width:** Prevent widgets from consuming all horizontal space on large screens. Wrap widgets like `GridView` or `ListView` in a `ConstrainedBox` or `Container` and define a `maxWidth` in the `BoxConstraints`.
35
+ - **Lazy Rendering:** Always use `ListView.builder` or `GridView.builder` when rendering lists with an unknown or large number of items.
30
36
 
31
37
  ## Device and Orientation Behaviors
32
38
 
33
- - **Do not lock screen orientation.** Causes severe layout issues on foldable devices.
34
- - **Support Multiple Inputs:** Implement support for mice, trackpads, and keyboard shortcuts.
39
+ Ensure the app behaves correctly across all device form factors and input methods.
40
+
41
+ - **Do not lock screen orientation.** Locking orientation causes severe layout issues on foldable devices, often resulting in letterboxing (the app centered with black borders). Android large format tiers require both portrait and landscape support.
42
+ - **Fallback for Locked Orientation:** If business requirements strictly mandate a locked orientation, use the `Display API` to retrieve physical screen dimensions instead of `MediaQuery`. `MediaQuery` fails to receive the larger window size in compatibility modes.
43
+ - **Support Multiple Inputs:** Implement support for basic mice, trackpads, and keyboard shortcuts. Ensure touch targets are appropriately sized and keyboard navigation is accessible.
35
44
 
36
45
  ## Workflow: Constructing an Adaptive Layout
37
46
 
47
+ Follow this workflow to implement a layout that adapts to the available `BoxConstraints`.
48
+
38
49
  **Task Progress:**
39
50
 
40
- - [ ] Identify the target widget.
41
- - [ ] Wrap in a `LayoutBuilder`.
42
- - [ ] Extract `constraints.maxWidth`.
43
- - [ ] Define breakpoint (e.g., `600`).
44
- - [ ] If `maxWidth > breakpoint`: Return large-screen layout (e.g., `Row` with sidebar).
45
- - [ ] If `maxWidth <= breakpoint`: Return small-screen layout.
46
- - [ ] Resize the app window -> review transitions -> fix overflow errors.
51
+ - [ ] Identify the target widget that requires adaptive behavior.
52
+ - [ ] Wrap the widget tree in a `LayoutBuilder`.
53
+ - [ ] Extract the `constraints.maxWidth` from the builder callback.
54
+ - [ ] Define an adaptive breakpoint (e.g., `largeScreenMinWidth = 600`).
55
+ - [ ] **If `maxWidth > largeScreenMinWidth`:** Return a large-screen layout (e.g., a `Row` placing a navigation sidebar and content area side-by-side).
56
+ - [ ] **If `maxWidth <= largeScreenMinWidth`:** Return a small-screen layout (e.g., a `Column` or standard navigation-style approach).
57
+ - [ ] Run validator -> resize the application window -> review layout transitions -> fix overflow errors.
47
58
 
48
59
  ## Workflow: Optimizing for Large Screens
49
60
 
61
+ Follow this workflow to prevent UI elements from stretching unnaturally on large displays.
62
+
50
63
  **Task Progress:**
51
64
 
52
- - [ ] Identify full-width components.
53
- - [ ] **Lists**: Convert `ListView.builder` to `GridView.builder` with `SliverGridDelegateWithMaxCrossAxisExtent`.
54
- - [ ] **Forms/text**: Wrap in `ConstrainedBox` with `BoxConstraints(maxWidth: ...)`.
55
- - [ ] Wrap in `Center` to keep constrained content centered.
56
- - [ ] Test on desktop/tablet -> review horizontal stretching.
65
+ - [ ] Identify full-width components (e.g., `ListView`, text blocks, forms).
66
+ - [ ] **If optimizing a list:** Convert `ListView.builder` to `GridView.builder` using `SliverGridDelegateWithMaxCrossAxisExtent` to automatically adjust column counts based on window size.
67
+ - [ ] **If optimizing a form or text block:** Wrap the component in a `ConstrainedBox`.
68
+ - [ ] Apply `BoxConstraints(maxWidth: [optimal_width])` to the `ConstrainedBox`.
69
+ - [ ] Wrap the `ConstrainedBox` in a `Center` widget to keep the constrained content centered on large screens.
70
+ - [ ] Run validator -> test on desktop/tablet target -> review horizontal stretching -> adjust `maxWidth` or grid extents.
57
71
 
58
72
  ## Examples
59
73
 
60
74
  ### Adaptive Layout using LayoutBuilder
61
75
 
76
+ Demonstrates switching between a mobile and desktop layout based on available width.
77
+
62
78
  ```dart
63
79
  import 'package:flutter/material.dart';
64
80
 
@@ -72,25 +88,37 @@ class AdaptiveLayout extends StatelessWidget {
72
88
  return LayoutBuilder(
73
89
  builder: (context, constraints) {
74
90
  if (constraints.maxWidth > largeScreenMinWidth) {
75
- return Row(
76
- children: [
77
- const SizedBox(width: 250, child: Placeholder(color: Colors.blue)),
78
- const VerticalDivider(width: 1),
79
- Expanded(child: const Placeholder(color: Colors.green)),
80
- ],
81
- );
91
+ return _buildLargeScreenLayout();
82
92
  } else {
83
- return const Placeholder(color: Colors.green);
93
+ return _buildSmallScreenLayout();
84
94
  }
85
95
  },
86
96
  );
87
97
  }
98
+
99
+ Widget _buildLargeScreenLayout() {
100
+ return Row(
101
+ children: [
102
+ const SizedBox(width: 250, child: Placeholder(color: Colors.blue)),
103
+ const VerticalDivider(width: 1),
104
+ Expanded(child: const Placeholder(color: Colors.green)),
105
+ ],
106
+ );
107
+ }
108
+
109
+ Widget _buildSmallScreenLayout() {
110
+ return const Placeholder(color: Colors.green);
111
+ }
88
112
  }
89
113
  ```
90
114
 
91
115
  ### Constraining Width on Large Screens
92
116
 
117
+ Demonstrates preventing a widget from consuming all horizontal space.
118
+
93
119
  ```dart
120
+ import 'package:flutter/material.dart';
121
+
94
122
  class ConstrainedContent extends StatelessWidget {
95
123
  const ConstrainedContent({super.key});
96
124
 
@@ -99,10 +127,16 @@ class ConstrainedContent extends StatelessWidget {
99
127
  return Scaffold(
100
128
  body: Center(
101
129
  child: ConstrainedBox(
102
- constraints: const BoxConstraints(maxWidth: 800.0),
130
+ constraints: const BoxConstraints(
131
+ maxWidth: 800.0, // Maximum width for readability
132
+ ),
103
133
  child: ListView.builder(
104
134
  itemCount: 50,
105
- itemBuilder: (context, index) => ListTile(title: Text('Item $index')),
135
+ itemBuilder: (context, index) {
136
+ return ListTile(
137
+ title: Text('Item $index'),
138
+ );
139
+ },
106
140
  ),
107
141
  ),
108
142
  ),
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: collect-coverage
3
- description: Collect coverage using the coverage package and create an LCOV report
3
+ description: Collect coverage using the coverage packge and create an LCOV report
4
+ last_modified: Fri, 24 Apr 2026 15:14:32 GMT
4
5
  ---
5
6
 
6
7
  # Implementing Dart and Flutter Test Coverage
@@ -63,8 +64,12 @@ Use the bundled `test_with_coverage` script. This script automatically runs all
63
64
  dart run coverage:test_with_coverage
64
65
  ```
65
66
 
67
+ _Note: If working within a Dart workspace (monorepo), specify the test directories explicitly (e.g., `dart run coverage:test_with_coverage -- pkgs/foo/test pkgs/bar/test`)._
68
+
66
69
  ### 3. Feedback Loop: Validate Output
67
70
 
71
+ **Run validator -> review errors -> fix:**
72
+
68
73
  1. Verify that the `coverage/` directory was created in the project root.
69
74
  2. Ensure `coverage/coverage.json` (raw data) and `coverage/lcov.info` (formatted report) exist.
70
75
  3. If coverage is missing for specific files, ensure they are imported and executed by your test files, or add `// coverage:ignore-file` if they are intentionally excluded.
@@ -95,6 +100,8 @@ Extract the coverage data from the running VM service and output it to a JSON fi
95
100
  dart run coverage:collect_coverage --wait-paused --uri=http://127.0.0.1:8181/ -o coverage/coverage.json --resume-isolates
96
101
  ```
97
102
 
103
+ _Optional: Append `--function-coverage` and `--branch-coverage` to gather deeper metrics (requires Dart VM 2.17.0+)._
104
+
98
105
  ### 3. Format to LCOV
99
106
 
100
107
  Convert the raw JSON data into the standard LCOV format.
@@ -107,6 +114,8 @@ dart run coverage:format_coverage --packages=.dart_tool/package_config.json --lc
107
114
 
108
115
  ### Example: `pubspec.yaml` Configuration
109
116
 
117
+ Ensure your `pubspec.yaml` reflects the `coverage` package strictly under `dev_dependencies`.
118
+
110
119
  ```yaml
111
120
  name: my_dart_app
112
121
  environment:
@@ -122,6 +131,8 @@ dev_dependencies:
122
131
 
123
132
  ### Example: Applying Ignore Directives
124
133
 
134
+ Use ignore directives to prevent generated code or untestable edge cases from lowering coverage scores.
135
+
125
136
  ```dart
126
137
  // coverage:ignore-file
127
138
  import 'package:meta/meta.dart';
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: fix-layout-issues
3
3
  description: Fixes Flutter layout errors (overflows, unbounded constraints) using Dart and Flutter MCP tools. Use when addressing "RenderFlex overflowed", "Vertical viewport was given unbounded height", or similar layout issues.
4
+ last_modified: Tue, 21 Apr 2026 19:45:59 GMT
4
5
  ---
5
6
 
6
7
  # Resolving Flutter Layout Errors
@@ -13,35 +14,40 @@ description: Fixes Flutter layout errors (overflows, unbounded constraints) usin
13
14
 
14
15
  ## Constraint Violation Diagnostics
15
16
 
16
- Flutter layout operates on: **Constraints go down. Sizes go up. Parent sets position.** Layout errors occur when this negotiation fails.
17
+ Flutter layout operates on a strict rule: **Constraints go down. Sizes go up. Parent sets position.** Layout errors occur when this negotiation fails, typically due to unbounded constraints or unconstrained children.
17
18
 
18
- - **"Vertical viewport was given unbounded height"**: Scrollable widget (`ListView`, `GridView`) inside unconstrained vertical parent (`Column`).
19
- - **"An InputDecorator...cannot have an unbounded width"**: `TextField` inside unconstrained horizontal parent (`Row`).
20
- - **"RenderFlex overflowed"**: Child of `Row` or `Column` requests more size than available. Yellow and black warning stripes.
21
- - **"Incorrect use of ParentData widget"**: `ParentDataWidget` not a direct descendant of required ancestor (e.g., `Expanded` outside a `Flex`).
22
- - **"RenderBox was not laid out"**: Cascading side-effect. Look further up the stack trace for the primary violation.
19
+ Diagnose layout failures using the following error signatures:
20
+
21
+ - **"Vertical viewport was given unbounded height"**: Triggered when a scrollable widget (`ListView`, `GridView`) is placed inside an unconstrained vertical parent (`Column`). The parent provides infinite height, and the child attempts to expand infinitely.
22
+ - **"An InputDecorator...cannot have an unbounded width"**: Triggered when a `TextField` or `TextFormField` is placed inside an unconstrained horizontal parent (`Row`). The text field attempts to determine its width based on infinite available space.
23
+ - **"RenderFlex overflowed"**: Triggered when a child of a `Row` or `Column` requests a size larger than the parent's allocated constraints. Visually indicated by yellow and black warning stripes.
24
+ - **"Incorrect use of ParentData widget"**: Triggered when a `ParentDataWidget` is not a direct descendant of its required ancestor. (e.g., `Expanded` outside a `Flex`, `Positioned` outside a `Stack`).
25
+ - **"RenderBox was not laid out"**: A cascading side-effect error. Ignore this and look further up the stack trace for the primary constraint violation (usually an unbounded height/width error).
23
26
 
24
27
  ## Layout Error Resolution Workflow
25
28
 
29
+ Copy and use this checklist to systematically resolve layout constraint violations.
30
+
26
31
  ### Task Progress
27
32
 
28
- - [ ] Run the application in debug mode to capture the exception.
29
- - [ ] Identify the primary error message (ignore cascading errors).
30
- - [ ] Apply the conditional fix:
31
- - **"Unbounded height"**: Wrap scrollable child in `Expanded` or `SizedBox`.
32
- - **"Unbounded width"**: Wrap `TextField` in `Expanded` or `Flexible`.
33
- - **"RenderFlex overflowed"**: Wrap overflowing child in `Expanded` or `Flexible`.
34
- - **"Incorrect ParentData"**: Move the widget to be a direct child of its required parent.
33
+ - [ ] Run the application in debug mode to capture the exact layout exception in the console.
34
+ - [ ] Identify the primary error message (ignore cascading "RenderBox was not laid out" errors).
35
+ - [ ] Apply the conditional fix based on the specific error type:
36
+ - **If "Vertical viewport was given unbounded height"**: Wrap the scrollable child (`ListView`, `GridView`) in an `Expanded` widget to consume remaining space, or wrap it in a `SizedBox` to provide an absolute height constraint.
37
+ - **If "An InputDecorator...cannot have an unbounded width"**: Wrap the `TextField` or `TextFormField` in an `Expanded` or `Flexible` widget.
38
+ - **If "RenderFlex overflowed"**: Constrain the overflowing child by wrapping it in an `Expanded` widget (to force it to fit) or a `Flexible` widget (to allow it to be smaller than the allocated space).
39
+ - **If "Incorrect use of ParentData widget"**: Move the `ParentDataWidget` to be a direct child of its required parent. Ensure `Expanded`/`Flexible` are direct children of `Row`/`Column`/`Flex`. Ensure `Positioned` is a direct child of `Stack`.
35
40
  - [ ] Execute Flutter hot reload.
36
- - [ ] Verify the error screen or overflow stripes are resolved. Repeat if new errors appear.
41
+ - [ ] Run validator -> review errors -> fix: Inspect the UI to verify the red/grey error screen or yellow/black overflow stripes are resolved. If new layout errors appear, repeat the workflow.
37
42
 
38
43
  ## Examples
39
44
 
40
45
  ### Fixing Unbounded Height (ListView in Column)
41
46
 
42
- **Before (Error):**
47
+ **Input (Error State):**
43
48
 
44
49
  ```dart
50
+ // Throws "Vertical viewport was given unbounded height"
45
51
  Column(
46
52
  children: <Widget>[
47
53
  const Text('Header'),
@@ -55,9 +61,10 @@ Column(
55
61
  )
56
62
  ```
57
63
 
58
- **After (Fixed):**
64
+ **Output (Resolved State):**
59
65
 
60
66
  ```dart
67
+ // Wrap ListView in Expanded to constrain its height to the remaining Column space
61
68
  Column(
62
69
  children: <Widget>[
63
70
  const Text('Header'),
@@ -75,15 +82,59 @@ Column(
75
82
 
76
83
  ### Fixing Unbounded Width (TextField in Row)
77
84
 
78
- **Before:** `Row(children: [Icon(Icons.search), TextField()])`
85
+ **Input (Error State):**
86
+
87
+ ```dart
88
+ // Throws "An InputDecorator...cannot have an unbounded width"
89
+ Row(
90
+ children: [
91
+ const Icon(Icons.search),
92
+ TextField(),
93
+ ],
94
+ )
95
+ ```
79
96
 
80
- **After:** `Row(children: [Icon(Icons.search), Expanded(child: TextField())])`
97
+ **Output (Resolved State):**
98
+
99
+ ```dart
100
+ // Wrap TextField in Expanded to constrain its width to the remaining Row space
101
+ Row(
102
+ children: [
103
+ const Icon(Icons.search),
104
+ Expanded(
105
+ child: TextField(),
106
+ ),
107
+ ],
108
+ )
109
+ ```
81
110
 
82
111
  ### Fixing RenderFlex Overflow
83
112
 
84
- **Before:** `Row(children: [Icon(Icons.info), Text('Very long text...')])`
113
+ **Input (Error State):**
114
+
115
+ ```dart
116
+ // Throws "A RenderFlex overflowed by X pixels on the right"
117
+ Row(
118
+ children: [
119
+ const Icon(Icons.info),
120
+ const Text('This is a very long text string that will definitely overflow the available screen width and cause a RenderFlex error.'),
121
+ ],
122
+ )
123
+ ```
124
+
125
+ **Output (Resolved State):**
85
126
 
86
- **After:** `Row(children: [Icon(Icons.info), Expanded(child: Text('Very long text...'))])`
127
+ ```dart
128
+ // Wrap the Text widget in Expanded to force it to wrap within the available constraints
129
+ Row(
130
+ children: [
131
+ const Icon(Icons.info),
132
+ Expanded(
133
+ child: const Text('This is a very long text string that will definitely overflow the available screen width and cause a RenderFlex error.'),
134
+ ),
135
+ ],
136
+ )
137
+ ```
87
138
 
88
139
  ## Flutter Ultra Integration
89
140