@buivietphi/skill-mobile-mt 1.3.0 → 1.4.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/AGENTS.md +24 -17
- package/README.md +78 -13
- package/SKILL.md +17 -3
- package/android/android-native.md +50 -0
- package/bin/install.mjs +41 -14
- package/flutter/flutter.md +58 -0
- package/humanizer/humanizer-mobile.md +295 -0
- package/package.json +3 -2
- package/shared/offline-first.md +377 -0
- package/shared/on-device-ai.md +175 -0
- package/shared/platform-excellence.md +85 -0
package/AGENTS.md
CHANGED
|
@@ -34,13 +34,13 @@ skill-mobile-mt/
|
|
|
34
34
|
│ └── react-native.md ← RN + Expo patterns (5,108 tokens)
|
|
35
35
|
│
|
|
36
36
|
├── flutter/
|
|
37
|
-
│ └── flutter.md ← Flutter + Dart patterns (
|
|
37
|
+
│ └── flutter.md ← Flutter + Dart 3.x patterns (2,100 tokens)
|
|
38
38
|
│
|
|
39
39
|
├── ios/
|
|
40
40
|
│ └── ios-native.md ← Swift + UIKit/SwiftUI patterns (1,452 tokens)
|
|
41
41
|
│
|
|
42
42
|
├── android/
|
|
43
|
-
│ └── android-native.md ← Kotlin + Compose patterns (
|
|
43
|
+
│ └── android-native.md ← Kotlin + Compose patterns (2,100 tokens)
|
|
44
44
|
│
|
|
45
45
|
└── shared/
|
|
46
46
|
│
|
|
@@ -54,21 +54,24 @@ skill-mobile-mt/
|
|
|
54
54
|
├── document-analysis.md ← Parse images/PDFs/DOCX → code (1,200 tokens)
|
|
55
55
|
├── anti-patterns.md ← PII, cardinality, payload detection (2,800 tokens)
|
|
56
56
|
├── performance-prediction.md ← Frame budget, FPS prediction (1,500 tokens)
|
|
57
|
-
├── platform-excellence.md ← iOS 18+ vs Android 15+ UX (
|
|
57
|
+
├── platform-excellence.md ← iOS 18+ vs Android 15+ UX + HIG (2,200 tokens)
|
|
58
58
|
├── version-management.md ← SDK compat matrix + release testing (3,500 tokens)
|
|
59
59
|
├── observability.md ← Sessions as 4th pillar (3,000 tokens)
|
|
60
60
|
├── architecture-intelligence.md ← Patterns from 30+ production repos (4,500 tokens)
|
|
61
61
|
├── common-pitfalls.md ← Known issue patterns (1,160 tokens)
|
|
62
62
|
├── release-checklist.md ← App Store/Play Store checklist (587 tokens)
|
|
63
63
|
│
|
|
64
|
+
├── offline-first.md ← Local-first + sync patterns (2,566 tokens)
|
|
65
|
+
├── on-device-ai.md ← Core ML / TFLite / llama.cpp patterns (700 tokens)
|
|
66
|
+
│
|
|
64
67
|
├── ── TEMPLATES (copy to your project) ────────────────────
|
|
65
68
|
├── claude-md-template.md ← CLAUDE.md for Claude Code (copy to project root)
|
|
66
69
|
└── agent-rules-template.md ← Rules for ALL agents: Cursor/.cursorrules, Windsurf/.windsurfrules, Copilot/.github/copilot-instructions.md, Codex/AGENTS.md, Gemini/GEMINI.md, Antigravity YAML
|
|
67
70
|
```
|
|
68
71
|
|
|
69
72
|
**Token totals:**
|
|
70
|
-
- Smart load (1 platform + core shared): **~
|
|
71
|
-
- Full load (all files): **~
|
|
73
|
+
- Smart load (1 platform + core shared): **~38,600 tokens** (30.2% of 128K)
|
|
74
|
+
- Full load (all files): **~70,000 tokens** (54.7% of 128K)
|
|
72
75
|
|
|
73
76
|
---
|
|
74
77
|
|
|
@@ -80,13 +83,13 @@ skill-mobile-mt/
|
|
|
80
83
|
|
|
81
84
|
**Loads automatically:**
|
|
82
85
|
```
|
|
83
|
-
SKILL.md (
|
|
84
|
-
+ 1 platform file (~1,
|
|
85
|
-
+ shared/code-review.md (
|
|
86
|
-
+ shared/bug-detection.md (
|
|
87
|
-
+ shared/prompt-engineering.md (
|
|
86
|
+
SKILL.md (~13,200 tokens)
|
|
87
|
+
+ 1 platform file (~1,580–5,730 tokens depending on platform)
|
|
88
|
+
+ shared/code-review.md (~1,500 tokens)
|
|
89
|
+
+ shared/bug-detection.md (~800 tokens)
|
|
90
|
+
+ shared/prompt-engineering.md (~5,600 tokens)
|
|
88
91
|
─────────────────────────────────────────────────
|
|
89
|
-
≈
|
|
92
|
+
≈ 38,600 tokens total (estimated)
|
|
90
93
|
```
|
|
91
94
|
|
|
92
95
|
**Use case:** Regular coding, new features, code review. Covers 90% of daily work.
|
|
@@ -107,6 +110,7 @@ The agent reads the task, then decides which extra file to load:
|
|
|
107
110
|
| "Install this package / upgrade SDK" | `shared/version-management.md` |
|
|
108
111
|
| "Prepare for App Store / Play Store" | `shared/release-checklist.md` |
|
|
109
112
|
| "Weird issue, not sure why" | `shared/common-pitfalls.md` |
|
|
113
|
+
| "On-device AI / ML / inference" | `shared/on-device-ai.md` |
|
|
110
114
|
|
|
111
115
|
**Load cost:** +500 to +3,500 tokens per on-demand file.
|
|
112
116
|
|
|
@@ -116,7 +120,7 @@ The agent reads the task, then decides which extra file to load:
|
|
|
116
120
|
|
|
117
121
|
**No automatic trigger.** Full load happens when the AI reads every file without being selective — either because it's over-eager, or because the user explicitly asks for it.
|
|
118
122
|
|
|
119
|
-
**Total:** ~
|
|
123
|
+
**Total:** ~70,000 tokens (54.7% of 128K, 35% of 200K)
|
|
120
124
|
|
|
121
125
|
**How it actually works:**
|
|
122
126
|
- `@skill-mobile-mt` only injects SKILL.md into context
|
|
@@ -141,7 +145,7 @@ The agent reads the task, then decides which extra file to load:
|
|
|
141
145
|
```yaml
|
|
142
146
|
skill:
|
|
143
147
|
name: skill-mobile-mt
|
|
144
|
-
version: "1.
|
|
148
|
+
version: "1.4.0"
|
|
145
149
|
author: buivietphi
|
|
146
150
|
category: engineering
|
|
147
151
|
tags:
|
|
@@ -174,6 +178,7 @@ skill:
|
|
|
174
178
|
# - shared/document-analysis.md
|
|
175
179
|
# - shared/release-checklist.md
|
|
176
180
|
# - shared/common-pitfalls.md
|
|
181
|
+
# - shared/on-device-ai.md
|
|
177
182
|
|
|
178
183
|
project:
|
|
179
184
|
description: "Read current project, adapt to its framework and conventions"
|
|
@@ -208,9 +213,9 @@ skill:
|
|
|
208
213
|
java: ".java files in app/src/"
|
|
209
214
|
|
|
210
215
|
context_budget:
|
|
211
|
-
max_tokens:
|
|
212
|
-
smart_load_tokens:
|
|
213
|
-
savings: "~
|
|
216
|
+
max_tokens: 70000
|
|
217
|
+
smart_load_tokens: 38600
|
|
218
|
+
savings: "~45%"
|
|
214
219
|
```
|
|
215
220
|
|
|
216
221
|
---
|
|
@@ -256,6 +261,7 @@ Every agent MUST follow this loading sequence:
|
|
|
256
261
|
- shared/observability.md (when adding logging, analytics, crash tracking)
|
|
257
262
|
- shared/common-pitfalls.md (when encountering unfamiliar errors)
|
|
258
263
|
- shared/release-checklist.md (when preparing for App Store/Play Store submission)
|
|
264
|
+
- shared/on-device-ai.md (when adding Core ML / TFLite / on-device inference)
|
|
259
265
|
|
|
260
266
|
7. SKIP non-matching platform subfolders (saves ~66% context)
|
|
261
267
|
```
|
|
@@ -277,6 +283,7 @@ Priority 6 (ON-DEMAND): shared/observability.md — Sessions as 4th pillar
|
|
|
277
283
|
Priority 6 (ON-DEMAND): shared/document-analysis.md — Parse images/PDFs → code
|
|
278
284
|
Priority 6 (ON-DEMAND): shared/release-checklist.md — Pre-release verification
|
|
279
285
|
Priority 6 (ON-DEMAND): shared/common-pitfalls.md — Known issue patterns
|
|
286
|
+
Priority 6 (ON-DEMAND): shared/on-device-ai.md — Core ML / TFLite / llama.cpp
|
|
280
287
|
```
|
|
281
288
|
|
|
282
289
|
---
|
|
@@ -455,7 +462,7 @@ npx @buivietphi/skill-mobile-mt --init all # → all files
|
|
|
455
462
|
{
|
|
456
463
|
"id": "skill-mobile-mt",
|
|
457
464
|
"name": "skill-mobile-mt",
|
|
458
|
-
"version": "1.
|
|
465
|
+
"version": "1.4.0",
|
|
459
466
|
"author": "buivietphi",
|
|
460
467
|
"category": "engineering",
|
|
461
468
|
"description": "Master Senior Mobile Engineer. Pre-built patterns from 18 production apps + project adaptation. Auto-detects language and framework. React Native, Flutter, iOS, Android.",
|
package/README.md
CHANGED
|
@@ -209,7 +209,7 @@ The skill automatically detects before any action:
|
|
|
209
209
|
|
|
210
210
|
## Smart Loading
|
|
211
211
|
|
|
212
|
-
Only loads the relevant platform docs — saves **~
|
|
212
|
+
Only loads the relevant platform docs — saves **~45% context tokens** vs loading everything.
|
|
213
213
|
|
|
214
214
|
```
|
|
215
215
|
Flutter project?
|
|
@@ -229,22 +229,22 @@ iOS only?
|
|
|
229
229
|
|
|
230
230
|
| Scenario | Tokens | % of 128K | % of 200K |
|
|
231
231
|
|----------|-------:|----------:|----------:|
|
|
232
|
-
| SKILL.md only | ~
|
|
233
|
-
| + 1 platform + core shared/ | ~
|
|
234
|
-
| Cross-platform (RN/Flutter + iOS + Android) | ~
|
|
235
|
-
| All files loaded | ~
|
|
236
|
-
| **Smart load (recommended)** | **~
|
|
232
|
+
| SKILL.md only | ~13,200 | 10.3% | 6.6% |
|
|
233
|
+
| + 1 platform + core shared/ | ~38,600 | 30.2% | 19.3% |
|
|
234
|
+
| Cross-platform (RN/Flutter + iOS + Android) | ~53,000 | 41.4% | 26.5% |
|
|
235
|
+
| All files loaded | ~70,000 | 54.7% | 35.0% |
|
|
236
|
+
| **Smart load (recommended)** | **~38,600** | **30.2%** | **19.3%** |
|
|
237
237
|
|
|
238
238
|
### Per-file token breakdown
|
|
239
239
|
|
|
240
240
|
| File | Tokens |
|
|
241
241
|
|------|-------:|
|
|
242
242
|
| `SKILL.md` | 6,100 |
|
|
243
|
-
| `AGENTS.md` | 1,
|
|
243
|
+
| `AGENTS.md` | 1,600 |
|
|
244
244
|
| `react-native/react-native.md` | 5,108 |
|
|
245
|
-
| `flutter/flutter.md` |
|
|
245
|
+
| `flutter/flutter.md` | 2,100 |
|
|
246
246
|
| `ios/ios-native.md` | 1,452 |
|
|
247
|
-
| `android/android-native.md` |
|
|
247
|
+
| `android/android-native.md` | 2,100 |
|
|
248
248
|
| `shared/code-review.md` | 865 |
|
|
249
249
|
| `shared/bug-detection.md` | 499 |
|
|
250
250
|
| `shared/prompt-engineering.md` | 3,927 |
|
|
@@ -255,12 +255,14 @@ iOS only?
|
|
|
255
255
|
| `shared/release-checklist.md` | 587 |
|
|
256
256
|
| `shared/anti-patterns.md` | 2,800 |
|
|
257
257
|
| `shared/performance-prediction.md` | 1,500 |
|
|
258
|
-
| `shared/platform-excellence.md` |
|
|
258
|
+
| `shared/platform-excellence.md` | 2,200 |
|
|
259
259
|
| `shared/version-management.md` | 3,500 |
|
|
260
260
|
| `shared/observability.md` | 3,000 |
|
|
261
|
+
| `shared/offline-first.md` | 2,566 |
|
|
262
|
+
| `shared/on-device-ai.md` | 700 |
|
|
261
263
|
| `shared/claude-md-template.md` | ~500 |
|
|
262
264
|
| `shared/agent-rules-template.md` | ~2,500 |
|
|
263
|
-
| **Total** | **~
|
|
265
|
+
| **Total** | **~49,500** |
|
|
264
266
|
|
|
265
267
|
## Installed Structure
|
|
266
268
|
|
|
@@ -287,10 +289,12 @@ iOS only?
|
|
|
287
289
|
├── document-analysis.md Parse docs/images → code
|
|
288
290
|
├── anti-patterns.md PII, cardinality, payload detection
|
|
289
291
|
├── performance-prediction.md Frame budget, FPS prediction
|
|
290
|
-
├── platform-excellence.md iOS 18+ vs Android 15+ guidelines
|
|
292
|
+
├── platform-excellence.md iOS 18+ vs Android 15+ guidelines + HIG
|
|
291
293
|
├── version-management.md SDK compatibility matrix
|
|
292
294
|
├── observability.md Sessions as 4th pillar
|
|
293
295
|
├── release-checklist.md Pre-release verification
|
|
296
|
+
├── offline-first.md Local-first + sync patterns
|
|
297
|
+
├── on-device-ai.md Core ML / TFLite / llama.cpp
|
|
294
298
|
├── claude-md-template.md CLAUDE.md template for projects
|
|
295
299
|
└── agent-rules-template.md Rules templates for all agents
|
|
296
300
|
```
|
|
@@ -385,7 +389,8 @@ your-project/
|
|
|
385
389
|
|
|
386
390
|
- **Anti-Pattern Detection** (`anti-patterns.md`): Detect PII leaks (CRITICAL), high cardinality tags, unbounded payloads, unstructured logs, sync telemetry on main thread — with auto-fix suggestions
|
|
387
391
|
- **Performance Prediction** (`performance-prediction.md`): Calculate frame budget, FlatList bridge calls, and memory usage BEFORE writing code. Example: `50 items × 3 bridge calls × 0.3ms = 45ms/frame → 22 FPS ❌ JANK`
|
|
388
|
-
- **Platform Excellence** (`platform-excellence.md`): iOS 18+ vs Android 15+ native UX standards — navigation patterns, typography,
|
|
392
|
+
- **Platform Excellence** (`platform-excellence.md`): iOS 18+ vs Android 15+ native UX standards — navigation patterns, typography, haptic feedback types, permission timing, ratings prompt flow, Live Activities/Dynamic Island, performance targets (cold start < 1s iOS, < 1.5s Android)
|
|
393
|
+
- **On-Device AI** (`on-device-ai.md`): Decision matrix (API vs on-device), Core ML (iOS), ML Kit + MediaPipe (Android), llama.cpp cross-platform, TFLite Flutter, React Native ML Kit — with performance rules and model size guidance
|
|
389
394
|
- **Version Management** (`version-management.md`): Full SDK compatibility matrix for RN 0.73-0.76, Expo 50-52, Flutter 3.22-3.27, iOS 16-18, Android 13-15. Check SDK compat BEFORE `npm install`. Release-mode testing protocol.
|
|
390
395
|
- **Observability** (`observability.md`): Sessions as the 4th pillar (Metrics + Logs + Traces + **Sessions**). Session lifecycle, enrichment API, unified instrumentation stack, correlation queries. Every event carries `session_id` for full user journey reconstruction.
|
|
391
396
|
|
|
@@ -421,6 +426,66 @@ your-project/
|
|
|
421
426
|
| **Kiro** | Reads `.kiro/steering/` from project root | `npx skill-mobile-mt --init kiro` |
|
|
422
427
|
| **Antigravity** | Reads from `~/.agents/skills/` | `npx skill-mobile-mt --antigravity` |
|
|
423
428
|
|
|
429
|
+
## Humanizer — Mobile Copy
|
|
430
|
+
|
|
431
|
+
Installed automatically alongside the main skill. Removes AI writing patterns from mobile app text.
|
|
432
|
+
|
|
433
|
+
```
|
|
434
|
+
@humanizer-mobile
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
Use for: app store descriptions, release notes, error messages, onboarding, push notifications, permission prompts, paywall copy.
|
|
438
|
+
|
|
439
|
+
### Examples
|
|
440
|
+
|
|
441
|
+
**App Store Description**
|
|
442
|
+
```
|
|
443
|
+
❌ "TaskFlow is a powerful, comprehensive task management application that
|
|
444
|
+
seamlessly integrates with your existing workflow."
|
|
445
|
+
|
|
446
|
+
✅ "TaskFlow keeps your team's work in one place. Add tasks, assign them,
|
|
447
|
+
set deadlines — everything syncs in real time. Works with Slack and Notion."
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
**Release Notes**
|
|
451
|
+
```
|
|
452
|
+
❌ "Version 2.1.0 introduces significant enhancements to the overall user
|
|
453
|
+
experience including robust improvements to performance and reliability."
|
|
454
|
+
|
|
455
|
+
✅ "2.1.0
|
|
456
|
+
- Faster load times on older Android devices (was 4s, now 1.2s)
|
|
457
|
+
- Fixed crash when opening notifications while offline
|
|
458
|
+
- Dark mode now remembers your setting between sessions"
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
**Error Messages**
|
|
462
|
+
```
|
|
463
|
+
❌ "We apologize for the inconvenience. An unexpected error has occurred."
|
|
464
|
+
|
|
465
|
+
✅ "Couldn't save — no internet connection.
|
|
466
|
+
[Try again] [Save for later]"
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
**Push Notifications**
|
|
470
|
+
```
|
|
471
|
+
❌ "You have received a new message from a team member."
|
|
472
|
+
✅ "Alex commented on "Landing page redesign""
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
**Paywall**
|
|
476
|
+
```
|
|
477
|
+
❌ "Unlock the full potential of our comprehensive premium features."
|
|
478
|
+
|
|
479
|
+
✅ "Go Pro
|
|
480
|
+
• Unlimited projects (free plan: 3)
|
|
481
|
+
• Team sharing
|
|
482
|
+
[Start 7-day free trial]"
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
Covers 24 AI patterns across: content inflation, chatbot artifacts, style issues, mobile-specific copy (App Store limits, permission prompts, rating requests, subscription CTAs).
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
424
489
|
## License
|
|
425
490
|
|
|
426
491
|
MIT — by [buivietphi](https://github.com/buivietphi)
|
package/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: skill-mobile-mt
|
|
3
3
|
description: "Master Senior Mobile Engineer. Patterns from 30+ production repos (200k+ GitHub stars: Ignite, Expensify, Mattermost, Immich, AppFlowy, Now in Android, TCA). Use when: building mobile features, fixing mobile bugs, reviewing mobile code, mobile architecture, React Native, Flutter, iOS Swift, Android Kotlin, mobile performance, mobile security audit, mobile code review, app release. Two modes: (1) default = pre-built production patterns, (2) 'project' = reads current project and adapts."
|
|
4
|
-
version: "1.
|
|
4
|
+
version: "1.4.0"
|
|
5
5
|
author: buivietphi
|
|
6
6
|
priority: high
|
|
7
7
|
user-invocable: true
|
|
@@ -126,6 +126,13 @@ USER REQUEST → ACTION (Read tool required)
|
|
|
126
126
|
|
|
127
127
|
"Build error / runtime crash" → Read: shared/error-recovery.md
|
|
128
128
|
then: apply matching fix pattern
|
|
129
|
+
|
|
130
|
+
"Offline / cache / sync" → Read: shared/offline-first.md
|
|
131
|
+
then: implement local-first architecture
|
|
132
|
+
|
|
133
|
+
"On-device AI / ML / inference" → Read: shared/on-device-ai.md
|
|
134
|
+
then: choose Core ML / TFLite / llama.cpp per platform
|
|
135
|
+
|
|
129
136
|
```
|
|
130
137
|
|
|
131
138
|
**⛔ NEVER start coding without identifying the task type first.**
|
|
@@ -1358,9 +1365,14 @@ skill-mobile-mt/
|
|
|
1358
1365
|
├── ios/ios-native.md ← iOS Swift MVVM + Clean Architecture
|
|
1359
1366
|
├── android/android-native.md ← Android Kotlin + Clean Architecture
|
|
1360
1367
|
└── shared/
|
|
1368
|
+
│
|
|
1369
|
+
├── ── CORE (always load) ────────────────────────────────
|
|
1361
1370
|
├── code-review.md ← 🔴 Senior review checklist
|
|
1362
1371
|
├── bug-detection.md ← 🔴 Auto bug scanner
|
|
1363
|
-
├── prompt-engineering.md ←
|
|
1372
|
+
├── prompt-engineering.md ← 🔴 Auto-think templates
|
|
1373
|
+
│
|
|
1374
|
+
├── ── ON-DEMAND (load by task) ──────────────────────────
|
|
1375
|
+
├── architecture-intelligence.md ← 🟡 Patterns from 30+ production repos
|
|
1364
1376
|
├── release-checklist.md ← 🟡 Before shipping to app store
|
|
1365
1377
|
├── common-pitfalls.md ← 🟡 Problem → Symptoms → Solution
|
|
1366
1378
|
├── error-recovery.md ← 🟡 Fix build/runtime errors
|
|
@@ -1369,5 +1381,7 @@ skill-mobile-mt/
|
|
|
1369
1381
|
├── performance-prediction.md ← 🟡 Predict FPS/memory BEFORE shipping
|
|
1370
1382
|
├── platform-excellence.md ← 🟡 iOS 18+ vs Android 15+ guidelines
|
|
1371
1383
|
├── version-management.md ← 🟡 SDK compatibility matrix
|
|
1372
|
-
|
|
1384
|
+
├── observability.md ← 🟡 Sessions as 4th pillar
|
|
1385
|
+
│
|
|
1386
|
+
└── offline-first.md ← 🟢 Local-first + sync patterns
|
|
1373
1387
|
```
|
|
@@ -192,6 +192,54 @@ dependencies {
|
|
|
192
192
|
}
|
|
193
193
|
```
|
|
194
194
|
|
|
195
|
+
## Compose Performance Optimization
|
|
196
|
+
|
|
197
|
+
```kotlin
|
|
198
|
+
// @Stable / @Immutable — tell Compose when to skip recomposition
|
|
199
|
+
// Use when your class isn't a data class but values never change
|
|
200
|
+
@Stable
|
|
201
|
+
class UserState(val id: String, val name: String)
|
|
202
|
+
|
|
203
|
+
@Immutable
|
|
204
|
+
data class ProductUiModel(val id: String, val price: Double)
|
|
205
|
+
|
|
206
|
+
// derivedStateOf — compute derived state only when inputs change
|
|
207
|
+
// Prevents recomposition on every scroll position change
|
|
208
|
+
val showFab by remember {
|
|
209
|
+
derivedStateOf { listState.firstVisibleItemIndex > 0 }
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// key() in LazyColumn — stable identity prevents full recomposition
|
|
213
|
+
LazyColumn {
|
|
214
|
+
items(products, key = { it.id }) { product ->
|
|
215
|
+
ProductCard(product) // Only recomposes if THIS product changes
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Stateless components — pass data + callbacks, not ViewModel
|
|
220
|
+
@Composable
|
|
221
|
+
fun ProductCard(
|
|
222
|
+
product: Product, // data only
|
|
223
|
+
onClick: () -> Unit, // callback only
|
|
224
|
+
) { /* no ViewModel here */ }
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Baseline Profiles (Startup Optimization)
|
|
228
|
+
|
|
229
|
+
```kotlin
|
|
230
|
+
// app/src/main/baseline-prof.txt (generated by Macrobenchmark)
|
|
231
|
+
// Speeds up cold start 20-30% by AOT-compiling hot code paths
|
|
232
|
+
|
|
233
|
+
// build.gradle.kts
|
|
234
|
+
dependencies {
|
|
235
|
+
implementation("androidx.profileinstaller:profileinstaller:1.3.1")
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Generate with Macrobenchmark:
|
|
239
|
+
// ./gradlew :app:generateBaselineProfile
|
|
240
|
+
// Commit the generated baseline-prof.txt
|
|
241
|
+
```
|
|
242
|
+
|
|
195
243
|
## Common Pitfalls
|
|
196
244
|
|
|
197
245
|
| Pitfall | Fix |
|
|
@@ -201,6 +249,8 @@ dependencies {
|
|
|
201
249
|
| Context leak | `@ApplicationContext`, never Activity |
|
|
202
250
|
| Missing ProGuard | Test release builds |
|
|
203
251
|
| Main thread blocking | `Dispatchers.IO` |
|
|
252
|
+
| Unstable lambdas in Compose | `remember { {} }` or move to ViewModel |
|
|
253
|
+
| List without keys | `items(list, key = { it.id })` |
|
|
204
254
|
|
|
205
255
|
---
|
|
206
256
|
|
package/bin/install.mjs
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* npx @buivietphi/skill-mobile --init all # Generate all project-level files
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
-
import { existsSync, mkdirSync, cpSync, readFileSync, writeFileSync } from 'node:fs';
|
|
28
|
+
import { existsSync, mkdirSync, cpSync, readFileSync, writeFileSync, readdirSync } from 'node:fs';
|
|
29
29
|
import { join, resolve, dirname } from 'node:path';
|
|
30
30
|
import { homedir } from 'node:os';
|
|
31
31
|
import { fileURLToPath } from 'node:url';
|
|
@@ -38,13 +38,14 @@ const HOME = homedir();
|
|
|
38
38
|
// Structure: root files + subfolders
|
|
39
39
|
const ROOT_FILES = ['SKILL.md', 'AGENTS.md'];
|
|
40
40
|
|
|
41
|
-
const SUBFOLDERS =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
const SUBFOLDERS = ['react-native', 'flutter', 'ios', 'android', 'shared'];
|
|
42
|
+
|
|
43
|
+
// Read all .md files from a folder dynamically
|
|
44
|
+
function getMdFiles(folder) {
|
|
45
|
+
const dir = join(PKG_ROOT, folder);
|
|
46
|
+
if (!existsSync(dir)) return [];
|
|
47
|
+
return readdirSync(dir).filter(f => f.endsWith('.md'));
|
|
48
|
+
}
|
|
48
49
|
|
|
49
50
|
const AGENTS = {
|
|
50
51
|
claude: { name: 'Claude Code', dir: join(HOME, '.claude', 'skills'), detect: () => existsSync(join(HOME, '.claude')) },
|
|
@@ -69,7 +70,7 @@ const fail = m => log(` ${c.red}✗${c.reset} ${m}`);
|
|
|
69
70
|
|
|
70
71
|
function banner() {
|
|
71
72
|
log(`\n${c.bold}${c.cyan} ┌──────────────────────────────────────────────────┐`);
|
|
72
|
-
log(` │ 📱 @buivietphi/skill-mobile-mt v1.
|
|
73
|
+
log(` │ 📱 @buivietphi/skill-mobile-mt v1.4.0 │`);
|
|
73
74
|
log(` │ Master Senior Mobile Engineer │`);
|
|
74
75
|
log(` │ │`);
|
|
75
76
|
log(` │ Claude · Cline · Roo Code · Cursor · Windsurf │`);
|
|
@@ -92,9 +93,9 @@ function showContext() {
|
|
|
92
93
|
total += t;
|
|
93
94
|
log(` ${c.dim} ${f.padEnd(30)} ~${t.toLocaleString()} tokens${c.reset}`);
|
|
94
95
|
}
|
|
95
|
-
for (const
|
|
96
|
+
for (const folder of SUBFOLDERS) {
|
|
96
97
|
let ft = 0;
|
|
97
|
-
for (const f of
|
|
98
|
+
for (const f of getMdFiles(folder)) ft += tokenCount(join(PKG_ROOT, folder, f));
|
|
98
99
|
total += ft;
|
|
99
100
|
log(` ${c.dim} ${(folder + '/').padEnd(30)} ~${ft.toLocaleString()} tokens${c.reset}`);
|
|
100
101
|
}
|
|
@@ -104,6 +105,7 @@ function showContext() {
|
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
function install(baseDir, agentName) {
|
|
108
|
+
// Install main skill
|
|
107
109
|
const dst = join(baseDir, SKILL_NAME);
|
|
108
110
|
mkdirSync(dst, { recursive: true });
|
|
109
111
|
let n = 0;
|
|
@@ -113,17 +115,26 @@ function install(baseDir, agentName) {
|
|
|
113
115
|
cpSync(src, join(dst, f), { force: true });
|
|
114
116
|
n++;
|
|
115
117
|
}
|
|
116
|
-
for (const
|
|
118
|
+
for (const folder of SUBFOLDERS) {
|
|
117
119
|
const dstFolder = join(dst, folder);
|
|
118
120
|
mkdirSync(dstFolder, { recursive: true });
|
|
119
|
-
for (const f of
|
|
121
|
+
for (const f of getMdFiles(folder)) {
|
|
120
122
|
const src = join(PKG_ROOT, folder, f);
|
|
121
|
-
if (!existsSync(src)) continue;
|
|
122
123
|
cpSync(src, join(dstFolder, f), { force: true });
|
|
123
124
|
n++;
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
127
|
ok(`${c.bold}${SKILL_NAME}/${c.reset} → ${agentName} ${c.dim}(${dst})${c.reset}`);
|
|
128
|
+
|
|
129
|
+
// Auto-install humanizer-mobile as separate skill
|
|
130
|
+
const humanizerSrc = join(PKG_ROOT, 'humanizer', 'humanizer-mobile.md');
|
|
131
|
+
if (existsSync(humanizerSrc)) {
|
|
132
|
+
const humDst = join(baseDir, 'humanizer-mobile');
|
|
133
|
+
mkdirSync(humDst, { recursive: true });
|
|
134
|
+
cpSync(humanizerSrc, join(humDst, 'humanizer-mobile.md'), { force: true });
|
|
135
|
+
ok(`${c.bold}humanizer-mobile/${c.reset} → ${agentName} ${c.dim}(${humDst})${c.reset}`);
|
|
136
|
+
}
|
|
137
|
+
|
|
127
138
|
return n;
|
|
128
139
|
}
|
|
129
140
|
|
|
@@ -895,6 +906,22 @@ async function main() {
|
|
|
895
906
|
} else if (flags.has('auto')) {
|
|
896
907
|
targets = Object.keys(AGENTS).filter(k => AGENTS[k].detect());
|
|
897
908
|
if (!targets.length) { info('No agents found. Using Claude.'); targets = ['claude']; }
|
|
909
|
+
} else if (flags.has('humanizer')) {
|
|
910
|
+
// Install humanizer-mobile as a separate skill
|
|
911
|
+
const src = join(PKG_ROOT, 'humanizer', 'humanizer-mobile.md');
|
|
912
|
+
if (!existsSync(src)) { fail('humanizer/humanizer-mobile.md not found'); process.exit(1); }
|
|
913
|
+
const detected = Object.keys(AGENTS).filter(k => AGENTS[k].detect());
|
|
914
|
+
const agentKeys = detected.length ? detected : ['claude'];
|
|
915
|
+
for (const k of agentKeys) {
|
|
916
|
+
const dst = join(AGENTS[k].dir, 'humanizer-mobile');
|
|
917
|
+
mkdirSync(dst, { recursive: true });
|
|
918
|
+
cpSync(src, join(dst, 'humanizer-mobile.md'), { force: true });
|
|
919
|
+
ok(`${c.bold}humanizer-mobile/${c.reset} → ${AGENTS[k].name} ${c.dim}(${dst})${c.reset}`);
|
|
920
|
+
}
|
|
921
|
+
log(`\n${c.green}${c.bold} ✅ Done!${c.reset}\n`);
|
|
922
|
+
log(` ${c.bold}Usage:${c.reset}`);
|
|
923
|
+
log(` ${c.cyan}@humanizer-mobile${c.reset} Humanize app store copy, release notes, error messages\n`);
|
|
924
|
+
return;
|
|
898
925
|
} else if (flags.has('path')) {
|
|
899
926
|
const p = args[args.indexOf('--path') + 1];
|
|
900
927
|
if (!p) { fail('--path needs a directory'); process.exit(1); }
|
package/flutter/flutter.md
CHANGED
|
@@ -240,7 +240,65 @@ FirebaseMessaging.onMessage.listen((message) {
|
|
|
240
240
|
| Firebase | firebase_core, messaging, firestore |
|
|
241
241
|
| Image | cached_network_image |
|
|
242
242
|
|
|
243
|
+
## Dart 3.x Patterns
|
|
244
|
+
|
|
245
|
+
```dart
|
|
246
|
+
// Sealed classes — exhaustive pattern matching (replaces abstract + subclasses)
|
|
247
|
+
sealed class AuthState {}
|
|
248
|
+
class Authenticated extends AuthState { final User user; Authenticated(this.user); }
|
|
249
|
+
class Unauthenticated extends AuthState {}
|
|
250
|
+
class Loading extends AuthState {}
|
|
251
|
+
|
|
252
|
+
// Usage — compiler enforces all cases are handled
|
|
253
|
+
Widget build() => switch (authState) {
|
|
254
|
+
Authenticated(:final user) => HomeScreen(user: user),
|
|
255
|
+
Unauthenticated() => LoginScreen(),
|
|
256
|
+
Loading() => const CircularProgressIndicator(),
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
// Records — lightweight tuples with named fields (Dart 3.0)
|
|
260
|
+
(String name, int age) getUser() => ('Alice', 30);
|
|
261
|
+
final (name, age) = getUser();
|
|
262
|
+
|
|
263
|
+
// Pattern matching in if/switch
|
|
264
|
+
if (response case {'status': 'ok', 'data': final data}) {
|
|
265
|
+
processData(data);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Riverpod + sealed class = clean state
|
|
269
|
+
@riverpod
|
|
270
|
+
class AuthNotifier extends _$AuthNotifier {
|
|
271
|
+
@override
|
|
272
|
+
AuthState build() => Unauthenticated();
|
|
273
|
+
|
|
274
|
+
Future<void> login(String email, String password) async {
|
|
275
|
+
state = Loading();
|
|
276
|
+
state = switch (await _repo.login(email, password)) {
|
|
277
|
+
Ok(:final value) => Authenticated(value),
|
|
278
|
+
Err(:final error) => Unauthenticated(), // or a separate Error state
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Impeller (Flutter 3.10+)
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
Impeller is Flutter's new rendering engine — enabled by default on iOS.
|
|
288
|
+
Android: opt-in via AndroidManifest.xml
|
|
289
|
+
|
|
290
|
+
Benefits:
|
|
291
|
+
- Eliminates shader compilation jank (the "jank on first frame" problem)
|
|
292
|
+
- Consistent 60/120fps even on first run
|
|
293
|
+
|
|
294
|
+
Enable on Android:
|
|
295
|
+
<meta-data android:name="io.flutter.embedding.android.EnableImpeller" android:value="true" />
|
|
296
|
+
|
|
297
|
+
Test: flutter run --enable-impeller
|
|
298
|
+
```
|
|
299
|
+
|
|
243
300
|
---
|
|
244
301
|
|
|
245
302
|
> Standard: Riverpod + get_it/injectable + Clean Architecture.
|
|
246
303
|
> Dio/Retrofit for complex APIs. Floor for offline-first. Firebase for push/analytics.
|
|
304
|
+
> Dart 3.x: sealed classes + records for type-safe state.
|