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.
- package/.claude-plugin/marketplace.json +24 -0
- package/.claude-plugin/plugin.json +12 -0
- package/CHANGELOG.md +103 -0
- package/LICENSE +21 -0
- package/README.md +631 -0
- package/THIRD_PARTY_NOTICES.md +105 -0
- package/agents/flutter-architect.md +92 -0
- package/agents/flutter-performance-engineer.md +103 -0
- package/agents/flutter-test-engineer.md +100 -0
- package/agents/lead-mobile.md +107 -0
- package/agents/mobile-code-reviewer.md +66 -0
- package/agents/mobile-staff-engineer.md +85 -0
- package/agents/plugin-native-expert.md +97 -0
- package/bin/reis-mobile.mjs +256 -0
- package/commands/debate.md +135 -0
- package/commands/doctor.md +23 -0
- package/commands/reis-mobile.md +50 -0
- package/commands/review.md +53 -0
- package/core/config/language.mjs +83 -0
- package/core/context/context-engine.mjs +113 -0
- package/core/detection/project-probe.mjs +104 -0
- package/core/detection/stack-detector.mjs +204 -0
- package/core/diagnostics/doctor.mjs +181 -0
- package/core/install/claude-plugin.mjs +76 -0
- package/core/paths.mjs +4 -0
- package/core/registry/frontmatter.mjs +81 -0
- package/core/registry/registry.mjs +140 -0
- package/core/router/intent-detector.mjs +75 -0
- package/core/router/intents.mjs +91 -0
- package/core/router/router.mjs +83 -0
- package/core/security/redact.mjs +24 -0
- package/package.json +35 -0
- package/skills/architecture-feature-first/SKILL.md +116 -0
- package/skills/bloc/SKILL.md +354 -0
- package/skills/code-review/SKILL.md +89 -0
- package/skills/dart-3-updates/SKILL.md +223 -0
- package/skills/dart-add-unit-test/SKILL.md +126 -0
- package/skills/dart-collect-coverage/SKILL.md +145 -0
- package/skills/dart-fix-runtime-errors/SKILL.md +170 -0
- package/skills/dart-generate-test-mocks/SKILL.md +159 -0
- package/skills/dart-migrate-to-checks-package/SKILL.md +532 -0
- package/skills/dart-resolve-package-conflicts/SKILL.md +120 -0
- package/skills/dart-run-static-analysis/SKILL.md +108 -0
- package/skills/dart-use-pattern-matching/SKILL.md +240 -0
- package/skills/dart-use-pattern-matching/examples/json_patterns.dart +85 -0
- package/skills/detect-mobile-stack/SKILL.md +33 -0
- package/skills/effective-dart/SKILL.md +187 -0
- package/skills/firebase-ai/SKILL.md +93 -0
- package/skills/firebase-analytics/SKILL.md +129 -0
- package/skills/firebase-app-check/SKILL.md +124 -0
- package/skills/firebase-auth/SKILL.md +224 -0
- package/skills/firebase-cloud-firestore/SKILL.md +165 -0
- package/skills/firebase-cloud-functions/SKILL.md +148 -0
- package/skills/firebase-crashlytics/SKILL.md +182 -0
- package/skills/firebase-data-connect/SKILL.md +80 -0
- package/skills/firebase-database/SKILL.md +224 -0
- package/skills/firebase-in-app-messaging/SKILL.md +111 -0
- package/skills/firebase-messaging/SKILL.md +201 -0
- package/skills/firebase-remote-config/SKILL.md +131 -0
- package/skills/firebase-storage/SKILL.md +158 -0
- package/skills/flutter-add-integration-test/SKILL.md +167 -0
- package/skills/flutter-add-widget-preview/SKILL.md +149 -0
- package/skills/flutter-add-widget-test/SKILL.md +158 -0
- package/skills/flutter-adding-home-screen-widgets/SKILL.md +205 -0
- package/skills/flutter-animating-apps/SKILL.md +185 -0
- package/skills/flutter-app-architecture/SKILL.md +80 -0
- package/skills/flutter-apply-architecture-best-practices/SKILL.md +166 -0
- package/skills/flutter-build-responsive-layout/SKILL.md +143 -0
- package/skills/flutter-building-forms/SKILL.md +125 -0
- package/skills/flutter-building-layouts/SKILL.md +131 -0
- package/skills/flutter-building-plugins/SKILL.md +209 -0
- package/skills/flutter-caching-data/SKILL.md +171 -0
- package/skills/flutter-change-notifier/SKILL.md +138 -0
- package/skills/flutter-embedding-native-views/SKILL.md +200 -0
- package/skills/flutter-errors/SKILL.md +126 -0
- package/skills/flutter-fix-layout-issues/SKILL.md +134 -0
- package/skills/flutter-handling-concurrency/SKILL.md +182 -0
- package/skills/flutter-implement-json-serialization/SKILL.md +157 -0
- package/skills/flutter-improving-accessibility/SKILL.md +113 -0
- package/skills/flutter-interoperating-with-native-apis/SKILL.md +130 -0
- package/skills/flutter-login-usecase/SKILL.md +38 -0
- package/skills/flutter-managing-state/SKILL.md +206 -0
- package/skills/flutter-project-audit/SKILL.md +66 -0
- package/skills/flutter-reducing-app-size/SKILL.md +103 -0
- package/skills/flutter-secure-token-store/SKILL.md +35 -0
- package/skills/flutter-setting-up-on-macos/SKILL.md +78 -0
- package/skills/flutter-setup-declarative-routing/SKILL.md +259 -0
- package/skills/flutter-setup-localization/SKILL.md +214 -0
- package/skills/flutter-theming-apps/SKILL.md +163 -0
- package/skills/flutter-use-http-package/SKILL.md +178 -0
- package/skills/flutter-widget-review/SKILL.md +54 -0
- package/skills/flutter-working-with-databases/SKILL.md +203 -0
- package/skills/flutterfire-configure/SKILL.md +143 -0
- package/skills/mobile-security-audit/SKILL.md +101 -0
- package/skills/mockito/SKILL.md +149 -0
- package/skills/mocktail/SKILL.md +122 -0
- package/skills/patrol-e2e-testing/SKILL.md +224 -0
- package/skills/provider/SKILL.md +139 -0
- package/skills/riverpod/SKILL.md +246 -0
- package/skills/testing/SKILL.md +50 -0
- package/stacks/android/stack.json +8 -0
- package/stacks/flutter/stack.json +8 -0
- package/stacks/ios/stack.json +8 -0
- package/stacks/kotlin-multiplatform/stack.json +8 -0
- package/stacks/react-native/stack.json +8 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: firebase-crashlytics
|
|
3
|
+
description: Integrates Firebase Crashlytics into Flutter apps. Use when setting up crash reporting, handling fatal and non-fatal errors, customizing crash reports with keys/logs/user identifiers, or configuring opt-in reporting.
|
|
4
|
+
routing: manual
|
|
5
|
+
stacks: [flutter]
|
|
6
|
+
source: https://github.com/evanca/flutter-ai-rules
|
|
7
|
+
license: MIT
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Firebase Crashlytics Skill
|
|
11
|
+
|
|
12
|
+
This skill defines how to correctly use Firebase Crashlytics in Flutter applications.
|
|
13
|
+
|
|
14
|
+
## When to Use
|
|
15
|
+
|
|
16
|
+
Use this skill when:
|
|
17
|
+
|
|
18
|
+
* Setting up Crashlytics in a Flutter project.
|
|
19
|
+
* Configuring fatal and non-fatal error handling.
|
|
20
|
+
* Customizing crash reports with keys, logs, and user identifiers.
|
|
21
|
+
* Testing crash reporting or configuring opt-in data collection.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 1. Setup and Configuration
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
flutter pub add firebase_crashlytics
|
|
29
|
+
flutter pub add firebase_analytics # enables breadcrumb logs for better crash context
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Run `flutterfire configure` to update your Firebase configuration and add the required Crashlytics Gradle plugin for Android.
|
|
33
|
+
|
|
34
|
+
```dart
|
|
35
|
+
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Obfuscated code:**
|
|
39
|
+
- For apps built with `--split-debug-info` and/or `--obfuscate`, upload symbol files for readable stack traces.
|
|
40
|
+
- **iOS:** Flutter 3.12.0+ and Crashlytics Flutter plugin 3.3.4+ handle symbol upload automatically.
|
|
41
|
+
- **Android:** Use Firebase CLI (v11.9.0+) to upload Flutter debug symbols before reporting crashes:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
firebase crashlytics:symbols:upload --app=FIREBASE_APP_ID PATH/TO/symbols
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 2. Error Handling
|
|
50
|
+
|
|
51
|
+
**Fatal Flutter errors:**
|
|
52
|
+
|
|
53
|
+
```dart
|
|
54
|
+
void main() async {
|
|
55
|
+
WidgetsFlutterBinding.ensureInitialized();
|
|
56
|
+
await Firebase.initializeApp();
|
|
57
|
+
|
|
58
|
+
// Pass all uncaught fatal errors from the framework to Crashlytics
|
|
59
|
+
FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterFatalError;
|
|
60
|
+
|
|
61
|
+
runApp(MyApp());
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Non-fatal Flutter errors:** use `recordFlutterError` instead of `recordFlutterFatalError`.
|
|
66
|
+
|
|
67
|
+
**Async errors not caught by the Flutter framework:**
|
|
68
|
+
|
|
69
|
+
```dart
|
|
70
|
+
PlatformDispatcher.instance.onError = (error, stack) {
|
|
71
|
+
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
|
|
72
|
+
return true;
|
|
73
|
+
};
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Isolate errors:**
|
|
77
|
+
|
|
78
|
+
```dart
|
|
79
|
+
Isolate.current.addErrorListener(RawReceivePort((pair) async {
|
|
80
|
+
final List<dynamic> errorAndStacktrace = pair;
|
|
81
|
+
await FirebaseCrashlytics.instance.recordError(
|
|
82
|
+
errorAndStacktrace.first,
|
|
83
|
+
errorAndStacktrace.last,
|
|
84
|
+
fatal: true,
|
|
85
|
+
);
|
|
86
|
+
}).sendPort);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Caught exceptions (non-fatal):**
|
|
90
|
+
|
|
91
|
+
```dart
|
|
92
|
+
await FirebaseCrashlytics.instance.recordError(
|
|
93
|
+
error,
|
|
94
|
+
stackTrace,
|
|
95
|
+
reason: 'a non-fatal error',
|
|
96
|
+
information: ['further diagnostic information about the error', 'version 2.0'],
|
|
97
|
+
);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
- Crashlytics only stores the **most recent 8 non-fatal exceptions** per session — older ones are discarded.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 3. Crash Report Customization
|
|
105
|
+
|
|
106
|
+
**Custom keys** (max 64 key/value pairs, up to 1 kB each):
|
|
107
|
+
|
|
108
|
+
```dart
|
|
109
|
+
FirebaseCrashlytics.instance.setCustomKey('str_key', 'hello');
|
|
110
|
+
FirebaseCrashlytics.instance.setCustomKey('bool_key', true);
|
|
111
|
+
FirebaseCrashlytics.instance.setCustomKey('int_key', 1);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Custom log messages** (limit: 64 kB per session):
|
|
115
|
+
|
|
116
|
+
```dart
|
|
117
|
+
FirebaseCrashlytics.instance.log("User tapped on payment button");
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**User identifier:**
|
|
121
|
+
|
|
122
|
+
```dart
|
|
123
|
+
FirebaseCrashlytics.instance.setUserIdentifier("user-123");
|
|
124
|
+
// Clear by setting to blank string
|
|
125
|
+
FirebaseCrashlytics.instance.setUserIdentifier("");
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
- Avoid putting unique values (user IDs, timestamps) directly in exception messages — use custom keys instead.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 4. Performance and Optimization
|
|
133
|
+
|
|
134
|
+
- Crashlytics processes exceptions on a **dedicated background thread** to minimize performance impact.
|
|
135
|
+
- **Fatal** reports are sent in real-time without requiring an app restart.
|
|
136
|
+
- **Non-fatal** reports are written to disk and sent with the next fatal report or on app restart.
|
|
137
|
+
- Crashlytics rate-limits reports from a device to reduce network traffic if necessary.
|
|
138
|
+
- Use breadcrumb logs (requires Firebase Analytics) to understand user actions leading up to a crash.
|
|
139
|
+
|
|
140
|
+
**Disable Crashlytics in debug builds:**
|
|
141
|
+
|
|
142
|
+
```dart
|
|
143
|
+
if (kReleaseMode) {
|
|
144
|
+
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
|
|
145
|
+
} else {
|
|
146
|
+
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(false);
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 5. Testing and Debugging
|
|
153
|
+
|
|
154
|
+
Force a test crash to verify your setup:
|
|
155
|
+
|
|
156
|
+
```dart
|
|
157
|
+
FirebaseCrashlytics.instance.crash();
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
- Test both fatal and non-fatal error reporting.
|
|
161
|
+
- Verify stack traces are properly symbolicated when using code obfuscation.
|
|
162
|
+
- Check that custom keys, logs, and user identifiers are associated with crash reports.
|
|
163
|
+
- Monitor the Crashlytics dashboard regularly and set up alerts for new issues or regressions.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 6. Opt-in Reporting
|
|
168
|
+
|
|
169
|
+
By default, Crashlytics automatically collects crash reports for all users.
|
|
170
|
+
|
|
171
|
+
To give users control over data collection:
|
|
172
|
+
- Disable automatic reporting and enable it only via `setCrashlyticsCollectionEnabled(true)` when users opt in.
|
|
173
|
+
- The override value **persists** across all subsequent app launches.
|
|
174
|
+
- To opt a user out, pass `false` — this applies from the next app launch.
|
|
175
|
+
- When disabled, crash info is **stored locally**; if later enabled, locally stored crashes are sent to Crashlytics.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## References
|
|
180
|
+
|
|
181
|
+
- [Firebase Crashlytics Flutter documentation](https://firebase.google.com/docs/crashlytics/get-started?platform=flutter)
|
|
182
|
+
- [Customize crash reports](https://firebase.google.com/docs/crashlytics/customize-crash-reports?platform=flutter)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: firebase-data-connect
|
|
3
|
+
description: Integrates Firebase Data Connect into Flutter apps. Use when setting up Data Connect, designing queries, handling errors, or applying security and performance best practices.
|
|
4
|
+
routing: manual
|
|
5
|
+
stacks: [flutter]
|
|
6
|
+
source: https://github.com/evanca/flutter-ai-rules
|
|
7
|
+
license: MIT
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Firebase Data Connect Skill
|
|
11
|
+
|
|
12
|
+
This skill defines how to correctly use Firebase Data Connect in Flutter applications.
|
|
13
|
+
|
|
14
|
+
## When to Use
|
|
15
|
+
|
|
16
|
+
Use this skill when:
|
|
17
|
+
|
|
18
|
+
* Setting up and configuring Firebase Data Connect in a Flutter project.
|
|
19
|
+
* Designing schemas, queries, and mutations for Data Connect.
|
|
20
|
+
* Handling network failures, data inconsistencies, and offline scenarios.
|
|
21
|
+
* Applying security and performance best practices.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 1. Setup and Configuration
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
flutter pub add firebase_data_connect
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```dart
|
|
32
|
+
import 'package:firebase_data_connect/firebase_data_connect.dart';
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
- Ensure your Firebase project is properly configured for Data Connect services.
|
|
36
|
+
- Initialize Firebase before using any Data Connect features.
|
|
37
|
+
|
|
38
|
+
**Platform support:**
|
|
39
|
+
|
|
40
|
+
| Platform | Support |
|
|
41
|
+
|---|---|
|
|
42
|
+
| iOS | Full |
|
|
43
|
+
| Android | Full |
|
|
44
|
+
| Web | Full |
|
|
45
|
+
| Other platforms | Not supported |
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 2. Best Practices
|
|
50
|
+
|
|
51
|
+
- Follow Firebase Data Connect documentation for proper **schema design** and **query optimization**.
|
|
52
|
+
- Design efficient queries to minimize data transfer and processing time.
|
|
53
|
+
- Implement **pagination** for large datasets to improve app responsiveness.
|
|
54
|
+
- Use real-time listeners judiciously to avoid unnecessary network usage.
|
|
55
|
+
- Consider **offline capabilities** for critical app functionality.
|
|
56
|
+
- Use **caching strategies** to improve performance and reduce costs.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 3. Error Handling
|
|
61
|
+
|
|
62
|
+
- Handle **connection errors** gracefully with appropriate retry mechanisms.
|
|
63
|
+
- Implement proper error messages for data validation failures.
|
|
64
|
+
- Handle **offline scenarios** and implement appropriate fallback behavior.
|
|
65
|
+
- Monitor error rates and investigate recurring issues.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 4. Security
|
|
70
|
+
|
|
71
|
+
- Configure **Firebase Security Rules** for Data Connect to control data access.
|
|
72
|
+
- Use **Firebase Authentication** integration for user-based access control.
|
|
73
|
+
- Implement proper **data validation** on both client and server sides.
|
|
74
|
+
- Follow data privacy best practices when handling user information.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## References
|
|
79
|
+
|
|
80
|
+
- [Firebase Data Connect documentation](https://firebase.google.com/docs/data-connect)
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: firebase-database
|
|
3
|
+
description: Integrates Firebase Realtime Database into Flutter apps. Use when setting up Realtime Database, structuring JSON data, querying, performing read/write operations, implementing offline capabilities, or applying security rules.
|
|
4
|
+
routing: manual
|
|
5
|
+
stacks: [flutter]
|
|
6
|
+
source: https://github.com/evanca/flutter-ai-rules
|
|
7
|
+
license: MIT
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Firebase Realtime Database Skill
|
|
11
|
+
|
|
12
|
+
This skill defines how to correctly use Firebase Realtime Database in Flutter applications.
|
|
13
|
+
|
|
14
|
+
## When to Use
|
|
15
|
+
|
|
16
|
+
Use this skill when working with Firebase Realtime Database for **simple data models**, **low-latency sync**, or **presence functionality**. For rich data models requiring complex queries and high scalability, use Cloud Firestore instead.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 1. Database Selection
|
|
21
|
+
|
|
22
|
+
Choose **Realtime Database** when your app needs:
|
|
23
|
+
- Simple data models with simple lookups.
|
|
24
|
+
- Extremely low-latency synchronization (typical response times under 10ms).
|
|
25
|
+
- Deep queries that return an entire subtree by default.
|
|
26
|
+
- Access to data at any granularity, down to individual leaf-node values.
|
|
27
|
+
- Frequent state-syncing with built-in presence functionality.
|
|
28
|
+
|
|
29
|
+
Choose **Cloud Firestore** instead for rich data models requiring queryability, scalability, and high availability.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 2. Setup and Configuration
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
flutter pub add firebase_database
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```dart
|
|
40
|
+
import 'package:firebase_database/firebase_database.dart';
|
|
41
|
+
|
|
42
|
+
// After Firebase.initializeApp():
|
|
43
|
+
final DatabaseReference ref = FirebaseDatabase.instance.ref();
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
- Select the database location closest to your users.
|
|
47
|
+
- Enable persistence for offline capabilities:
|
|
48
|
+
|
|
49
|
+
```dart
|
|
50
|
+
FirebaseDatabase.instance.setPersistenceEnabled(true);
|
|
51
|
+
FirebaseDatabase.instance.setPersistenceCacheSizeBytes(10000000); // 10MB
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 3. Data Structure
|
|
57
|
+
|
|
58
|
+
- Structure data as a **flattened JSON tree** — avoid deep nesting.
|
|
59
|
+
- Maximum nesting depth is **32 levels**.
|
|
60
|
+
- Design your data structure to support your most common queries.
|
|
61
|
+
- Use **push IDs** for unique identifiers in list-type data:
|
|
62
|
+
|
|
63
|
+
```dart
|
|
64
|
+
final newPostKey = FirebaseDatabase.instance.ref().child('posts').push().key;
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- **Denormalize** data when necessary — Realtime Database doesn't support joins.
|
|
68
|
+
- Custom keys must be UTF-8 encoded, max 768 bytes, and cannot contain `.` `$` `#` `[` `]` `/` or ASCII control characters 0–31 or 127.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 4. Indexing and Querying
|
|
73
|
+
|
|
74
|
+
- Queries can sort **or** filter on a property, but not both in the same query.
|
|
75
|
+
- Use `.indexOn` in security rules to index frequently queried fields:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"rules": {
|
|
80
|
+
"dinosaurs": {
|
|
81
|
+
".indexOn": ["height", "length"]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
- Queries are **deep** by default and return the entire subtree.
|
|
88
|
+
- Sort with `orderByChild()`, `orderByKey()`, or `orderByValue()`:
|
|
89
|
+
|
|
90
|
+
```dart
|
|
91
|
+
final query = FirebaseDatabase.instance.ref("dinosaurs").orderByChild("height");
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
- Limit results with `limitToFirst()` or `limitToLast()`:
|
|
95
|
+
|
|
96
|
+
```dart
|
|
97
|
+
final query = ref.orderByChild("height").limitToFirst(10);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 5. Read and Write Operations
|
|
103
|
+
|
|
104
|
+
**Read once:**
|
|
105
|
+
|
|
106
|
+
```dart
|
|
107
|
+
final snapshot = await FirebaseDatabase.instance.ref('users/123').get();
|
|
108
|
+
if (snapshot.exists) {
|
|
109
|
+
print(snapshot.value);
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Real-time listener:**
|
|
114
|
+
|
|
115
|
+
```dart
|
|
116
|
+
FirebaseDatabase.instance.ref('users/123').onValue.listen((event) {
|
|
117
|
+
final data = event.snapshot.value;
|
|
118
|
+
print(data);
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
A `DatabaseEvent` fires every time data changes at the reference, including changes to children.
|
|
123
|
+
|
|
124
|
+
**Write (replace):**
|
|
125
|
+
|
|
126
|
+
```dart
|
|
127
|
+
await ref.set({
|
|
128
|
+
"name": "John",
|
|
129
|
+
"age": 18,
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Update (partial):**
|
|
134
|
+
|
|
135
|
+
```dart
|
|
136
|
+
await ref.update({"age": 19});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Atomic transaction:**
|
|
140
|
+
|
|
141
|
+
```dart
|
|
142
|
+
FirebaseDatabase.instance.ref('posts/123/likes').runTransaction((currentValue) {
|
|
143
|
+
return (currentValue as int? ?? 0) + 1;
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Multi-path atomic update:**
|
|
148
|
+
|
|
149
|
+
```dart
|
|
150
|
+
final updates = <String, dynamic>{
|
|
151
|
+
'posts/$postId': postData,
|
|
152
|
+
'user-posts/$uid/$postId': postData,
|
|
153
|
+
};
|
|
154
|
+
FirebaseDatabase.instance.ref().update(updates);
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
- Keep individual write operations under **256KB**.
|
|
158
|
+
- Use listeners for real-time updates rather than polling.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 6. Designing for Scale
|
|
163
|
+
|
|
164
|
+
- Realtime Database scales to ~200,000 concurrent connections and 1,000 writes/second per database. For higher scale, **shard** data across multiple database instances.
|
|
165
|
+
- Avoid storing large blobs — use **Firebase Storage** for files.
|
|
166
|
+
- Use **server timestamps** for consistent time tracking:
|
|
167
|
+
|
|
168
|
+
```dart
|
|
169
|
+
FirebaseDatabase.instance.ref('posts/123/timestamp').set(ServerValue.timestamp);
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
- Implement **fan-out patterns** for data accessed from multiple paths.
|
|
173
|
+
- Avoid deep nesting — it leads to performance issues when retrieving data.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## 7. Offline Capabilities
|
|
178
|
+
|
|
179
|
+
```dart
|
|
180
|
+
FirebaseDatabase.instance.setPersistenceEnabled(true);
|
|
181
|
+
|
|
182
|
+
// Keep critical paths synced when offline
|
|
183
|
+
FirebaseDatabase.instance.ref('important-data').keepSynced(true);
|
|
184
|
+
|
|
185
|
+
// Detect connection state
|
|
186
|
+
FirebaseDatabase.instance.ref('.info/connected').onValue.listen((event) {
|
|
187
|
+
final connected = event.snapshot.value as bool? ?? false;
|
|
188
|
+
print('Connected: $connected');
|
|
189
|
+
});
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
- Use value events (`onValue`) to read data and get notified of updates — optimized for online/offline transitions.
|
|
193
|
+
- Use `get()` only when you need data once; it probes local cache if the server is unavailable.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## 8. Security
|
|
198
|
+
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"rules": {
|
|
202
|
+
"users": {
|
|
203
|
+
"$uid": {
|
|
204
|
+
".read": "$uid === auth.uid",
|
|
205
|
+
".write": "$uid === auth.uid"
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
- Use `.read`, `.write`, `.validate`, and `.indexOn` to control access and validate data.
|
|
213
|
+
- Read and write rules **cascade** in Realtime Database.
|
|
214
|
+
- Use the `auth` variable to authenticate users in security rules.
|
|
215
|
+
- Test rules thoroughly using the Firebase console's rules simulator.
|
|
216
|
+
- Use the **Firebase Emulator Suite** for local testing.
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## References
|
|
221
|
+
|
|
222
|
+
- [Firebase Realtime Database Flutter documentation](https://firebase.google.com/docs/database/flutter/start)
|
|
223
|
+
- [Structure data](https://firebase.google.com/docs/database/flutter/structure-data)
|
|
224
|
+
- [Read and write data](https://firebase.google.com/docs/database/flutter/read-and-write)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: firebase-in-app-messaging
|
|
3
|
+
description: Integrates Firebase In-App Messaging into Flutter apps. Use when setting up in-app messaging, triggering or suppressing messages, managing user privacy and opt-in data collection, or testing campaigns.
|
|
4
|
+
routing: manual
|
|
5
|
+
stacks: [flutter]
|
|
6
|
+
source: https://github.com/evanca/flutter-ai-rules
|
|
7
|
+
license: MIT
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Firebase In-App Messaging Skill
|
|
11
|
+
|
|
12
|
+
This skill defines how to correctly use Firebase In-App Messaging in Flutter applications.
|
|
13
|
+
|
|
14
|
+
## When to Use
|
|
15
|
+
|
|
16
|
+
Use this skill when:
|
|
17
|
+
|
|
18
|
+
* Setting up Firebase In-App Messaging in a Flutter project.
|
|
19
|
+
* Triggering or suppressing in-app messages programmatically.
|
|
20
|
+
* Implementing opt-in data collection for user privacy.
|
|
21
|
+
* Testing campaigns with specific devices.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 1. Setup and Configuration
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
flutter pub add firebase_in_app_messaging
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```dart
|
|
32
|
+
import 'package:firebase_in_app_messaging/firebase_in_app_messaging.dart';
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
- Initialize Firebase before using any In-App Messaging features.
|
|
36
|
+
- In-App Messaging **retrieves messages from the server once per day** by default to conserve power.
|
|
37
|
+
|
|
38
|
+
**Finding your Installation ID for testing:**
|
|
39
|
+
- **Android:** Look for `I/FIAM.Headless: Starting InAppMessaging runtime with Installation ID YOUR_INSTALLATION_ID` in logcat (filter by "FIAM.Headless").
|
|
40
|
+
- **iOS:** Enable debug mode by adding `-FIRDebugEnabled` as a runtime argument in Xcode's scheme settings; find `[Firebase/InAppMessaging][I-IAM180017]` in Xcode console logs.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 2. Message Triggering and Display
|
|
45
|
+
|
|
46
|
+
Use Google Analytics events to trigger in-app messages without additional code. For programmatic triggering:
|
|
47
|
+
|
|
48
|
+
```dart
|
|
49
|
+
FirebaseInAppMessaging.instance.triggerEvent("eventName");
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Suppress messages during critical flows** (e.g., payment processing):
|
|
53
|
+
|
|
54
|
+
```dart
|
|
55
|
+
FirebaseInAppMessaging.instance.setMessagesSuppressed(true);
|
|
56
|
+
// Re-enable when appropriate:
|
|
57
|
+
FirebaseInAppMessaging.instance.setMessagesSuppressed(false);
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- Suppression is **automatically turned off** on app restart.
|
|
61
|
+
- Suppressed messages are ignored — their trigger conditions must be met again after suppression is lifted.
|
|
62
|
+
- Platform-specific message interaction callbacks (iOS/Android) are not directly accessible from Flutter; use native APIs for those.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 3. User Privacy and Opt-In Data Collection
|
|
67
|
+
|
|
68
|
+
By default, In-App Messaging automatically delivers messages to all targeted users.
|
|
69
|
+
|
|
70
|
+
**Disable automatic collection — iOS** (`Info.plist`):
|
|
71
|
+
```
|
|
72
|
+
FirebaseInAppMessagingAutomaticDataCollectionEnabled = NO
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Disable automatic collection — Android** (`AndroidManifest.xml`):
|
|
76
|
+
```xml
|
|
77
|
+
<meta-data
|
|
78
|
+
android:name="firebase_inapp_messaging_auto_data_collection_enabled"
|
|
79
|
+
android:value="false" />
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Enable for users who opt in:**
|
|
83
|
+
```dart
|
|
84
|
+
FirebaseInAppMessaging.instance.setAutomaticDataCollectionEnabled(true);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
- Manually set preferences **persist through app restarts**, overriding configuration file values.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 4. Testing and Debugging
|
|
92
|
+
|
|
93
|
+
- Use the Firebase console's **"Test on your Device"** feature, entering the app's Firebase Installation ID to send test messages on demand.
|
|
94
|
+
- Always test on **actual devices** for proper rendering and behavior.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 5. Campaign Management
|
|
99
|
+
|
|
100
|
+
- Create campaigns in the Firebase console under **Messaging**.
|
|
101
|
+
- Message types: **modal**, **banner**, **card**, or **image-only**.
|
|
102
|
+
- Use **custom metadata** (key-value pairs) to pass additional info accessible when users interact with messages.
|
|
103
|
+
- Target based on user segments, app version, language, and Analytics-based conditions.
|
|
104
|
+
- Use **A/B testing** to optimize message content and delivery.
|
|
105
|
+
- Monitor campaign performance through Firebase console analytics.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## References
|
|
110
|
+
|
|
111
|
+
- [Firebase In-App Messaging Flutter documentation](https://firebase.google.com/docs/in-app-messaging/get-started?platform=flutter)
|