reis-mobile 0.3.5

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.
Files changed (105) hide show
  1. package/.claude-plugin/marketplace.json +24 -0
  2. package/.claude-plugin/plugin.json +12 -0
  3. package/CHANGELOG.md +103 -0
  4. package/LICENSE +21 -0
  5. package/README.md +631 -0
  6. package/THIRD_PARTY_NOTICES.md +105 -0
  7. package/agents/flutter-architect.md +92 -0
  8. package/agents/flutter-performance-engineer.md +103 -0
  9. package/agents/flutter-test-engineer.md +100 -0
  10. package/agents/lead-mobile.md +107 -0
  11. package/agents/mobile-code-reviewer.md +66 -0
  12. package/agents/mobile-staff-engineer.md +85 -0
  13. package/agents/plugin-native-expert.md +97 -0
  14. package/bin/reis-mobile.mjs +256 -0
  15. package/commands/debate.md +135 -0
  16. package/commands/doctor.md +23 -0
  17. package/commands/reis-mobile.md +50 -0
  18. package/commands/review.md +53 -0
  19. package/core/config/language.mjs +83 -0
  20. package/core/context/context-engine.mjs +113 -0
  21. package/core/detection/project-probe.mjs +104 -0
  22. package/core/detection/stack-detector.mjs +204 -0
  23. package/core/diagnostics/doctor.mjs +181 -0
  24. package/core/install/claude-plugin.mjs +76 -0
  25. package/core/paths.mjs +4 -0
  26. package/core/registry/frontmatter.mjs +81 -0
  27. package/core/registry/registry.mjs +140 -0
  28. package/core/router/intent-detector.mjs +75 -0
  29. package/core/router/intents.mjs +91 -0
  30. package/core/router/router.mjs +83 -0
  31. package/core/security/redact.mjs +24 -0
  32. package/package.json +35 -0
  33. package/skills/architecture-feature-first/SKILL.md +116 -0
  34. package/skills/bloc/SKILL.md +354 -0
  35. package/skills/code-review/SKILL.md +89 -0
  36. package/skills/dart-3-updates/SKILL.md +223 -0
  37. package/skills/dart-add-unit-test/SKILL.md +126 -0
  38. package/skills/dart-collect-coverage/SKILL.md +145 -0
  39. package/skills/dart-fix-runtime-errors/SKILL.md +170 -0
  40. package/skills/dart-generate-test-mocks/SKILL.md +159 -0
  41. package/skills/dart-migrate-to-checks-package/SKILL.md +532 -0
  42. package/skills/dart-resolve-package-conflicts/SKILL.md +120 -0
  43. package/skills/dart-run-static-analysis/SKILL.md +108 -0
  44. package/skills/dart-use-pattern-matching/SKILL.md +240 -0
  45. package/skills/dart-use-pattern-matching/examples/json_patterns.dart +85 -0
  46. package/skills/detect-mobile-stack/SKILL.md +33 -0
  47. package/skills/effective-dart/SKILL.md +187 -0
  48. package/skills/firebase-ai/SKILL.md +93 -0
  49. package/skills/firebase-analytics/SKILL.md +129 -0
  50. package/skills/firebase-app-check/SKILL.md +124 -0
  51. package/skills/firebase-auth/SKILL.md +224 -0
  52. package/skills/firebase-cloud-firestore/SKILL.md +165 -0
  53. package/skills/firebase-cloud-functions/SKILL.md +148 -0
  54. package/skills/firebase-crashlytics/SKILL.md +182 -0
  55. package/skills/firebase-data-connect/SKILL.md +80 -0
  56. package/skills/firebase-database/SKILL.md +224 -0
  57. package/skills/firebase-in-app-messaging/SKILL.md +111 -0
  58. package/skills/firebase-messaging/SKILL.md +201 -0
  59. package/skills/firebase-remote-config/SKILL.md +131 -0
  60. package/skills/firebase-storage/SKILL.md +158 -0
  61. package/skills/flutter-add-integration-test/SKILL.md +167 -0
  62. package/skills/flutter-add-widget-preview/SKILL.md +149 -0
  63. package/skills/flutter-add-widget-test/SKILL.md +158 -0
  64. package/skills/flutter-adding-home-screen-widgets/SKILL.md +205 -0
  65. package/skills/flutter-animating-apps/SKILL.md +185 -0
  66. package/skills/flutter-app-architecture/SKILL.md +80 -0
  67. package/skills/flutter-apply-architecture-best-practices/SKILL.md +166 -0
  68. package/skills/flutter-build-responsive-layout/SKILL.md +143 -0
  69. package/skills/flutter-building-forms/SKILL.md +125 -0
  70. package/skills/flutter-building-layouts/SKILL.md +131 -0
  71. package/skills/flutter-building-plugins/SKILL.md +209 -0
  72. package/skills/flutter-caching-data/SKILL.md +171 -0
  73. package/skills/flutter-change-notifier/SKILL.md +138 -0
  74. package/skills/flutter-embedding-native-views/SKILL.md +200 -0
  75. package/skills/flutter-errors/SKILL.md +126 -0
  76. package/skills/flutter-fix-layout-issues/SKILL.md +134 -0
  77. package/skills/flutter-handling-concurrency/SKILL.md +182 -0
  78. package/skills/flutter-implement-json-serialization/SKILL.md +157 -0
  79. package/skills/flutter-improving-accessibility/SKILL.md +113 -0
  80. package/skills/flutter-interoperating-with-native-apis/SKILL.md +130 -0
  81. package/skills/flutter-login-usecase/SKILL.md +38 -0
  82. package/skills/flutter-managing-state/SKILL.md +206 -0
  83. package/skills/flutter-project-audit/SKILL.md +66 -0
  84. package/skills/flutter-reducing-app-size/SKILL.md +103 -0
  85. package/skills/flutter-secure-token-store/SKILL.md +35 -0
  86. package/skills/flutter-setting-up-on-macos/SKILL.md +78 -0
  87. package/skills/flutter-setup-declarative-routing/SKILL.md +259 -0
  88. package/skills/flutter-setup-localization/SKILL.md +214 -0
  89. package/skills/flutter-theming-apps/SKILL.md +163 -0
  90. package/skills/flutter-use-http-package/SKILL.md +178 -0
  91. package/skills/flutter-widget-review/SKILL.md +54 -0
  92. package/skills/flutter-working-with-databases/SKILL.md +203 -0
  93. package/skills/flutterfire-configure/SKILL.md +143 -0
  94. package/skills/mobile-security-audit/SKILL.md +101 -0
  95. package/skills/mockito/SKILL.md +149 -0
  96. package/skills/mocktail/SKILL.md +122 -0
  97. package/skills/patrol-e2e-testing/SKILL.md +224 -0
  98. package/skills/provider/SKILL.md +139 -0
  99. package/skills/riverpod/SKILL.md +246 -0
  100. package/skills/testing/SKILL.md +50 -0
  101. package/stacks/android/stack.json +8 -0
  102. package/stacks/flutter/stack.json +8 -0
  103. package/stacks/ios/stack.json +8 -0
  104. package/stacks/kotlin-multiplatform/stack.json +8 -0
  105. package/stacks/react-native/stack.json +8 -0
