@bdayadev/flutter-ultra-mcp 1.12.0 → 1.14.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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +41 -13
- package/dart/ultra_flutter/pubspec.yaml +1 -1
- package/dart/ultra_flutter_devtools/pubspec.yaml +1 -1
- package/package.json +1 -1
- package/packages/flutter-ultra-native-desktop/package.json +2 -0
- package/packages/flutter-ultra-native-mobile/package.json +2 -0
- package/skills/add-integration-test/SKILL.md +72 -20
- package/skills/add-unit-test/SKILL.md +1 -0
- package/skills/add-widget-preview/SKILL.md +75 -26
- package/skills/add-widget-test/SKILL.md +51 -22
- package/skills/apply-architecture-best-practices/SKILL.md +55 -29
- package/skills/build-cli-app/SKILL.md +36 -9
- package/skills/build-responsive-layout/SKILL.md +65 -31
- package/skills/collect-coverage/SKILL.md +12 -1
- package/skills/debug/SKILL.md +19 -2
- package/skills/drive/SKILL.md +30 -15
- package/skills/fix-layout-issues/SKILL.md +71 -20
- package/skills/fix-runtime-errors/SKILL.md +79 -20
- package/skills/generate-test-mocks/SKILL.md +43 -13
- package/skills/implement-json-serialization/SKILL.md +82 -17
- package/skills/migrate-to-checks-package/SKILL.md +46 -14
- package/skills/record-demo/SKILL.md +20 -0
- package/skills/resolve-package-conflicts/SKILL.md +41 -12
- package/skills/run-static-analysis/SKILL.md +29 -16
- package/skills/setup/SKILL.md +1 -0
- package/skills/setup-declarative-routing/SKILL.md +166 -30
- package/skills/setup-localization/SKILL.md +90 -20
- package/skills/test/SKILL.md +2 -1
- package/skills/tour/SKILL.md +31 -22
- package/skills/use-http-package/SKILL.md +61 -23
- package/skills/use-pattern-matching/SKILL.md +63 -26
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: migrate-to-checks-package
|
|
3
3
|
description: Replace the usage of `expect` and similar functions from `package:matcher` to `package:checks` equivalents.
|
|
4
|
+
last_modified: Fri, 24 Apr 2026 15:15:22 GMT
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Migrating Dart Tests to Package Checks
|
|
@@ -9,11 +10,14 @@ description: Replace the usage of `expect` and similar functions from `package:m
|
|
|
9
10
|
|
|
10
11
|
- [Dependency Management](#dependency-management)
|
|
11
12
|
- [Syntax Migration Guidelines](#syntax-migration-guidelines)
|
|
13
|
+
- [Utilizing Dart MCP Tools](#utilizing-dart-mcp-tools)
|
|
12
14
|
- [Migration Workflow](#migration-workflow)
|
|
13
15
|
- [Examples](#examples)
|
|
14
16
|
|
|
15
17
|
## Dependency Management
|
|
16
18
|
|
|
19
|
+
Manage dependencies using the Dart Tooling MCP Server `pub` tool or standard CLI commands.
|
|
20
|
+
|
|
17
21
|
- Add `package:checks` as a `dev_dependency` using `dart pub add dev:checks`.
|
|
18
22
|
- Remove `package:matcher` if it is explicitly listed in the `pubspec.yaml` (note: it is often transitively included by `package:test`, which is fine).
|
|
19
23
|
- Import `package:checks/checks.dart` in all test files undergoing migration.
|
|
@@ -22,35 +26,47 @@ description: Replace the usage of `expect` and similar functions from `package:m
|
|
|
22
26
|
|
|
23
27
|
Transition test assertions from the `package:matcher` syntax to the literate API provided by `package:checks`.
|
|
24
28
|
|
|
25
|
-
- **Basic Equality:** Replace `expect(actual, equals(expected))` with `check(actual).equals(expected)`.
|
|
29
|
+
- **Basic Equality:** Replace `expect(actual, equals(expected))` or `expect(actual, expected)` with `check(actual).equals(expected)`.
|
|
26
30
|
- **Type Checking:** Replace `expect(actual, isA<Type>())` with `check(actual).isA<Type>()`.
|
|
27
31
|
- **Property Extraction:** Replace `expect(actual.property, expected)` with `check(actual).has((a) => a.property, 'property name').equals(expected)`.
|
|
28
32
|
- **Cascades for Multiple Checks:** Use Dart's cascade operator (`..`) to chain multiple expectations on a single subject.
|
|
29
33
|
- **Asynchronous Expectations:**
|
|
30
34
|
- If checking a `Future`, `await` the `check` call: `await check(someFuture).completes((r) => r.equals(expected));`.
|
|
31
|
-
- If checking a `Stream`, wrap it in a `StreamQueue` for multiple checks.
|
|
35
|
+
- If checking a `Stream`, wrap it in a `StreamQueue` for multiple checks, or use `.withQueue` for single/broadcast checks.
|
|
36
|
+
|
|
37
|
+
## Utilizing Dart MCP Tools
|
|
38
|
+
|
|
39
|
+
Leverage the Dart MCP Server tools to automate and validate the migration process.
|
|
40
|
+
|
|
41
|
+
- Use `pub` to run `dart pub get` or `dart pub add`.
|
|
42
|
+
- Use `analyze_files` to run static analysis on the project or specific paths.
|
|
43
|
+
- Use `run_tests` to execute Dart or Flutter tests with an agent-centric UX. ALWAYS use this instead of shell commands like `dart test`.
|
|
44
|
+
- Use `dart_fix` to apply automated fixes if applicable.
|
|
32
45
|
|
|
33
46
|
## Migration Workflow
|
|
34
47
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
- [ ]
|
|
38
|
-
- [ ]
|
|
39
|
-
- [ ]
|
|
40
|
-
- [ ]
|
|
48
|
+
Copy and use the following checklist to track progress when migrating a test suite:
|
|
49
|
+
|
|
50
|
+
- [ ] **Task Progress**
|
|
51
|
+
- [ ] Add `package:checks` as a dev dependency.
|
|
52
|
+
- [ ] Identify all test files using `package:matcher` (`expect` calls).
|
|
53
|
+
- [ ] Import `package:checks/checks.dart` in target test files.
|
|
54
|
+
- [ ] Rewrite all `expect(...)` statements to `check(...)` statements.
|
|
55
|
+
- [ ] Run static analyzer (`analyze_files`).
|
|
56
|
+
- [ ] Run tests (`run_tests`).
|
|
41
57
|
|
|
42
58
|
### Feedback Loop: Static Analysis
|
|
43
59
|
|
|
44
|
-
1. Run the
|
|
45
|
-
2. Review any static analysis warnings or errors.
|
|
60
|
+
1. Run the `analyze_files` tool on the modified test directories.
|
|
61
|
+
2. Review any static analysis warnings or errors (e.g., missing imports, incorrect generic types on `isA`, unawaited futures).
|
|
46
62
|
3. Fix the warnings.
|
|
47
|
-
4. Repeat until zero issues.
|
|
63
|
+
4. Repeat until the analyzer returns zero issues.
|
|
48
64
|
|
|
49
65
|
### Feedback Loop: Test Validation
|
|
50
66
|
|
|
51
|
-
1. Run the
|
|
52
|
-
2. If tests fail, review the failure output. `package:checks` provides detailed context.
|
|
53
|
-
3. Adjust the `check()` expectations or the underlying code.
|
|
67
|
+
1. Run the `run_tests` tool.
|
|
68
|
+
2. If tests fail, review the failure output. `package:checks` provides detailed context (e.g., `Which: has length of <2>`).
|
|
69
|
+
3. Adjust the `check()` expectations or the underlying code to resolve the failure.
|
|
54
70
|
4. Repeat until all tests pass.
|
|
55
71
|
|
|
56
72
|
## Examples
|
|
@@ -110,6 +126,22 @@ await check(Future.value(10)).completes((it) => it.equals(10));
|
|
|
110
126
|
await check(Future.error('oh no')).throws<String>().equals('oh no');
|
|
111
127
|
```
|
|
112
128
|
|
|
129
|
+
### Asynchronous Streams
|
|
130
|
+
|
|
131
|
+
**Input (`matcher`):**
|
|
132
|
+
|
|
133
|
+
```dart
|
|
134
|
+
var stdout = StreamQueue(Stream.fromIterable(['Ready', 'Go']));
|
|
135
|
+
await expectLater(stdout, emitsThrough('Ready'));
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Output (`checks`):**
|
|
139
|
+
|
|
140
|
+
```dart
|
|
141
|
+
var stdout = StreamQueue(Stream.fromIterable(['Ready', 'Go']));
|
|
142
|
+
await check(stdout).emitsThrough((it) => it.equals('Ready'));
|
|
143
|
+
```
|
|
144
|
+
|
|
113
145
|
## Flutter Ultra Integration
|
|
114
146
|
|
|
115
147
|
Validate the migration with static analysis and tests:
|
|
@@ -68,6 +68,26 @@ For responsive demos, resize the viewport between key interactions:
|
|
|
68
68
|
|
|
69
69
|
Take screenshots at key moments for verification alongside the recording.
|
|
70
70
|
|
|
71
|
+
### 3b. Web performance trace (optional, alongside video)
|
|
72
|
+
|
|
73
|
+
For web demos where you also want a Chrome DevTools trace alongside the video:
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
mcp__plugin_flutter_flutter-ultra-browser__start_tracing
|
|
77
|
+
contextId: <id>
|
|
78
|
+
categories: ["blink", "v8", "disabled-by-default-devtools.timeline"]
|
|
79
|
+
outputPath: /tmp/flutter-demo-trace.json
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Drive the UI flow, then stop:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
mcp__plugin_flutter_flutter-ultra-browser__stop_tracing
|
|
86
|
+
contextId: <id>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Returns the trace JSON path. Open in `chrome://tracing` or Perfetto for frame-level analysis alongside the recorded video.
|
|
90
|
+
|
|
71
91
|
### 4. Stop recording
|
|
72
92
|
|
|
73
93
|
#### Web
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: resolve-package-conflicts
|
|
3
3
|
description: Workflow for fixing package version conflicts. Use this when `pub get` fails due to incompatible package versions.
|
|
4
|
+
last_modified: Fri, 24 Apr 2026 15:11:14 GMT
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Managing Dart Dependencies
|
|
@@ -16,46 +17,54 @@ description: Workflow for fixing package version conflicts. Use this when `pub g
|
|
|
16
17
|
|
|
17
18
|
## Core Concepts
|
|
18
19
|
|
|
19
|
-
Dart enforces a strict single-version rule for dependencies: a project and all its transitive dependencies must resolve to a single, shared version of any given package.
|
|
20
|
+
Dart enforces a strict single-version rule for dependencies: a project and all its transitive dependencies must resolve to a single, shared version of any given package. This prevents runtime type mismatches but introduces the risk of "version lock."
|
|
21
|
+
|
|
22
|
+
To mitigate version lock, Dart relies on version constraints rather than pinned versions in the `pubspec.yaml`. The `pubspec.lock` file maintains the exact resolved versions for reproducible builds.
|
|
20
23
|
|
|
21
24
|
Understand the output columns of `dart pub outdated`:
|
|
22
25
|
|
|
23
26
|
- **Current:** The version currently recorded in `pubspec.lock`.
|
|
24
27
|
- **Upgradable:** The latest version allowed by the constraints in `pubspec.yaml`. `dart pub upgrade` resolves to this.
|
|
25
|
-
- **Resolvable:** The absolute latest version that can be resolved when factoring in all other dependencies.
|
|
28
|
+
- **Resolvable:** The absolute latest version that can be resolved when factoring in all other dependencies in the project.
|
|
26
29
|
- **Latest:** The latest published version of the package (excluding prereleases).
|
|
27
30
|
|
|
28
31
|
## Version Constraints
|
|
29
32
|
|
|
30
|
-
- **Use Caret Syntax:** Always use caret syntax (e.g., `^1.2.3`) for dependencies.
|
|
31
|
-
- **Tighten Dev Dependencies:** Set the lower bound of `dev_dependencies` to the exact version currently used.
|
|
32
|
-
- **Enforce Lockfiles in CI:** Use `dart pub get --enforce-lockfile` in CI/CD pipelines.
|
|
33
|
+
- **Use Caret Syntax:** Always use caret syntax (e.g., `^1.2.3`) for dependencies in `pubspec.yaml`. This allows `pub` to select newer, non-breaking versions (up to, but not including, the next major version) during resolution.
|
|
34
|
+
- **Tighten Dev Dependencies:** Set the lower bound of `dev_dependencies` to the exact version currently used. This reduces resolution complexity and prevents older, incompatible dev tools from being selected.
|
|
35
|
+
- **Enforce Lockfiles in CI:** Use `dart pub get --enforce-lockfile` in CI/CD pipelines to ensure the exact versions tested locally are used in production.
|
|
33
36
|
|
|
34
37
|
## Workflow: Auditing Dependencies
|
|
35
38
|
|
|
39
|
+
Run this workflow periodically to identify stale packages that may impact stability or performance.
|
|
40
|
+
|
|
36
41
|
**Task Progress:**
|
|
37
42
|
|
|
38
43
|
- [ ] Run `dart pub outdated`.
|
|
39
|
-
- [ ] Review the **Upgradable** column.
|
|
40
|
-
- [ ] Review the **Resolvable** column.
|
|
44
|
+
- [ ] Review the **Upgradable** column to identify packages that can be updated without modifying `pubspec.yaml`.
|
|
45
|
+
- [ ] Review the **Resolvable** column to identify packages that require constraint modifications in `pubspec.yaml` to update.
|
|
41
46
|
- [ ] Identify any packages marked as retracted or discontinued.
|
|
42
47
|
|
|
43
48
|
## Workflow: Upgrading Dependencies
|
|
44
49
|
|
|
50
|
+
Use conditional logic based on the audit results to upgrade dependencies.
|
|
51
|
+
|
|
45
52
|
**Task Progress:**
|
|
46
53
|
|
|
47
54
|
- [ ] **If updating to "Upgradable" versions:**
|
|
48
55
|
- [ ] Run `dart pub upgrade`.
|
|
49
|
-
- [ ] Run `dart pub upgrade --tighten` to update lower bounds.
|
|
56
|
+
- [ ] Run `dart pub upgrade --tighten` to automatically update the lower bounds in `pubspec.yaml` to match the newly resolved versions.
|
|
50
57
|
- [ ] **If updating to "Resolvable" versions (Major updates):**
|
|
51
|
-
- [ ] Manually edit `pubspec.yaml` to bump the version constraint.
|
|
52
|
-
- [ ] Run `dart pub upgrade` to resolve the new constraints.
|
|
58
|
+
- [ ] Manually edit `pubspec.yaml` to bump the version constraint to match the "Resolvable" column (e.g., change `^0.11.0` to `^0.12.1`).
|
|
59
|
+
- [ ] Run `dart pub upgrade` to resolve the new constraints and update `pubspec.lock`.
|
|
53
60
|
- [ ] **Feedback Loop:**
|
|
54
61
|
- [ ] Run `dart analyze` -> review errors -> fix breaking API changes.
|
|
55
62
|
- [ ] Run `dart test` -> review failures -> fix regressions.
|
|
56
63
|
|
|
57
64
|
## Workflow: Resolving Version Conflicts
|
|
58
65
|
|
|
66
|
+
When `pub` cannot find a set of concrete versions that satisfy all constraints, or when dealing with a retracted package version, manipulate the lockfile surgically.
|
|
67
|
+
|
|
59
68
|
**NEVER** delete the entire `pubspec.lock` file and run `dart pub get`. This causes uncontrolled upgrades across the entire dependency graph.
|
|
60
69
|
|
|
61
70
|
**Task Progress:**
|
|
@@ -63,7 +72,7 @@ Understand the output columns of `dart pub outdated`:
|
|
|
63
72
|
- [ ] Open `pubspec.lock`.
|
|
64
73
|
- [ ] Locate the specific YAML block for the conflicting or retracted package.
|
|
65
74
|
- [ ] Delete ONLY that package's entry from the lockfile.
|
|
66
|
-
- [ ] Run `dart pub get` to fetch the newest compatible version.
|
|
75
|
+
- [ ] Run `dart pub get` to fetch the newest compatible, non-retracted version for that specific package.
|
|
67
76
|
- [ ] **Feedback Loop:**
|
|
68
77
|
- [ ] Run `dart pub deps` -> verify the dependency graph resolves correctly.
|
|
69
78
|
- [ ] If resolution fails, identify the transitive dependency causing the lock, update its constraint in `pubspec.yaml`, and retry.
|
|
@@ -72,6 +81,8 @@ Understand the output columns of `dart pub outdated`:
|
|
|
72
81
|
|
|
73
82
|
### Tightening Constraints
|
|
74
83
|
|
|
84
|
+
When `dart pub outdated` shows a package is resolvable to a higher minor/patch version, use the `--tighten` flag to update the `pubspec.yaml` automatically.
|
|
85
|
+
|
|
75
86
|
**Input (`pubspec.yaml`):**
|
|
76
87
|
|
|
77
88
|
```yaml
|
|
@@ -94,7 +105,25 @@ dependencies:
|
|
|
94
105
|
|
|
95
106
|
### Surgical Lockfile Removal
|
|
96
107
|
|
|
97
|
-
If `package_a` is retracted or locked in a conflict, remove only its block from `pubspec.lock`.
|
|
108
|
+
If `package_a` is retracted or locked in a conflict, remove only its block from `pubspec.lock`.
|
|
109
|
+
|
|
110
|
+
**Before (`pubspec.lock`):**
|
|
111
|
+
|
|
112
|
+
```yaml
|
|
113
|
+
packages:
|
|
114
|
+
package_a:
|
|
115
|
+
dependency: 'direct main'
|
|
116
|
+
description:
|
|
117
|
+
name: package_a
|
|
118
|
+
url: 'https://pub.dev'
|
|
119
|
+
source: hosted
|
|
120
|
+
version: '1.0.0' # Retracted version
|
|
121
|
+
package_b:
|
|
122
|
+
dependency: 'direct main'
|
|
123
|
+
# ...
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Action:** Delete the `package_a` block entirely. Leave `package_b` untouched. Run `dart pub get`.
|
|
98
127
|
|
|
99
128
|
## Flutter Ultra Integration
|
|
100
129
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: run-static-analysis
|
|
3
3
|
description: Execute `dart analyze` to identify warnings and errors, and use `dart fix --apply` to automatically resolve mechanical lint issues. Use during development to ensure code quality and before committing changes.
|
|
4
|
+
last_modified: Fri, 24 Apr 2026 15:09:34 GMT
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Analyzing and Fixing Dart Code
|
|
@@ -15,38 +16,48 @@ description: Execute `dart analyze` to identify warnings and errors, and use `da
|
|
|
15
16
|
|
|
16
17
|
## Analysis Configuration
|
|
17
18
|
|
|
18
|
-
Configure the Dart analyzer using the `analysis_options.yaml` file at the package root.
|
|
19
|
+
Configure the Dart analyzer using the `analysis_options.yaml` file located at the package root.
|
|
19
20
|
|
|
20
|
-
- **Base Configuration:**
|
|
21
|
-
- **Strict Type Checks:** Enable `strict-casts: true`, `strict-inference: true`, and `strict-raw-types: true
|
|
22
|
-
- **Linter Rules:**
|
|
23
|
-
- **Formatter Configuration:** Configure `dart format` behavior under the `formatter:` node. Set `page_width` and `trailing_commas
|
|
21
|
+
- **Base Configuration:** Always include a standard rule set (e.g., `package:lints/recommended.yaml` or `package:flutter_lints/flutter.yaml`) using the `include:` directive.
|
|
22
|
+
- **Strict Type Checks:** Enable strict type checks under the `analyzer: language:` node to prevent implicit downcasts and dynamic inferences. Set `strict-casts: true`, `strict-inference: true`, and `strict-raw-types: true`.
|
|
23
|
+
- **Linter Rules:** Explicitly enable or disable specific rules under the `linter: rules:` node. Use a key-value map (`rule_name: true/false`) when overriding included rules, or a list (`- rule_name`) when defining a fresh set. Do not mix list and map syntax in the same `rules` block.
|
|
24
|
+
- **Formatter Configuration:** Configure `dart format` behavior under the `formatter:` node. Set `page_width` (default 80) and `trailing_commas` (`automate` or `preserve`).
|
|
25
|
+
- **Analyzer Plugins:** Enable custom diagnostics by adding plugins under the `analyzer: plugins:` node. Ensure the plugin package is added as a `dev_dependency` in `pubspec.yaml`.
|
|
24
26
|
|
|
25
27
|
## Diagnostic Suppression
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
- **
|
|
29
|
+
When a diagnostic (lint or warning) yields a false positive or applies to generated code, suppress it explicitly.
|
|
30
|
+
|
|
31
|
+
- **File-level Exclusion:** Use the `analyzer: exclude:` node in `analysis_options.yaml` to exclude entire files or directories (e.g., `**/*.g.dart`) using glob patterns.
|
|
32
|
+
- **File-level Suppression:** Add `// ignore_for_file: <diagnostic_code>` at the top of a Dart file to suppress specific diagnostics for the entire file. Use `// ignore_for_file: type=lint` to suppress all linter rules.
|
|
33
|
+
- **Line-level Suppression:** Add `// ignore: <diagnostic_code>` on the line directly above the offending code, or appended to the end of the offending line.
|
|
34
|
+
- **Pubspec Suppression:** Add `# ignore: <diagnostic_code>` above the offending line in `pubspec.yaml` files (e.g., `# ignore: sort_pub_dependencies`).
|
|
35
|
+
- **Plugin Diagnostics:** Prefix the diagnostic code with the plugin name when suppressing plugin-specific issues (e.g., `// ignore: some_plugin/some_code`).
|
|
30
36
|
|
|
31
37
|
## Workflow: Executing Static Analysis
|
|
32
38
|
|
|
39
|
+
Use this workflow to identify type-related bugs, style violations, and potential runtime errors.
|
|
40
|
+
|
|
33
41
|
**Task Progress:**
|
|
34
42
|
|
|
35
43
|
- [ ] 1. Verify `analysis_options.yaml` exists at the project root.
|
|
36
|
-
- [ ] 2. Run the analyzer
|
|
44
|
+
- [ ] 2. Run the analyzer using the `analyze_files` MCP tool (if available) or the CLI command `dart analyze <target_directory>`.
|
|
37
45
|
- [ ] 3. Review the diagnostic output.
|
|
38
|
-
- [ ] 4. If info-level issues must be treated as failures, append `--fatal-infos
|
|
39
|
-
- [ ] 5. Resolve reported errors manually or proceed to Automated Fixes.
|
|
46
|
+
- [ ] 4. If info-level issues must be treated as failures, append the `--fatal-infos` flag.
|
|
47
|
+
- [ ] 5. Resolve reported errors manually or proceed to the Automated Fixes workflow.
|
|
40
48
|
|
|
41
49
|
## Workflow: Applying Automated Fixes
|
|
42
50
|
|
|
51
|
+
Use this workflow to resolve outdated API usages, apply quick fixes, and migrate code (e.g., Dart 3 migrations).
|
|
52
|
+
|
|
43
53
|
**Task Progress:**
|
|
44
54
|
|
|
45
|
-
- [ ] 1.
|
|
46
|
-
- [ ] 2. Review the proposed fixes.
|
|
47
|
-
- [ ] 3.
|
|
48
|
-
- [ ] 4.
|
|
49
|
-
- [ ] 5.
|
|
55
|
+
- [ ] 1. Execute a dry run to preview proposed changes using the `dart_fix` MCP tool or CLI command `dart fix --dry-run`.
|
|
56
|
+
- [ ] 2. Review the proposed fixes to ensure they align with the intended architecture.
|
|
57
|
+
- [ ] 3. If additional fixes are required, verify that the corresponding linter rules are enabled in `analysis_options.yaml`.
|
|
58
|
+
- [ ] 4. Apply the fixes using the `dart_fix` MCP tool or CLI command `dart fix --apply`.
|
|
59
|
+
- [ ] 5. Format the modified code using the `dart_format` MCP tool or CLI command `dart format .`.
|
|
60
|
+
- [ ] 6. Run the static analysis workflow to verify all diagnostics are resolved.
|
|
50
61
|
|
|
51
62
|
## Examples
|
|
52
63
|
|
|
@@ -82,9 +93,11 @@ formatter:
|
|
|
82
93
|
### Inline Diagnostic Suppression
|
|
83
94
|
|
|
84
95
|
```dart
|
|
96
|
+
// Suppress for the entire file
|
|
85
97
|
// ignore_for_file: unused_local_variable, dead_code
|
|
86
98
|
|
|
87
99
|
void processData() {
|
|
100
|
+
// Suppress for a specific line
|
|
88
101
|
// ignore: invalid_assignment
|
|
89
102
|
int x = '';
|
|
90
103
|
|
package/skills/setup/SKILL.md
CHANGED
|
@@ -12,6 +12,7 @@ Expected end state: `UltraFlutterBinding` initialized in the app entry point, `u
|
|
|
12
12
|
### 1. Verify the environment
|
|
13
13
|
|
|
14
14
|
- `mcp__plugin_flutter_flutter-ultra-build__flutter_doctor` — stop if Flutter SDK, devices, or Dart show `[x]`.
|
|
15
|
+
- `mcp__plugin_flutter_flutter-ultra-build__list_projects` — check if the target project already exists. If not, use `mcp__plugin_flutter_flutter-ultra-build__create_project` to scaffold it (an alternative to running `flutter create` manually), then proceed with setup steps below.
|
|
15
16
|
- `mcp__plugin_flutter_flutter-ultra-build__project_info` — note entry points, `hasSentry`, `hasPatrol`, `hasUltraBinding`.
|
|
16
17
|
- `mcp__plugin_flutter_flutter-ultra-runtime__list_devices` — verify at least one target device is available.
|
|
17
18
|
- `mcp__plugin_flutter_flutter-ultra-build__list_dart_defines` — discover required dart-defines for launch.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: setup-declarative-routing
|
|
3
3
|
description: Configure `MaterialApp.router` using a package like `go_router` for advanced URL-based navigation. Use when developing web applications or mobile apps that require specific deep linking and browser history support.
|
|
4
|
+
last_modified: Tue, 21 Apr 2026 21:08:03 GMT
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Implementing Routing and Deep Linking
|
|
@@ -15,29 +16,46 @@ description: Configure `MaterialApp.router` using a package like `go_router` for
|
|
|
15
16
|
|
|
16
17
|
## Core Concepts
|
|
17
18
|
|
|
18
|
-
Use the `go_router` package for declarative routing in Flutter.
|
|
19
|
+
Use the `go_router` package for declarative routing in Flutter. It provides a robust API for complex routing scenarios, deep linking, and nested navigation.
|
|
19
20
|
|
|
20
|
-
- **GoRouter**:
|
|
21
|
-
- **GoRoute**:
|
|
22
|
-
- **ShellRoute / StatefulShellRoute**: Wraps child routes in a persistent UI shell (e.g., `BottomNavigationBar`). `StatefulShellRoute` maintains state of parallel branches.
|
|
23
|
-
- **Path URL Strategy**: Removes the default `#` from web URLs.
|
|
21
|
+
- **GoRouter**: The central configuration object defining the application's route tree.
|
|
22
|
+
- **GoRoute**: A standard route mapping a URL path to a Flutter screen.
|
|
23
|
+
- **ShellRoute / StatefulShellRoute**: Wraps child routes in a persistent UI shell (e.g., a `BottomNavigationBar`). `StatefulShellRoute` maintains the state of parallel navigation branches.
|
|
24
|
+
- **Path URL Strategy**: Removes the default `#` fragment from web URLs, essential for clean deep linking across platforms.
|
|
24
25
|
|
|
25
26
|
## Workflow: Initializing the Application and Router
|
|
26
27
|
|
|
28
|
+
Follow this workflow to bootstrap a new Flutter application with `go_router` and configure the root routing mechanism.
|
|
29
|
+
|
|
27
30
|
### Task Progress
|
|
28
31
|
|
|
29
32
|
- [ ] Create the Flutter application.
|
|
30
|
-
- [ ] Add `go_router
|
|
31
|
-
- [ ] Configure URL strategy
|
|
33
|
+
- [ ] Add the `go_router` dependency.
|
|
34
|
+
- [ ] Configure the URL strategy for web/deep linking.
|
|
32
35
|
- [ ] Implement the `GoRouter` configuration.
|
|
33
36
|
- [ ] Bind the router to `MaterialApp.router`.
|
|
34
37
|
|
|
38
|
+
### 1. Scaffold the Application
|
|
39
|
+
|
|
40
|
+
Run the following commands to create the app and add the required routing package:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
flutter create <app-name>
|
|
44
|
+
cd <app-name>
|
|
45
|
+
flutter pub add go_router
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 2. Configure the Router
|
|
49
|
+
|
|
50
|
+
Define a top-level `GoRouter` instance. Handle authentication or state-based routing using the `redirect` parameter.
|
|
51
|
+
|
|
35
52
|
```dart
|
|
36
53
|
import 'package:flutter/material.dart';
|
|
37
54
|
import 'package:go_router/go_router.dart';
|
|
38
55
|
import 'package:flutter_web_plugins/url_strategy.dart';
|
|
39
56
|
|
|
40
57
|
void main() {
|
|
58
|
+
// Use path URL strategy to remove the '#' from web URLs
|
|
41
59
|
usePathUrlStrategy();
|
|
42
60
|
runApp(const MyApp());
|
|
43
61
|
}
|
|
@@ -61,25 +79,115 @@ final GoRouter _router = GoRouter(
|
|
|
61
79
|
|
|
62
80
|
class MyApp extends StatelessWidget {
|
|
63
81
|
const MyApp({super.key});
|
|
82
|
+
|
|
64
83
|
@override
|
|
65
84
|
Widget build(BuildContext context) {
|
|
66
|
-
return MaterialApp.router(
|
|
85
|
+
return MaterialApp.router(
|
|
86
|
+
routerConfig: _router,
|
|
87
|
+
title: 'Routing App',
|
|
88
|
+
);
|
|
67
89
|
}
|
|
68
90
|
}
|
|
69
91
|
```
|
|
70
92
|
|
|
71
93
|
## Workflow: Configuring Platform Deep Linking
|
|
72
94
|
|
|
95
|
+
Configure the native platforms to intercept specific URLs and route them into the Flutter application.
|
|
96
|
+
|
|
73
97
|
### Task Progress
|
|
74
98
|
|
|
75
99
|
- [ ] Determine target platforms (iOS, Android, or both).
|
|
76
|
-
- [ ]
|
|
77
|
-
- [ ]
|
|
78
|
-
- [ ]
|
|
100
|
+
- [ ] Apply conditional configuration for Android (Manifest + Asset Links).
|
|
101
|
+
- [ ] Apply conditional configuration for iOS (Plist + Entitlements + AASA).
|
|
102
|
+
- [ ] Run validator -> review errors -> fix.
|
|
103
|
+
|
|
104
|
+
### If configuring for Android:
|
|
105
|
+
|
|
106
|
+
1. **Modify `AndroidManifest.xml`**: Add the intent filter inside the `<activity>` tag for `.MainActivity`.
|
|
107
|
+
|
|
108
|
+
```xml
|
|
109
|
+
<intent-filter android:autoVerify="true">
|
|
110
|
+
<action android:name="android.intent.action.VIEW" />
|
|
111
|
+
<category android:name="android.intent.category.DEFAULT" />
|
|
112
|
+
<category android:name="android.intent.category.BROWSABLE" />
|
|
113
|
+
<data android:scheme="http" android:host="yourdomain.com" />
|
|
114
|
+
<data android:scheme="https" />
|
|
115
|
+
</intent-filter>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
2. **Host `assetlinks.json`**: Serve the following JSON at `https://yourdomain.com/.well-known/assetlinks.json`.
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
[
|
|
122
|
+
{
|
|
123
|
+
"relation": ["delegate_permission/common.handle_all_urls"],
|
|
124
|
+
"target": {
|
|
125
|
+
"namespace": "android_app",
|
|
126
|
+
"package_name": "com.yourcompany.yourapp",
|
|
127
|
+
"sha256_cert_fingerprints": ["YOUR_SHA256_FINGERPRINT"]
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### If configuring for iOS:
|
|
134
|
+
|
|
135
|
+
1. **Modify `Info.plist`**: Opt-in to Flutter's default deep link handler.
|
|
136
|
+
_Note: If using a third-party deep linking plugin (e.g., `app_links`), set this to `NO` to prevent conflicts._
|
|
137
|
+
|
|
138
|
+
```xml
|
|
139
|
+
<key>FlutterDeepLinkingEnabled</key>
|
|
140
|
+
<true/>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
2. **Modify `Runner.entitlements`**: Add the associated domain.
|
|
144
|
+
|
|
145
|
+
```xml
|
|
146
|
+
<key>com.apple.developer.associated-domains</key>
|
|
147
|
+
<array>
|
|
148
|
+
<string>applinks:yourdomain.com</string>
|
|
149
|
+
</array>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
3. **Host `apple-app-site-association`**: Serve the following JSON (without a `.json` extension) at `https://yourdomain.com/.well-known/apple-app-site-association`.
|
|
153
|
+
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
"applinks": {
|
|
157
|
+
"apps": [],
|
|
158
|
+
"details": [
|
|
159
|
+
{
|
|
160
|
+
"appIDs": ["TEAM_ID.com.yourcompany.yourapp"],
|
|
161
|
+
"paths": ["*"],
|
|
162
|
+
"components": [{ "/": "/*" }]
|
|
163
|
+
}
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Validation Loop
|
|
170
|
+
|
|
171
|
+
Run validator -> review errors -> fix.
|
|
172
|
+
|
|
173
|
+
- **Android**: Test using ADB.
|
|
174
|
+
```bash
|
|
175
|
+
adb shell 'am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "https://yourdomain.com/details/123"' com.yourcompany.yourapp
|
|
176
|
+
```
|
|
177
|
+
- **iOS**: Test using `xcrun` on a booted simulator.
|
|
178
|
+
```bash
|
|
179
|
+
xcrun simctl openurl booted https://yourdomain.com/details/123
|
|
180
|
+
```
|
|
79
181
|
|
|
80
182
|
## Workflow: Implementing Nested Navigation
|
|
81
183
|
|
|
82
|
-
Use `StatefulShellRoute
|
|
184
|
+
Use `StatefulShellRoute` to implement persistent UI shells (like a bottom navigation bar) that maintain the state of their child routes.
|
|
185
|
+
|
|
186
|
+
### Task Progress
|
|
187
|
+
|
|
188
|
+
- [ ] Define `StatefulShellRoute.indexedStack` in the `GoRouter` configuration.
|
|
189
|
+
- [ ] Create `StatefulShellBranch` instances for each navigation tab.
|
|
190
|
+
- [ ] Implement the shell widget using `StatefulNavigationShell`.
|
|
83
191
|
|
|
84
192
|
```dart
|
|
85
193
|
final GoRouter _router = GoRouter(
|
|
@@ -90,12 +198,22 @@ final GoRouter _router = GoRouter(
|
|
|
90
198
|
return ScaffoldWithNavBar(navigationShell: navigationShell);
|
|
91
199
|
},
|
|
92
200
|
branches: [
|
|
93
|
-
StatefulShellBranch(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
201
|
+
StatefulShellBranch(
|
|
202
|
+
routes: [
|
|
203
|
+
GoRoute(
|
|
204
|
+
path: '/home',
|
|
205
|
+
builder: (context, state) => const HomeScreen(),
|
|
206
|
+
),
|
|
207
|
+
],
|
|
208
|
+
),
|
|
209
|
+
StatefulShellBranch(
|
|
210
|
+
routes: [
|
|
211
|
+
GoRoute(
|
|
212
|
+
path: '/settings',
|
|
213
|
+
builder: (context, state) => const SettingsScreen(),
|
|
214
|
+
),
|
|
215
|
+
],
|
|
216
|
+
),
|
|
99
217
|
],
|
|
100
218
|
),
|
|
101
219
|
],
|
|
@@ -104,25 +222,25 @@ final GoRouter _router = GoRouter(
|
|
|
104
222
|
|
|
105
223
|
## Examples
|
|
106
224
|
|
|
107
|
-
###
|
|
108
|
-
|
|
109
|
-
```dart
|
|
110
|
-
context.go('/details/123'); // Replace current stack
|
|
111
|
-
context.push('/details/123'); // Push onto stack
|
|
112
|
-
context.goNamed('details', pathParameters: {'id': '123'});
|
|
113
|
-
context.pop();
|
|
114
|
-
```
|
|
225
|
+
### High-Fidelity Shell Widget Implementation
|
|
115
226
|
|
|
116
|
-
|
|
227
|
+
Implement the UI shell that consumes the `StatefulNavigationShell` to handle branch switching.
|
|
117
228
|
|
|
118
229
|
```dart
|
|
119
230
|
class ScaffoldWithNavBar extends StatelessWidget {
|
|
120
|
-
const ScaffoldWithNavBar({
|
|
231
|
+
const ScaffoldWithNavBar({
|
|
232
|
+
required this.navigationShell,
|
|
233
|
+
super.key,
|
|
234
|
+
});
|
|
235
|
+
|
|
121
236
|
final StatefulNavigationShell navigationShell;
|
|
122
237
|
|
|
123
238
|
void _goBranch(int index) {
|
|
124
|
-
navigationShell.goBranch(
|
|
125
|
-
|
|
239
|
+
navigationShell.goBranch(
|
|
240
|
+
index,
|
|
241
|
+
// Support navigating to the initial location when tapping the active tab.
|
|
242
|
+
initialLocation: index == navigationShell.currentIndex,
|
|
243
|
+
);
|
|
126
244
|
}
|
|
127
245
|
|
|
128
246
|
@override
|
|
@@ -142,6 +260,24 @@ class ScaffoldWithNavBar extends StatelessWidget {
|
|
|
142
260
|
}
|
|
143
261
|
```
|
|
144
262
|
|
|
263
|
+
### Programmatic Navigation
|
|
264
|
+
|
|
265
|
+
Use the `context.go()` and `context.push()` extension methods provided by `go_router`.
|
|
266
|
+
|
|
267
|
+
```dart
|
|
268
|
+
// Replaces the current route stack with the target route (Declarative)
|
|
269
|
+
context.go('/details/123');
|
|
270
|
+
|
|
271
|
+
// Pushes the target route onto the existing stack (Imperative)
|
|
272
|
+
context.push('/details/123');
|
|
273
|
+
|
|
274
|
+
// Navigates using a named route and path parameters
|
|
275
|
+
context.goNamed('details', pathParameters: {'id': '123'});
|
|
276
|
+
|
|
277
|
+
// Pops the current route
|
|
278
|
+
context.pop();
|
|
279
|
+
```
|
|
280
|
+
|
|
145
281
|
## Flutter Ultra Integration
|
|
146
282
|
|
|
147
283
|
After configuring routes, test navigation in the running app:
|