@@ -0,0 +1,182 @@
1
+ ---
2
+ name: flutter-handling-concurrency
3
+ description: Executes long-running tasks in background isolates to keep the UI responsive. Use when performing heavy computations or parsing large datasets.
4
+ metadata:
5
+ model: models/gemini-3.1-pro-preview
6
+ last_modified: Thu, 12 Mar 2026 22:23:14 GMT
7
+ intents: [performance]
8
+ stacks: [flutter]
9
+ source: https://github.com/flutter/skills
10
+ license: BSD-3-Clause
11
+ ---
12
+ # Managing Dart Concurrency and Isolates
13
+
14
+ ## Contents
15
+ - [Core Concepts](#core-concepts)
16
+ - [Decision Matrix: Async vs. Isolates](#decision-matrix-async-vs-isolates)
17
+ - [Workflows](#workflows)
18
+ - [Implementing Standard Asynchronous UI](#implementing-standard-asynchronous-ui)
19
+ - [Offloading Short-Lived Heavy Computation](#offloading-short-lived-heavy-computation)
20
+ - [Establishing Long-Lived Worker Isolates](#establishing-long-lived-worker-isolates)
21
+ - [Examples](#examples)
22
+
23
+ ## Core Concepts
24
+
25
+ Dart utilizes a single-threaded execution model driven by an Event Loop (comparable to the iOS main loop). By default, all Flutter application code runs on the Main Isolate.
26
+
27
+ * **Asynchronous Operations (`async`/`await`):** Use for non-blocking I/O tasks (network requests, file access). The Event Loop continues processing other events while waiting for the `Future` to complete.
28
+ * **Isolates:** Dart's implementation of lightweight threads. Isolates possess their own isolated memory and do not share state. They communicate exclusively via message passing.
29
+ * **Main Isolate:** The default thread where UI rendering and event handling occur. Blocking this isolate causes UI freezing (jank).
30
+ * **Worker Isolate:** A spawned isolate used to offload CPU-bound tasks (e.g., decoding large JSON blobs) to prevent Main Isolate blockage.
31
+
32
+ ## Decision Matrix: Async vs. Isolates
33
+
34
+ Apply the following conditional logic to determine the correct concurrency approach:
35
+
36
+ * **If** the task is I/O bound (e.g., HTTP request, database read) -> **Use `async`/`await`** on the Main Isolate.
37
+ * **If** the task is CPU-bound but executes quickly (< 16ms) -> **Use `async`/`await`** on the Main Isolate.
38
+ * **If** the task is CPU-bound, takes significant time, and runs once (e.g., parsing a massive JSON payload) -> **Use `Isolate.run()`**.
39
+ * **If** the task requires continuous or repeated background processing with multiple messages passed over time -> **Use `Isolate.spawn()` with `ReceivePort` and `SendPort`**.
40
+
41
+ ## Workflows
42
+
43
+ ### Implementing Standard Asynchronous UI
44
+
45
+ Use this workflow to fetch and display non-blocking asynchronous data.
46
+
47
+ **Task Progress:**
48
+ - [ ] Mark the data-fetching function with the `async` keyword.
49
+ - [ ] Return a `Future<T>` from the function.
50
+ - [ ] Use the `await` keyword to yield execution until the operation completes.
51
+ - [ ] Wrap the UI component in a `FutureBuilder<T>` (or `StreamBuilder` for streams).
52
+ - [ ] Handle `ConnectionState.waiting`, `hasError`, and `hasData` states within the builder.
53
+ - [ ] Run validator -> review UI for loading indicators -> fix missing states.
54
+
55
+ ### Offloading Short-Lived Heavy Computation
56
+
57
+ Use this workflow for one-off, CPU-intensive tasks using Dart 2.19+.
58
+
59
+ **Task Progress:**
60
+ - [ ] Identify the CPU-bound operation blocking the Main Isolate.
61
+ - [ ] Extract the computation into a standalone callback function.
62
+ - [ ] Ensure the callback function signature accepts exactly one required, unnamed argument (as per specific architectural constraints).
63
+ - [ ] Invoke `Isolate.run()` passing the callback.
64
+ - [ ] `await` the result of `Isolate.run()` in the Main Isolate.
65
+ - [ ] Assign the returned value to the application state.
66
+
67
+ ### Establishing Long-Lived Worker Isolates
68
+
69
+ Use this workflow for persistent background processes requiring continuous bidirectional communication.
70
+
71
+ **Task Progress:**
72
+ - [ ] Instantiate a `ReceivePort` on the Main Isolate to listen for messages.
73
+ - [ ] Spawn the worker isolate using `Isolate.spawn()`, passing the `ReceivePort.sendPort` as the initial message.
74
+ - [ ] In the worker isolate, instantiate its own `ReceivePort`.
75
+ - [ ] Send the worker's `SendPort` back to the Main Isolate via the initial port.
76
+ - [ ] Store the worker's `SendPort` in the Main Isolate for future message dispatching.
77
+ - [ ] Implement listeners on both `ReceivePort` instances to handle incoming messages.
78
+ - [ ] Run validator -> review memory leaks -> ensure ports are closed when the isolate is no longer needed.
79
+
80
+ ## Examples
81
+
82
+ ### Example 1: Asynchronous UI with FutureBuilder
83
+
84
+ ```dart
85
+ // 1. Define the async operation
86
+ Future<String> fetchUserData() async {
87
+ await Future.delayed(const Duration(seconds: 2)); // Simulate network I/O
88
+ return "User Data Loaded";
89
+ }
90
+
91
+ // 2. Consume in the UI
92
+ Widget build(BuildContext context) {
93
+ return FutureBuilder<String>(
94
+ future: fetchUserData(),
95
+ builder: (context, snapshot) {
96
+ if (snapshot.connectionState == ConnectionState.waiting) {
97
+ return const CircularProgressIndicator();
98
+ } else if (snapshot.hasError) {
99
+ return Text('Error: ${snapshot.error}');
100
+ } else {
101
+ return Text('Result: ${snapshot.data}');
102
+ }
103
+ },
104
+ );
105
+ }
106
+ ```
107
+
108
+ ### Example 2: Short-Lived Isolate (`Isolate.run`)
109
+
110
+ ```dart
111
+ import 'dart:isolate';
112
+ import 'dart:convert';
113
+
114
+ // 1. Define the heavy computation callback
115
+ // Note: Adhering to the strict single-argument signature requirement.
116
+ List<dynamic> decodeHeavyJson(String jsonString) {
117
+ return jsonDecode(jsonString) as List<dynamic>;
118
+ }
119
+
120
+ // 2. Offload to a worker isolate
121
+ Future<List<dynamic>> processDataInBackground(String rawJson) async {
122
+ // Isolate.run spawns the isolate, runs the computation, returns the value, and exits.
123
+ final result = await Isolate.run(() => decodeHeavyJson(rawJson));
124
+ return result;
125
+ }
126
+ ```
127
+
128
+ ### Example 3: Long-Lived Isolate (`ReceivePort` / `SendPort`)
129
+
130
+ ```dart
131
+ import 'dart:isolate';
132
+
133
+ class WorkerManager {
134
+ late SendPort _workerSendPort;
135
+ final ReceivePort _mainReceivePort = ReceivePort();
136
+ Isolate? _isolate;
137
+
138
+ Future<void> initialize() async {
139
+ // 1. Spawn isolate and pass the Main Isolate's SendPort
140
+ _isolate = await Isolate.spawn(_workerEntry, _mainReceivePort.sendPort);
141
+
142
+ // 2. Listen for messages from the Worker Isolate
143
+ _mainReceivePort.listen((message) {
144
+ if (message is SendPort) {
145
+ // First message is the Worker's SendPort
146
+ _workerSendPort = message;
147
+ _startCommunication();
148
+ } else {
149
+ // Subsequent messages are data payloads
150
+ print('Main Isolate received: $message');
151
+ }
152
+ });
153
+ }
154
+
155
+ void _startCommunication() {
156
+ // Send data to the worker
157
+ _workerSendPort.send("Process this data");
158
+ }
159
+
160
+ // 3. Worker Isolate Entry Point
161
+ static void _workerEntry(SendPort mainSendPort) {
162
+ final workerReceivePort = ReceivePort();
163
+
164
+ // Send the Worker's SendPort back to the Main Isolate
165
+ mainSendPort.send(workerReceivePort.sendPort);
166
+
167
+ // Listen for incoming tasks
168
+ workerReceivePort.listen((message) {
169
+ print('Worker Isolate received: $message');
170
+
171
+ // Perform work and send result back
172
+ final result = "Processed: $message";
173
+ mainSendPort.send(result);
174
+ });
175
+ }
176
+
177
+ void dispose() {
178
+ _mainReceivePort.close();
179
+ _isolate?.kill();
180
+ }
181
+ }
182
+ ```
@@ -0,0 +1,157 @@
1
+ ---
2
+ name: flutter-implement-json-serialization
3
+ description: Create model classes with `fromJson` and `toJson` methods using `dart:convert`. Use when manually mapping JSON keys to class properties for simple data structures.
4
+ metadata:
5
+ model: models/gemini-3.1-pro-preview
6
+ last_modified: Tue, 21 Apr 2026 21:44:50 GMT
7
+ routing: manual
8
+ stacks: [flutter]
9
+ source: https://github.com/flutter/skills
10
+ license: BSD-3-Clause
11
+ ---
12
+ # Serializing JSON Manually in Flutter
13
+
14
+ ## Contents
15
+ - [Core Guidelines](#core-guidelines)
16
+ - [Workflow: Implementing a Serializable Model](#workflow-implementing-a-serializable-model)
17
+ - [Workflow: Fetching and Parsing JSON](#workflow-fetching-and-parsing-json)
18
+ - [Examples](#examples)
19
+
20
+ ## Core Guidelines
21
+
22
+ - **Import `dart:convert`**: Utilize Flutter's built-in `dart:convert` library for manual JSON encoding (`jsonEncode`) and decoding (`jsonDecode`).
23
+ - **Enforce Type Safety**: Always cast the `dynamic` result of `jsonDecode()` to the expected type, typically `Map<String, dynamic>` for objects or `List<dynamic>` for arrays.
24
+ - **Encapsulate Serialization Logic**: Define plain model classes containing properties corresponding to the JSON structure. Implement a `fromJson` factory constructor and a `toJson` method within the model.
25
+ - **Handle Background Parsing**: If parsing large JSON documents (execution time > 16ms), offload the parsing logic to a separate isolate using Flutter's `compute()` function to prevent UI jank.
26
+ - **Throw Exceptions on Failure**: When handling HTTP responses, throw an exception if the status code is not successful (e.g., not 200 OK or 201 Created). Do not return `null`.
27
+
28
+ ## Workflow: Implementing a Serializable Model
29
+
30
+ Use this checklist to implement manual JSON serialization for a data model.
31
+
32
+ **Task Progress:**
33
+ - [ ] Define the plain model class with `final` properties.
34
+ - [ ] Implement the `factory Model.fromJson(Map<String, dynamic> json)` constructor.
35
+ - [ ] Implement the `Map<String, dynamic> toJson()` method.
36
+ - [ ] Write unit tests for both serialization methods.
37
+ - [ ] Run validator -> review type mismatch errors -> fix casting logic.
38
+
39
+ 1. **Define the Model**: Create a class with properties matching the JSON keys.
40
+ 2. **Implement `fromJson`**: Extract values from the `Map` and cast them to the appropriate Dart types. Use pattern matching or explicit casting.
41
+ 3. **Implement `toJson`**: Return a `Map<String, dynamic>` mapping the class properties back to their JSON string keys.
42
+ 4. **Validate**: Execute unit tests to ensure type safety, autocompletion, and compile-time exception handling function correctly.
43
+
44
+ ## Workflow: Fetching and Parsing JSON
45
+
46
+ Use this conditional workflow when retrieving and parsing JSON from a network request.
47
+
48
+ **Task Progress:**
49
+ - [ ] Execute the HTTP request.
50
+ - [ ] Validate the response status code.
51
+ - [ ] Determine parsing strategy (Synchronous vs. Isolate).
52
+ - [ ] Decode and map the JSON to the model.
53
+
54
+ 1. **Execute Request**: Use the `http` package to perform the network call.
55
+ 2. **Validate Response**:
56
+ - If `response.statusCode == 200` (or 201 for POST), proceed to parsing.
57
+ - If the status code indicates failure, throw an `Exception`.
58
+ 3. **Determine Parsing Strategy**:
59
+ - If parsing a **small payload** (e.g., a single object), parse synchronously on the main thread.
60
+ - If parsing a **large payload** (e.g., an array of thousands of objects), use `compute(parseFunction, response.body)` to parse in a background isolate.
61
+ 4. **Decode and Map**: Pass the decoded JSON to your model's `fromJson` constructor.
62
+
63
+ ## Examples
64
+
65
+ ### High-Fidelity Model Implementation
66
+
67
+ ```dart
68
+ import 'dart:convert';
69
+
70
+ class User {
71
+ final int id;
72
+ final String name;
73
+ final String email;
74
+
75
+ const User({
76
+ required this.id,
77
+ required this.name,
78
+ required this.email,
79
+ });
80
+
81
+ // Factory constructor for deserialization
82
+ factory User.fromJson(Map<String, dynamic> json) {
83
+ return switch (json) {
84
+ {
85
+ 'id': int id,
86
+ 'name': String name,
87
+ 'email': String email,
88
+ } =>
89
+ User(
90
+ id: id,
91
+ name: name,
92
+ email: email,
93
+ ),
94
+ _ => throw const FormatException('Failed to load User.'),
95
+ };
96
+ }
97
+
98
+ // Method for serialization
99
+ Map<String, dynamic> toJson() {
100
+ return {
101
+ 'id': id,
102
+ 'name': name,
103
+ 'email': email,
104
+ };
105
+ }
106
+ }
107
+ ```
108
+
109
+ ### Synchronous Parsing (Small Payload)
110
+
111
+ ```dart
112
+ import 'dart:convert';
113
+ import 'package:http/http.dart' as http;
114
+
115
+ Future<User> fetchUser(http.Client client, int userId) async {
116
+ final response = await client.get(
117
+ Uri.parse('https://api.example.com/users/$userId'),
118
+ headers: {'Accept': 'application/json'},
119
+ );
120
+
121
+ if (response.statusCode == 200) {
122
+ // Decode returns dynamic, cast to Map<String, dynamic>
123
+ final Map<String, dynamic> jsonMap = jsonDecode(response.body) as Map<String, dynamic>;
124
+ return User.fromJson(jsonMap);
125
+ } else {
126
+ throw Exception('Failed to load user');
127
+ }
128
+ }
129
+ ```
130
+
131
+ ### Background Parsing (Large Payload)
132
+
133
+ ```dart
134
+ import 'dart:convert';
135
+ import 'package:flutter/foundation.dart';
136
+ import 'package:http/http.dart' as http;
137
+
138
+ // Top-level function required for compute()
139
+ List<User> parseUsers(String responseBody) {
140
+ final parsed = (jsonDecode(responseBody) as List<dynamic>).cast<Map<String, dynamic>>();
141
+ return parsed.map<User>((json) => User.fromJson(json)).toList();
142
+ }
143
+
144
+ Future<List<User>> fetchUsers(http.Client client) async {
145
+ final response = await client.get(
146
+ Uri.parse('https://api.example.com/users'),
147
+ headers: {'Accept': 'application/json'},
148
+ );
149
+
150
+ if (response.statusCode == 200) {
151
+ // Offload expensive parsing to a background isolate
152
+ return compute(parseUsers, response.body);
153
+ } else {
154
+ throw Exception('Failed to load users');
155
+ }
156
+ }
157
+ ```
@@ -0,0 +1,113 @@
1
+ ---
2
+ name: flutter-improving-accessibility
3
+ description: Configures a Flutter app to support assistive technologies like Screen Readers. Use when ensuring an application is usable for people with disabilities.
4
+ metadata:
5
+ model: models/gemini-3.1-pro-preview
6
+ last_modified: Thu, 12 Mar 2026 22:17:37 GMT
7
+ intents: [accessibility]
8
+ stacks: [flutter]
9
+ source: https://github.com/flutter/skills
10
+ license: BSD-3-Clause
11
+ ---
12
+ # Implementing Flutter Accessibility
13
+
14
+ ## Contents
15
+ - [UI Design and Styling](#ui-design-and-styling)
16
+ - [Accessibility Widgets](#accessibility-widgets)
17
+ - [Web Accessibility](#web-accessibility)
18
+ - [Adaptive and Responsive Design](#adaptive-and-responsive-design)
19
+ - [Workflows](#workflows)
20
+ - [Examples](#examples)
21
+
22
+ ## UI Design and Styling
23
+ Design layouts to accommodate dynamic scaling and high visibility. Flutter automatically calculates font sizes based on OS-level accessibility settings.
24
+
25
+ * **Font Scaling:** Ensure layouts provide sufficient room to render all contents when font sizes are increased to their maximum OS settings. Avoid hardcoding fixed heights on text containers.
26
+ * **Color Contrast:** Maintain a contrast ratio of at least 4.5:1 for small text and 3.0:1 for large text (18pt+ regular or 14pt+ bold) to meet W3C standards.
27
+ * **Tap Targets:** Enforce a minimum tap target size of 48x48 logical pixels to accommodate users with limited dexterity.
28
+
29
+ ## Accessibility Widgets
30
+ Utilize Flutter's catalog of accessibility widgets to manipulate the semantics tree exposed to assistive technologies (like TalkBack or VoiceOver).
31
+
32
+ * **`Semantics`**: Use this to annotate the widget tree with a description of the meaning of the widgets. Assign specific roles using the `SemanticsRole` enum (e.g., button, link, heading) when building custom components.
33
+ * **`MergeSemantics`**: Wrap composite widgets to merge the semantics of all descendants into a single selectable node for screen readers.
34
+ * **`ExcludeSemantics`**: Use this to drop the semantics of all descendants, hiding redundant or purely decorative sub-widgets from accessibility tools.
35
+
36
+ ## Web Accessibility
37
+ Flutter web renders UI on a single canvas, requiring a specialized DOM layer to expose structure to browsers.
38
+
39
+ * **Enable Semantics:** Web accessibility is disabled by default for performance. Users can enable it via an invisible button (`aria-label="Enable accessibility"`).
40
+ * **Programmatic Enablement:** If building a web-first application requiring default accessibility, force the semantics tree generation at startup.
41
+ * **Semantic Roles:** Rely on standard widgets (`TabBar`, `MenuAnchor`, `Table`) for automatic ARIA role mapping. For custom components, explicitly assign `SemanticsRole` values to ensure screen readers interpret the elements correctly.
42
+
43
+ ## Adaptive and Responsive Design
44
+ Differentiate between adaptive and responsive paradigms to build universal applications.
45
+
46
+ * **Responsive Design:** Adjust the placement, sizing, and reflowing of design elements to fit the available screen space.
47
+ * **Adaptive Design:** Select appropriate layouts (e.g., bottom navigation vs. side panel) and input mechanisms (e.g., touch vs. mouse/keyboard) to make the UI usable within the current device context. Design to the strengths of each form factor.
48
+
49
+ ## Workflows
50
+
51
+ ### Task Progress: Accessibility Implementation
52
+ Copy this checklist to track accessibility compliance during UI development:
53
+
54
+ - [ ] Verify all interactive elements have a minimum tap target of 48x48 pixels.
55
+ - [ ] Test layout with maximum OS font size settings to ensure no text clipping or overflow occurs.
56
+ - [ ] Validate color contrast ratios (4.5:1 for normal text, 3.0:1 for large text).
57
+ - [ ] Wrap custom interactive widgets in `Semantics` and assign the appropriate `SemanticsRole`.
58
+ - [ ] Group complex composite widgets using `MergeSemantics` to prevent screen reader fatigue.
59
+ - [ ] Hide decorative elements from screen readers using `ExcludeSemantics`.
60
+ - [ ] If targeting web, verify ARIA roles are correctly mapped and consider programmatic enablement of the semantics tree.
61
+
62
+ ### Feedback Loop: Accessibility Validation
63
+ Run this loop when finalizing a view or component:
64
+ 1. **Run validator:** Execute accessibility tests or use OS-level screen readers (VoiceOver/TalkBack) to navigate the view.
65
+ 2. **Review errors:** Identify unannounced interactive elements, trapped focus, or clipped text.
66
+ 3. **Fix:** Apply `Semantics`, adjust constraints, or modify colors. Repeat until the screen reader provides a clear, logical traversal of the UI.
67
+
68
+ ## Examples
69
+
70
+ ### Programmatic Web Accessibility Enablement
71
+ If targeting web and requiring accessibility by default, initialize the semantics binding before running the app.
72
+
73
+ ```dart
74
+ import 'package:flutter/material.dart';
75
+ import 'package:flutter/semantics.dart';
76
+ import 'package:flutter/foundation.dart';
77
+
78
+ void main() {
79
+ if (kIsWeb) {
80
+ SemanticsBinding.instance.ensureSemantics();
81
+ }
82
+ runApp(const MyApp());
83
+ }
84
+ ```
85
+
86
+ ### Custom Component Semantics
87
+ If building a custom widget that acts as a list item, explicitly define its semantic role so assistive technologies and web ARIA mappings interpret it correctly.
88
+
89
+ ```dart
90
+ import 'package:flutter/material.dart';
91
+ import 'package:flutter/semantics.dart';
92
+
93
+ class CustomListItem extends StatelessWidget {
94
+ final String text;
95
+
96
+ const CustomListItem({super.key, required this.text});
97
+
98
+ @override
99
+ Widget build(BuildContext context) {
100
+ return Semantics(
101
+ role: SemanticsRole.listItem,
102
+ label: text,
103
+ child: Padding(
104
+ padding: const EdgeInsets.all(12.0), // Ensures > 48px tap target if interactive
105
+ child: Text(
106
+ text,
107
+ style: const TextStyle(fontSize: 16), // Ensure contrast ratio > 4.5:1
108
+ ),
109
+ ),
110
+ );
111
+ }
112
+ }
113
+ ```
@@ -0,0 +1,130 @@
1
+ ---
2
+ name: flutter-interoperating-with-native-apis
3
+ description: Interoperates with native platform APIs on Android, iOS, and the web. Use when accessing device-specific features not available in Dart or calling existing native code.
4
+ metadata:
5
+ model: models/gemini-3.1-pro-preview
6
+ last_modified: Thu, 12 Mar 2026 22:21:02 GMT
7
+ routing: manual
8
+ stacks: [flutter]
9
+ source: https://github.com/flutter/skills
10
+ license: BSD-3-Clause
11
+ ---
12
+ # Integrating Platform-Specific Code in Flutter
13
+
14
+ ## Contents
15
+ - [Core Concepts & Terminology](#core-concepts--terminology)
16
+ - [Binding to Native C/C++ Code (FFI)](#binding-to-native-cc-code-ffi)
17
+ - [Implementing Platform Channels & Pigeon](#implementing-platform-channels--pigeon)
18
+ - [Hosting Native Platform Views](#hosting-native-platform-views)
19
+ - [Integrating Web Content & Wasm](#integrating-web-content--wasm)
20
+ - [Workflows](#workflows)
21
+
22
+ ## Core Concepts & Terminology
23
+ - **FFI (Foreign Function Interface):** The `dart:ffi` library used to bind Dart directly to native C/C++ APIs.
24
+ - **Platform Channel:** The asynchronous message-passing system (`MethodChannel`, `BasicMessageChannel`) connecting the Dart client (UI) to the host platform (Kotlin/Java, Swift/Objective-C, C++).
25
+ - **Pigeon:** A code-generation tool that creates type-safe Platform Channels.
26
+ - **Platform View:** A mechanism to embed native UI components (e.g., Android `View`, iOS `UIView`) directly into the Flutter widget tree.
27
+ - **JS Interop:** The modern, Wasm-compatible approach to interacting with JavaScript and DOM APIs using `package:web` and `dart:js_interop`.
28
+
29
+ ## Binding to Native C/C++ Code (FFI)
30
+ Use FFI to execute high-performance native code or utilize existing C/C++ libraries without the overhead of asynchronous Platform Channels.
31
+
32
+ ### Project Setup
33
+ * **If creating a standard C/C++ integration (Recommended since Flutter 3.38):** Use the `package_ffi` template. This utilizes `build.dart` hooks to compile native code, eliminating the need for OS-specific build files (CMake, build.gradle, podspec).
34
+ ```bash
35
+ flutter create --template=package_ffi <package_name>
36
+ ```
37
+ * **If requiring access to the Flutter Plugin API or Play Services:** Use the legacy `plugin_ffi` template.
38
+ ```bash
39
+ flutter create --template=plugin_ffi <plugin_name>
40
+ ```
41
+
42
+ ### Implementation Rules
43
+ * **Symbol Visibility:** Always mark C++ symbols with `extern "C"` and prevent linker discarding during link-time optimization (LTO).
44
+ ```cpp
45
+ extern "C" __attribute__((visibility("default"))) __attribute__((used))
46
+ ```
47
+ * **Dynamic Library Naming (Apple Platforms):** Ensure your `build.dart` hook produces the exact same filename across all target architectures (e.g., `arm64` vs `x86_64`) and SDKs (`iphoneos` vs `iphonesimulator`). Do not append architecture suffixes to the `.dylib` or `.framework` names.
48
+ * **Binding Generation:** Always use `package:ffigen` to generate Dart bindings from your C headers (`.h`). Configure this in `ffigen.yaml`.
49
+
50
+ ## Implementing Platform Channels & Pigeon
51
+ Use Platform Channels when you need to interact with platform-specific APIs (e.g., Battery, Bluetooth, OS-level services) using the platform's native language.
52
+
53
+ ### Pigeon (Type-Safe Channels)
54
+ Always prefer `package:pigeon` over raw `MethodChannel` implementations for complex or frequently used APIs.
55
+ 1. Define the messaging protocol in a standalone Dart file using Pigeon annotations (`@HostApi()`).
56
+ 2. Generate the host (Kotlin/Swift/C++) and client (Dart) code.
57
+ 3. Implement the generated interfaces on the native side.
58
+
59
+ ### Threading Rules
60
+ * **Main Thread Requirement:** Always invoke channel methods destined for Flutter on the platform's main thread (UI thread).
61
+ * **Background Execution:** If executing channel handlers on a background thread (Android/iOS), you must use the Task Queue API (`makeBackgroundTaskQueue()`).
62
+ * **Isolates:** To use plugins/channels from a Dart background `Isolate`, ensure it is registered using `BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken)`.
63
+
64
+ ## Hosting Native Platform Views
65
+ Use Platform Views to embed native UI components (e.g., Google Maps, native video players) into the Flutter widget tree.
66
+
67
+ ### Android Platform Views
68
+ Evaluate the trade-offs between the two rendering modes and select the appropriate one:
69
+ * **If requiring perfect fidelity, accessibility, or SurfaceView support:** Use **Hybrid Composition** (`PlatformViewLink` + `AndroidViewSurface`). This appends the native view to the hierarchy but may reduce Flutter's rendering performance.
70
+ * **If prioritizing Flutter rendering performance and transformations:** Use **Texture Layer** (`AndroidView`). This renders the native view into a texture. Note: Quick scrolling may drop frames, and `SurfaceView` is problematic.
71
+
72
+ ### iOS Platform Views
73
+ * iOS exclusively uses Hybrid Composition.
74
+ * Implement `FlutterPlatformViewFactory` and `FlutterPlatformView` in Swift or Objective-C.
75
+ * Use the `UiKitView` widget on the Dart side.
76
+ * *Limitation:* `ShaderMask` and `ColorFiltered` widgets cannot be applied to iOS Platform Views.
77
+
78
+ ## Integrating Web Content & Wasm
79
+ Flutter Web supports compiling to WebAssembly (Wasm) for improved performance and multi-threading.
80
+
81
+ ### Wasm Compilation
82
+ * Compile to Wasm using: `flutter build web --wasm`.
83
+ * **Server Configuration:** To enable multi-threading, configure your HTTP server to emit the following headers:
84
+ * `Cross-Origin-Embedder-Policy: credentialless` (or `require-corp`)
85
+ * `Cross-Origin-Opener-Policy: same-origin`
86
+ * *Limitation:* WasmGC is not currently supported on iOS browsers (WebKit limitation). Flutter will automatically fall back to JavaScript if WasmGC is unavailable.
87
+
88
+ ### Web Interop
89
+ * **If writing new web-specific code:** Strictly use `package:web` and `dart:js_interop`.
90
+ * **Do NOT use:** `dart:html`, `dart:js`, or `package:js`. These are incompatible with Wasm compilation.
91
+ * **Embedding HTML:** Use `HtmlElementView.fromTagName` to inject arbitrary HTML elements (like `<video>`) into the Flutter Web DOM.
92
+
93
+ ---
94
+
95
+ ## Workflows
96
+
97
+ ### Workflow: Creating a Native FFI Integration
98
+ Use this workflow when binding to a C/C++ library.
99
+
100
+ - [ ] **Task Progress:**
101
+ - [ ] 1. Run `flutter create --template=package_ffi <name>`.
102
+ - [ ] 2. Place C/C++ source code in the `src/` directory.
103
+ - [ ] 3. Ensure all exported C++ functions are wrapped in `extern "C"` and visibility attributes.
104
+ - [ ] 4. Configure `ffigen.yaml` to point to your header files.
105
+ - [ ] 5. Run `dart run ffigen` to generate Dart bindings.
106
+ - [ ] 6. Modify `hook/build.dart` if linking against pre-compiled or system libraries.
107
+ - [ ] 7. Run validator -> `flutter test` -> review errors -> fix.
108
+
109
+ ### Workflow: Implementing a Type-Safe Platform Channel (Pigeon)
110
+ Use this workflow when you need to call Kotlin/Swift APIs from Dart.
111
+
112
+ - [ ] **Task Progress:**
113
+ - [ ] 1. Add `pigeon` to `dev_dependencies`.
114
+ - [ ] 2. Create `pigeons/messages.dart` and define data classes and `@HostApi()` abstract classes.
115
+ - [ ] 3. Run the Pigeon generator script to output Dart, Kotlin, and Swift files.
116
+ - [ ] 4. **Android:** Implement the generated interface in `MainActivity.kt` or your Plugin class.
117
+ - [ ] 5. **iOS:** Implement the generated protocol in `AppDelegate.swift` or your Plugin class.
118
+ - [ ] 6. **Dart:** Import the generated Dart file and call the API methods.
119
+ - [ ] 7. Run validator -> verify cross-platform compilation -> review errors -> fix.
120
+
121
+ ### Workflow: Embedding a Native Platform View
122
+ Use this workflow when embedding a native UI component (e.g., a native map or camera view).
123
+
124
+ - [ ] **Task Progress:**
125
+ - [ ] 1. **Dart:** Create a widget that conditionally returns `AndroidView` (or `PlatformViewLink`) for Android, and `UiKitView` for iOS based on `defaultTargetPlatform`.
126
+ - [ ] 2. **Android:** Create a class implementing `PlatformView` that returns the native Android `View`.
127
+ - [ ] 3. **Android:** Create a `PlatformViewFactory` and register it in `configureFlutterEngine`.
128
+ - [ ] 4. **iOS:** Create a class implementing `FlutterPlatformView` that returns the native `UIView`.
129
+ - [ ] 5. **iOS:** Create a `FlutterPlatformViewFactory` and register it in `application:didFinishLaunchingWithOptions:`.
130
+ - [ ] 6. Run validator -> test on physical Android and iOS devices -> review UI clipping/scrolling issues -> fix.
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: flutter-login-usecase
3
+ description: "Implements a Flutter login use case that authenticates through an injected repository and persists the access token through an injected storage abstraction. Use when building or reviewing the login flow of a Flutter app with layered architecture."
4
+ routing: manual
5
+ stacks: [flutter]
6
+ ---
7
+
8
+ # flutter-login-usecase
9
+
10
+ ## Description
11
+ Execute mobile login and persist the access token through injected abstractions.
12
+
13
+ ## Language
14
+ Dart
15
+
16
+ ## Inputs
17
+ - `email: String`
18
+ - `password: String`
19
+ - `repo: AuthRepository`
20
+ - `storage: TokenStorage`
21
+
22
+ ## Returns
23
+ - `Future<void>`
24
+
25
+ ## Example
26
+ ```dart
27
+ class LoginUseCase {
28
+ LoginUseCase(this._repo, this._storage);
29
+
30
+ final AuthRepository _repo;
31
+ final TokenStorage _storage;
32
+
33
+ Future<void> call(String email, String password) async {
34
+ final token = await _repo.login(email, password);
35
+ await _storage.save(token);
36
+ }
37
+ }
38
+ ```