@amorydev/antigravity-kit 1.0.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/.agent/.shared/ui-ux-pro-max/data/charts.csv +26 -0
- package/.agent/.shared/ui-ux-pro-max/data/colors.csv +97 -0
- package/.agent/.shared/ui-ux-pro-max/data/icons.csv +101 -0
- package/.agent/.shared/ui-ux-pro-max/data/landing.csv +31 -0
- package/.agent/.shared/ui-ux-pro-max/data/products.csv +97 -0
- package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +24 -0
- package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.agent/.shared/ui-ux-pro-max/data/styles.csv +59 -0
- package/.agent/.shared/ui-ux-pro-max/data/typography.csv +58 -0
- package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/core.py +258 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +487 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/search.py +76 -0
- package/.agent/ARCHITECTURE.md +225 -0
- package/.agent/agents/backend-specialist.md +263 -0
- package/.agent/agents/database-architect.md +226 -0
- package/.agent/agents/debugger.md +225 -0
- package/.agent/agents/devops-engineer.md +242 -0
- package/.agent/agents/documentation-writer.md +104 -0
- package/.agent/agents/explorer-agent.md +73 -0
- package/.agent/agents/frontend-specialist.md +527 -0
- package/.agent/agents/game-developer.md +162 -0
- package/.agent/agents/mobile-developer.md +1126 -0
- package/.agent/agents/orchestrator.md +400 -0
- package/.agent/agents/penetration-tester.md +188 -0
- package/.agent/agents/performance-optimizer.md +187 -0
- package/.agent/agents/project-planner.md +403 -0
- package/.agent/agents/security-auditor.md +170 -0
- package/.agent/agents/seo-specialist.md +111 -0
- package/.agent/agents/test-engineer.md +158 -0
- package/.agent/rules/GEMINI.md +252 -0
- package/.agent/skills/api-patterns/SKILL.md +81 -0
- package/.agent/skills/api-patterns/api-style.md +42 -0
- package/.agent/skills/api-patterns/auth.md +24 -0
- package/.agent/skills/api-patterns/documentation.md +26 -0
- package/.agent/skills/api-patterns/graphql.md +41 -0
- package/.agent/skills/api-patterns/rate-limiting.md +31 -0
- package/.agent/skills/api-patterns/response.md +37 -0
- package/.agent/skills/api-patterns/rest.md +40 -0
- package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
- package/.agent/skills/api-patterns/security-testing.md +122 -0
- package/.agent/skills/api-patterns/trpc.md +41 -0
- package/.agent/skills/api-patterns/versioning.md +22 -0
- package/.agent/skills/app-builder/SKILL.md +75 -0
- package/.agent/skills/app-builder/agent-coordination.md +71 -0
- package/.agent/skills/app-builder/feature-building.md +53 -0
- package/.agent/skills/app-builder/project-detection.md +34 -0
- package/.agent/skills/app-builder/scaffolding.md +118 -0
- package/.agent/skills/app-builder/tech-stack.md +40 -0
- package/.agent/skills/app-builder/templates/SKILL.md +39 -0
- package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
- package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
- package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +82 -0
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +100 -0
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +106 -0
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +101 -0
- package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +93 -0
- package/.agent/skills/architecture/SKILL.md +55 -0
- package/.agent/skills/architecture/context-discovery.md +43 -0
- package/.agent/skills/architecture/examples.md +94 -0
- package/.agent/skills/architecture/pattern-selection.md +68 -0
- package/.agent/skills/architecture/patterns-reference.md +50 -0
- package/.agent/skills/architecture/trade-off-analysis.md +77 -0
- package/.agent/skills/bash-linux/SKILL.md +199 -0
- package/.agent/skills/behavioral-modes/SKILL.md +242 -0
- package/.agent/skills/brainstorming/SKILL.md +163 -0
- package/.agent/skills/brainstorming/dynamic-questioning.md +350 -0
- package/.agent/skills/clean-code/SKILL.md +201 -0
- package/.agent/skills/code-review-checklist/SKILL.md +109 -0
- package/.agent/skills/database-design/SKILL.md +52 -0
- package/.agent/skills/database-design/database-selection.md +43 -0
- package/.agent/skills/database-design/indexing.md +39 -0
- package/.agent/skills/database-design/migrations.md +48 -0
- package/.agent/skills/database-design/optimization.md +36 -0
- package/.agent/skills/database-design/orm-selection.md +30 -0
- package/.agent/skills/database-design/schema-design.md +56 -0
- package/.agent/skills/database-design/scripts/schema_validator.py +172 -0
- package/.agent/skills/deployment-procedures/SKILL.md +241 -0
- package/.agent/skills/doc.md +177 -0
- package/.agent/skills/docker-expert/SKILL.md +409 -0
- package/.agent/skills/documentation-templates/SKILL.md +194 -0
- package/.agent/skills/frontend-design/SKILL.md +396 -0
- package/.agent/skills/frontend-design/animation-guide.md +331 -0
- package/.agent/skills/frontend-design/color-system.md +311 -0
- package/.agent/skills/frontend-design/decision-trees.md +418 -0
- package/.agent/skills/frontend-design/motion-graphics.md +306 -0
- package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
- package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
- package/.agent/skills/frontend-design/typography-system.md +345 -0
- package/.agent/skills/frontend-design/ux-psychology.md +541 -0
- package/.agent/skills/frontend-design/visual-effects.md +383 -0
- package/.agent/skills/game-development/2d-games/SKILL.md +119 -0
- package/.agent/skills/game-development/3d-games/SKILL.md +135 -0
- package/.agent/skills/game-development/SKILL.md +167 -0
- package/.agent/skills/game-development/game-art/SKILL.md +185 -0
- package/.agent/skills/game-development/game-audio/SKILL.md +190 -0
- package/.agent/skills/game-development/game-design/SKILL.md +129 -0
- package/.agent/skills/game-development/mobile-games/SKILL.md +108 -0
- package/.agent/skills/game-development/multiplayer/SKILL.md +132 -0
- package/.agent/skills/game-development/pc-games/SKILL.md +144 -0
- package/.agent/skills/game-development/vr-ar/SKILL.md +123 -0
- package/.agent/skills/game-development/web-games/SKILL.md +150 -0
- package/.agent/skills/geo-fundamentals/SKILL.md +156 -0
- package/.agent/skills/geo-fundamentals/scripts/geo_checker.py +289 -0
- package/.agent/skills/i18n-localization/SKILL.md +154 -0
- package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
- package/.agent/skills/lint-and-validate/SKILL.md +45 -0
- package/.agent/skills/lint-and-validate/scripts/lint_runner.py +172 -0
- package/.agent/skills/lint-and-validate/scripts/type_coverage.py +173 -0
- package/.agent/skills/mcp-builder/SKILL.md +176 -0
- package/.agent/skills/mobile-design/SKILL.md +937 -0
- package/.agent/skills/mobile-design/decision-trees.md +516 -0
- package/.agent/skills/mobile-design/mobile-backend.md +491 -0
- package/.agent/skills/mobile-design/mobile-color-system.md +420 -0
- package/.agent/skills/mobile-design/mobile-debugging.md +122 -0
- package/.agent/skills/mobile-design/mobile-design-thinking.md +598 -0
- package/.agent/skills/mobile-design/mobile-navigation.md +458 -0
- package/.agent/skills/mobile-design/mobile-performance.md +1050 -0
- package/.agent/skills/mobile-design/mobile-testing.md +356 -0
- package/.agent/skills/mobile-design/mobile-typography.md +433 -0
- package/.agent/skills/mobile-design/platform-android.md +666 -0
- package/.agent/skills/mobile-design/platform-ios.md +561 -0
- package/.agent/skills/mobile-design/platform-kmp.md +770 -0
- package/.agent/skills/mobile-design/scripts/mobile_audit.py +670 -0
- package/.agent/skills/mobile-design/touch-psychology.md +537 -0
- package/.agent/skills/nestjs-expert/SKILL.md +552 -0
- package/.agent/skills/nextjs-best-practices/SKILL.md +203 -0
- package/.agent/skills/nodejs-best-practices/SKILL.md +333 -0
- package/.agent/skills/parallel-agents/SKILL.md +175 -0
- package/.agent/skills/performance-profiling/SKILL.md +143 -0
- package/.agent/skills/performance-profiling/scripts/lighthouse_audit.py +76 -0
- package/.agent/skills/plan-writing/SKILL.md +152 -0
- package/.agent/skills/powershell-windows/SKILL.md +167 -0
- package/.agent/skills/prisma-expert/SKILL.md +355 -0
- package/.agent/skills/python-patterns/SKILL.md +441 -0
- package/.agent/skills/react-patterns/SKILL.md +198 -0
- package/.agent/skills/red-team-tactics/SKILL.md +199 -0
- package/.agent/skills/seo-fundamentals/SKILL.md +129 -0
- package/.agent/skills/seo-fundamentals/scripts/seo_checker.py +219 -0
- package/.agent/skills/server-management/SKILL.md +161 -0
- package/.agent/skills/systematic-debugging/SKILL.md +109 -0
- package/.agent/skills/tailwind-patterns/SKILL.md +269 -0
- package/.agent/skills/tdd-workflow/SKILL.md +149 -0
- package/.agent/skills/testing-patterns/SKILL.md +178 -0
- package/.agent/skills/testing-patterns/scripts/test_runner.py +219 -0
- package/.agent/skills/typescript-expert/SKILL.md +429 -0
- package/.agent/skills/typescript-expert/references/tsconfig-strict.json +92 -0
- package/.agent/skills/typescript-expert/references/typescript-cheatsheet.md +383 -0
- package/.agent/skills/typescript-expert/references/utility-types.ts +335 -0
- package/.agent/skills/typescript-expert/scripts/ts_diagnostic.py +203 -0
- package/.agent/skills/ui-ux-pro-max/SKILL.md +351 -0
- package/.agent/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/.agent/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/.agent/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/.agent/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/.agent/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/.agent/skills/ui-ux-pro-max/data/prompts.csv +24 -0
- package/.agent/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.agent/skills/ui-ux-pro-max/data/styles.csv +59 -0
- package/.agent/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/.agent/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/.agent/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.agent/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/.agent/skills/ui-ux-pro-max/scripts/core.py +257 -0
- package/.agent/skills/ui-ux-pro-max/scripts/design_system.py +487 -0
- package/.agent/skills/ui-ux-pro-max/scripts/search.py +76 -0
- package/.agent/skills/vulnerability-scanner/SKILL.md +276 -0
- package/.agent/skills/vulnerability-scanner/checklists.md +121 -0
- package/.agent/skills/vulnerability-scanner/scripts/security_scan.py +458 -0
- package/.agent/skills/webapp-testing/SKILL.md +187 -0
- package/.agent/skills/webapp-testing/scripts/playwright_runner.py +173 -0
- package/.agent/workflows/brainstorm.md +113 -0
- package/.agent/workflows/create.md +59 -0
- package/.agent/workflows/debug.md +103 -0
- package/.agent/workflows/deploy.md +176 -0
- package/.agent/workflows/enhance.md +63 -0
- package/.agent/workflows/orchestrate.md +237 -0
- package/.agent/workflows/plan.md +89 -0
- package/.agent/workflows/preview.md +80 -0
- package/.agent/workflows/status.md +86 -0
- package/.agent/workflows/test.md +144 -0
- package/.agent/workflows/ui-ux-pro-max.md +231 -0
- package/LICENSE +21 -0
- package/README.md +120 -0
- package/bin/cli.js +81 -0
- package/package.json +29 -0
|
@@ -0,0 +1,937 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mobile-design
|
|
3
|
+
description: Mobile-first design thinking and decision-making for iOS and Android apps. Touch interaction, performance patterns, platform conventions. Teaches principles, not fixed values. Use when building React Native, Flutter, or native mobile apps.
|
|
4
|
+
allowed-tools: Read, Glob, Grep, Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Mobile Design System
|
|
8
|
+
|
|
9
|
+
> **Philosophy:** Touch-first. Battery-conscious. Platform-respectful. Offline-capable.
|
|
10
|
+
> **Core Principle:** Mobile is NOT a small desktop. THINK mobile constraints, ASK platform choice.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 🔧 Runtime Scripts
|
|
15
|
+
|
|
16
|
+
**Execute these for validation (don't read, just run):**
|
|
17
|
+
|
|
18
|
+
| Script | Purpose | Usage |
|
|
19
|
+
|--------|---------|-------|
|
|
20
|
+
| `scripts/mobile_audit.py` | Mobile UX & Touch Audit | `python scripts/mobile_audit.py <project_path>` |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 🔴 MANDATORY: Read Reference Files Before Working!
|
|
25
|
+
|
|
26
|
+
**⛔ DO NOT start development until you read the relevant files:**
|
|
27
|
+
|
|
28
|
+
### Universal (Always Read)
|
|
29
|
+
|
|
30
|
+
| File | Content | Status |
|
|
31
|
+
|------|---------|--------|
|
|
32
|
+
| **[mobile-design-thinking.md](mobile-design-thinking.md)** | **⚠️ ANTI-MEMORIZATION: Forces thinking, prevents AI defaults** | **⬜ CRITICAL FIRST** |
|
|
33
|
+
| **[touch-psychology.md](touch-psychology.md)** | **Fitts' Law, gestures, haptics, thumb zone** | **⬜ CRITICAL** |
|
|
34
|
+
| **[mobile-performance.md](mobile-performance.md)** | **RN/Flutter performance, 60fps, memory** | **⬜ CRITICAL** |
|
|
35
|
+
| **[mobile-backend.md](mobile-backend.md)** | **Push notifications, offline sync, mobile API** | **⬜ CRITICAL** |
|
|
36
|
+
| **[mobile-testing.md](mobile-testing.md)** | **Testing pyramid, E2E, platform-specific** | **⬜ CRITICAL** |
|
|
37
|
+
| **[mobile-debugging.md](mobile-debugging.md)** | **Native vs JS debugging, Flipper, Logcat** | **⬜ CRITICAL** |
|
|
38
|
+
| [mobile-navigation.md](mobile-navigation.md) | Tab/Stack/Drawer, deep linking | ⬜ Read |
|
|
39
|
+
| [mobile-typography.md](mobile-typography.md) | System fonts, Dynamic Type, a11y | ⬜ Read |
|
|
40
|
+
| [mobile-color-system.md](mobile-color-system.md) | OLED, dark mode, battery-aware | ⬜ Read |
|
|
41
|
+
| [decision-trees.md](decision-trees.md) | Framework/state/storage selection | ⬜ Read |
|
|
42
|
+
|
|
43
|
+
> 🧠 **mobile-design-thinking.md is PRIORITY!** This file ensures AI thinks instead of using memorized patterns.
|
|
44
|
+
|
|
45
|
+
### Platform-Specific (Read Based on Target)
|
|
46
|
+
|
|
47
|
+
| Platform | File | Content | When to Read |
|
|
48
|
+
|----------|------|---------|--------------|
|
|
49
|
+
| **iOS** | [platform-ios.md](../skills/mobile-design/platform-ios.md) | Building for iPhone/iPad |
|
|
50
|
+
| **Android** | [platform-android.md](../skills/mobile-design/platform-android.md) | Building for Android |
|
|
51
|
+
| **Kotlin Multiplatform** | [platform-kmp.md](../skills/mobile-design/platform-kmp.md) | **Shared logic, expect/actual, iOS integration, Compose Multiplatform** | **Building with KMP** |
|
|
52
|
+
| **Cross-Platform** | All relevant above | Platform divergence points | React Native / Flutter / KMP |
|
|
53
|
+
|
|
54
|
+
> 🔴 **If building with KMP → Read platform-kmp.md FIRST!**
|
|
55
|
+
> 🔴 **KMP + iOS UI → Read platform-kmp.md + platform-ios.md**
|
|
56
|
+
> 🔴 **KMP + Android UI → Read platform-kmp.md + platform-android.md**
|
|
57
|
+
> 🔴 **Compose Multiplatform → Read platform-kmp.md + both platform files**
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## ⚠️ CRITICAL: ASK BEFORE ASSUMING (MANDATORY)
|
|
62
|
+
|
|
63
|
+
> **STOP! If the user's request is open-ended, DO NOT default to your favorites.**
|
|
64
|
+
> **ALWAYS ask these questions FIRST before generating any code.**
|
|
65
|
+
|
|
66
|
+
### Core Decisions (MUST Ask If Not Specified)
|
|
67
|
+
|
|
68
|
+
| Aspect | Question | Why | Follow-up Considerations |
|
|
69
|
+
|--------|----------|-----|-------------------------|
|
|
70
|
+
| **Platform** | "iOS, Android, or both?" | Affects EVERY design decision | - iOS minimum version (14+, 15+)? <br>- Android API level (21+, 24+)? <br>- Platform-specific features needed? |
|
|
71
|
+
| **Framework** | "React Native, Flutter, Kotlin Multiplatform, or native?" | Determines patterns and tools | - Team expertise? <br>- Performance requirements? <br>- Code sharing vs platform optimization? |
|
|
72
|
+
| **Navigation** | "Tab bar, drawer, or stack-based?" | Core UX decision | - Deep linking needed? <br>- Nested navigation? <br>- Modal flows? |
|
|
73
|
+
| **State** | "What state management?" <br>(Zustand/Redux/Riverpod/BLoC/MobX) | Architecture foundation | - Global vs local state split? <br>- Persistence needed? <br>- DevTools requirements? |
|
|
74
|
+
| **Offline** | "Does this need to work offline?" | Affects data strategy | - Full offline mode or just caching? <br>- Conflict resolution strategy? <br>- Background sync? |
|
|
75
|
+
| **Target devices** | "Phone only, or tablet support?" | Layout complexity | - Foldables? <br>- Landscape orientation? <br>- Responsive breakpoints? |
|
|
76
|
+
|
|
77
|
+
### Additional Critical Questions (Ask When Relevant)
|
|
78
|
+
|
|
79
|
+
| Aspect | Question | Why | Impact |
|
|
80
|
+
|--------|----------|-----|--------|
|
|
81
|
+
| **Authentication** | "What auth method?" <br>(OAuth, biometrics, SSO) | Security & UX baseline | Affects onboarding, session management, keychain usage |
|
|
82
|
+
| **API Integration** | "REST, GraphQL, or gRPC?" | Data layer architecture | Determines networking library, caching strategy, type generation |
|
|
83
|
+
| **Analytics** | "What tracking is needed?" | User insights & debugging | Firebase, Mixpanel, custom? GDPR compliance? |
|
|
84
|
+
| **Push Notifications** | "Local, remote, or both?" | Engagement strategy | FCM/APNs setup, notification permissions flow |
|
|
85
|
+
| **Payments** | "In-app purchases or external?" | Revenue model | App Store/Play Store policies, payment provider integration |
|
|
86
|
+
| **Media** | "Camera, photos, video?" | Native permissions needed | Storage strategy, compression, upload handling |
|
|
87
|
+
| **Location** | "Background tracking or on-demand?" | Battery & privacy impact | Permission strategy (always/when-in-use), geofencing |
|
|
88
|
+
| **Theme** | "Light/dark mode support?" | Modern UX expectation | Color system, system preference detection |
|
|
89
|
+
| **Internationalization** | "Multi-language support?" | Global reach | RTL support, locale management, date/number formatting |
|
|
90
|
+
| **Testing** | "Unit, integration, E2E?" | Quality assurance | Detox/Appium for E2E, testing strategy, CI/CD pipeline |
|
|
91
|
+
|
|
92
|
+
### Framework-Specific Questions
|
|
93
|
+
|
|
94
|
+
#### React Native
|
|
95
|
+
- "Expo or bare workflow?"
|
|
96
|
+
- "New Architecture (Fabric/TurboModules)?"
|
|
97
|
+
- "Monorepo setup?"
|
|
98
|
+
- "TypeScript or JavaScript?"
|
|
99
|
+
|
|
100
|
+
#### Flutter
|
|
101
|
+
- "Material or Cupertino design?"
|
|
102
|
+
- "Code generation (freezed/json_serializable)?"
|
|
103
|
+
- "Platform channels needed?"
|
|
104
|
+
- "State: BLoC, Provider, Riverpod, or GetX?"
|
|
105
|
+
|
|
106
|
+
#### Kotlin Multiplatform
|
|
107
|
+
- "iOS framework type (static/dynamic)?"
|
|
108
|
+
- "Shared UI or logic only?"
|
|
109
|
+
- "Compose Multiplatform for UI?"
|
|
110
|
+
- "Ktor or other networking?"
|
|
111
|
+
|
|
112
|
+
#### Native (Jetpack Compose)
|
|
113
|
+
- "Single Activity or multi-Activity?"
|
|
114
|
+
- "ViewModel scoping strategy?"
|
|
115
|
+
- "Modularization approach?"
|
|
116
|
+
- "Hilt or Koin for DI?"
|
|
117
|
+
|
|
118
|
+
### ⛔ DEFAULT TENDENCIES TO AVOID:
|
|
119
|
+
|
|
120
|
+
| AI Default Tendency | Why It's Bad | Think Instead |
|
|
121
|
+
|---------------------|--------------|---------------|
|
|
122
|
+
| **ScrollView for lists** | Memory explosion | Is this a list? → FlatList |
|
|
123
|
+
| **Inline renderItem** | Re-renders all items | Am I memoizing renderItem? |
|
|
124
|
+
| **AsyncStorage for tokens** | Insecure | Is this sensitive? → SecureStore |
|
|
125
|
+
| **Same stack for all projects** | Doesn't fit context | What does THIS project need? |
|
|
126
|
+
| **Skipping platform checks** | Feels broken to users | iOS = iOS feel, Android = Android feel |
|
|
127
|
+
| **Redux for simple apps** | Overkill | Is Zustand enough? |
|
|
128
|
+
| **Ignoring thumb zone** | Hard to use one-handed | Where is the primary CTA? |
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 🚫 MOBILE ANTI-PATTERNS (NEVER DO THESE!)
|
|
133
|
+
|
|
134
|
+
> **If you catch yourself doing ANY of these, STOP and refactor immediately.**
|
|
135
|
+
|
|
136
|
+
### Performance Sins
|
|
137
|
+
|
|
138
|
+
| ❌ NEVER | ✅ ALWAYS | Why |
|
|
139
|
+
|----------|----------|-----|
|
|
140
|
+
| `ScrollView` for lists | `FlatList` / `FlashList` / `ListView.builder` | ScrollView renders ALL items at once (OOM crash) |
|
|
141
|
+
| Inline `renderItem` function | `useCallback` + `React.memo` | Causes re-render of entire list on state change |
|
|
142
|
+
| Missing `keyExtractor` | Stable unique ID from data | Without it, React can't optimize rerenders |
|
|
143
|
+
| `useNativeDriver: false` | `useNativeDriver: true` (when possible) | JS thread animations drop frames at 60fps |
|
|
144
|
+
| `console.log` in production | Remove before release | Massive performance impact on devices |
|
|
145
|
+
| Heavy computation in render | `useMemo` / `useEffect` / background thread | Blocks UI thread → janky scrolling |
|
|
146
|
+
| `setState()` for everything (Flutter) | Targeted state, `const` constructors | Rebuilds entire widget tree unnecessarily |
|
|
147
|
+
| Deep widget trees | Extract widgets, use `const` | Flutter: Every level adds layout cost |
|
|
148
|
+
| Large images without sizing | `resizeMode`, compression, CDN | Loads full resolution → memory spike |
|
|
149
|
+
| Unoptimized re-renders | `React.memo`, `shouldComponentUpdate`, `key` | Wasted CPU cycles on unchanged components |
|
|
150
|
+
|
|
151
|
+
### Touch/UX Sins
|
|
152
|
+
|
|
153
|
+
| ❌ NEVER | ✅ ALWAYS | Why |
|
|
154
|
+
|----------|----------|-----|
|
|
155
|
+
| Touch target < 44px | Minimum 44pt (iOS) / 48dp (Android) | Accessibility + fat-finger errors |
|
|
156
|
+
| Spacing < 8px | Minimum 8-12px gap | Cramped UI, accidental taps |
|
|
157
|
+
| Gesture-only navigation | Provide visible button alternative | Discoverability + accessibility |
|
|
158
|
+
| No loading state | ALWAYS show skeleton/spinner | Users think app froze |
|
|
159
|
+
| No error state | Show error with retry option | Dead ends frustrate users |
|
|
160
|
+
| No offline handling | Graceful degradation, cached data | Apps crash when network drops |
|
|
161
|
+
| Platform-inconsistent UI | Follow HIG (iOS) / Material (Android) | Users notice "wrong" patterns instantly |
|
|
162
|
+
| Blocking main thread | Async operations, background threads | App freezes → ANR (Android) / watchdog (iOS) |
|
|
163
|
+
| No empty states | Show helpful message + action | Blank screens confuse users |
|
|
164
|
+
| Missing ripple/haptic feedback | Provide tactile response | Feels unresponsive without it |
|
|
165
|
+
|
|
166
|
+
### Security Sins
|
|
167
|
+
|
|
168
|
+
| ❌ NEVER | ✅ ALWAYS | Why |
|
|
169
|
+
|----------|----------|-----|
|
|
170
|
+
| Token in `AsyncStorage` | `SecureStore` (Expo) / `Keychain` (iOS) / `EncryptedSharedPreferences` (Android) | AsyncStorage is plaintext, easily extractable |
|
|
171
|
+
| Hardcode API keys | Environment variables (`.env`) | Keys leak in version control |
|
|
172
|
+
| Skip SSL pinning | Pin certificates in production | Prevents MITM attacks |
|
|
173
|
+
| Log sensitive data | Never log tokens, passwords, PII | Logs persist on device, visible in crash reports |
|
|
174
|
+
| Trust user input | Validate + sanitize everything | SQL injection, XSS in WebViews |
|
|
175
|
+
| Store passwords | Use OAuth / biometrics | Password managers exist for a reason |
|
|
176
|
+
| HTTP in production | HTTPS only + ATS (iOS) / cleartext off (Android) | Network traffic visible on public WiFi |
|
|
177
|
+
| Ignore permissions | Request at point of use, explain why | Users deny "creepy" permission requests |
|
|
178
|
+
|
|
179
|
+
### Navigation Sins
|
|
180
|
+
|
|
181
|
+
| ❌ NEVER | ✅ ALWAYS | Why |
|
|
182
|
+
|----------|----------|-----|
|
|
183
|
+
| Nested navigators without planning | Flat structure when possible | Navigation state becomes unpredictable |
|
|
184
|
+
| `navigate()` without checking state | Use `navigation.canGoBack()` | App crashes on back press |
|
|
185
|
+
| Passing large objects in params | Pass IDs, fetch in destination | Route params serialized → perf hit |
|
|
186
|
+
| No deep linking setup | Configure universal links + URL schemes | Can't link to specific screens |
|
|
187
|
+
| Ignoring back button (Android) | Handle `BackHandler` | Breaks user expectations |
|
|
188
|
+
| Tab bar + drawer together | Pick one primary navigation | Confusing UX, conflicts |
|
|
189
|
+
|
|
190
|
+
### State Management Sins
|
|
191
|
+
|
|
192
|
+
| ❌ NEVER | ✅ ALWAYS | Why |
|
|
193
|
+
|----------|----------|-----|
|
|
194
|
+
| Global state for everything | Local state by default, lift when needed | Unnecessary re-renders across app |
|
|
195
|
+
| Prop drilling 5+ levels | Context / state management library | Unmaintainable, fragile |
|
|
196
|
+
| Mutating state directly | Immutable updates (`...spread`, `produce`) | React/Flutter can't detect changes |
|
|
197
|
+
| No state persistence | Save critical state (auth, cart) | User loses progress on app kill |
|
|
198
|
+
| Using Context for high-frequency updates | Zustand / Redux / Riverpod | Context re-renders all consumers |
|
|
199
|
+
| Forgetting to cleanup | `useEffect` return, `dispose()` | Memory leaks, subscriptions pile up |
|
|
200
|
+
|
|
201
|
+
### API/Data Sins
|
|
202
|
+
|
|
203
|
+
| ❌ NEVER | ✅ ALWAYS | Why |
|
|
204
|
+
|----------|----------|-----|
|
|
205
|
+
| No request timeout | Set timeout (10-30s) | Hangs forever on poor connection |
|
|
206
|
+
| No retry logic | Exponential backoff + max retries | Temporary failures shouldn't kill UX |
|
|
207
|
+
| Fetch on every render | Cache, debounce, or React Query | Hammers API, wastes data |
|
|
208
|
+
| No pagination | Lazy load, infinite scroll | Loading 10k items crashes app |
|
|
209
|
+
| Ignoring HTTP status codes | Handle 401, 403, 429, 500+ | Silent failures confuse users |
|
|
210
|
+
| Trusting API response shape | Validate with Zod / type guards | Runtime errors from API changes |
|
|
211
|
+
| No offline-first strategy | Cache data, sync when online | Apps feel broken without internet |
|
|
212
|
+
|
|
213
|
+
### Build/Deployment Sins
|
|
214
|
+
|
|
215
|
+
| ❌ NEVER | ✅ ALWAYS | Why |
|
|
216
|
+
|----------|----------|-----|
|
|
217
|
+
| Commit secrets | `.gitignore` sensitive files | Leaked on GitHub → security breach |
|
|
218
|
+
| Skip version bumping | Increment `versionCode` / `CFBundleVersion` | Can't deploy without it |
|
|
219
|
+
| No crash reporting | Sentry, Crashlytics, Bugsnag | You won't know why users crash |
|
|
220
|
+
| No analytics | Firebase, Mixpanel, Amplitude | Flying blind on user behavior |
|
|
221
|
+
| Test only on emulator | Test on real devices | Emulators hide performance issues |
|
|
222
|
+
| Ignore store guidelines | Read App Store / Play Store policies | Rejection delays launch by weeks |
|
|
223
|
+
| No staged rollout | Gradual rollout (10% → 50% → 100%) | Catch critical bugs before full release |
|
|
224
|
+
|
|
225
|
+
### React Native Specific
|
|
226
|
+
|
|
227
|
+
| ❌ NEVER | ✅ ALWAYS | Why |
|
|
228
|
+
|----------|----------|-----|
|
|
229
|
+
| Old React Navigation version | Stay on latest stable | Breaking changes pile up |
|
|
230
|
+
| Ignoring new architecture | Plan migration to Fabric/TurboModules | Old arch deprecated soon |
|
|
231
|
+
| Massive bundle size | Code splitting, lazy loading | Slow startup, app store limits |
|
|
232
|
+
| `react-native-vector-icons` without linking | Use Expo vector-icons or link properly | Icons don't show |
|
|
233
|
+
|
|
234
|
+
### Flutter Specific
|
|
235
|
+
|
|
236
|
+
| ❌ NEVER | ✅ ALWAYS | Why |
|
|
237
|
+
|----------|----------|-----|
|
|
238
|
+
| `setState()` in StatelessWidget | Use StatefulWidget or state management | Runtime error |
|
|
239
|
+
| Not using `const` constructors | Mark immutable widgets `const` | Rebuild optimizations |
|
|
240
|
+
| Rebuilding entire screen | `Consumer` / `Selector` for targeted updates | Wastes CPU |
|
|
241
|
+
| Ignoring widget lifecycle | `initState`, `dispose` correctly | Memory leaks, stale state |
|
|
242
|
+
|
|
243
|
+
### Jetpack Compose Specific
|
|
244
|
+
|
|
245
|
+
| ❌ NEVER | ✅ ALWAYS | Why |
|
|
246
|
+
|----------|----------|-----|
|
|
247
|
+
| Side effects in composition | Use `LaunchedEffect`, `DisposableEffect` | Unpredictable behavior |
|
|
248
|
+
| Mutable state without `remember` | `remember { mutableStateOf() }` | State lost on recomposition |
|
|
249
|
+
| Heavy work in `@Composable` | Move to ViewModel / coroutine | Janky UI |
|
|
250
|
+
| Not using `derivedStateOf` | Derive computed values properly | Unnecessary recompositions |
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## 📱 Platform Decision Matrix
|
|
255
|
+
|
|
256
|
+
### When to Unify vs Diverge
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
UNIFY (same on both) DIVERGE (platform-specific)
|
|
260
|
+
─────────────────── ──────────────────────────
|
|
261
|
+
Business Logic ✅ Always -
|
|
262
|
+
Data Layer ✅ Always -
|
|
263
|
+
Core Features ✅ Always -
|
|
264
|
+
|
|
265
|
+
Navigation - ✅ iOS: edge swipe, Android: back button
|
|
266
|
+
Gestures - ✅ Platform-native feel
|
|
267
|
+
Icons - ✅ SF Symbols vs Material Icons
|
|
268
|
+
Date Pickers - ✅ Native pickers feel right
|
|
269
|
+
Modals/Sheets - ✅ iOS: bottom sheet vs Android: dialog
|
|
270
|
+
Typography - ✅ SF Pro vs Roboto (or custom)
|
|
271
|
+
Error Dialogs - ✅ Platform conventions for alerts
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Quick Reference: Platform Defaults
|
|
275
|
+
|
|
276
|
+
| Element | iOS | Android |
|
|
277
|
+
|---------|-----|---------|
|
|
278
|
+
| **Primary Font** | SF Pro / SF Compact | Roboto |
|
|
279
|
+
| **Min Touch Target** | 44pt × 44pt | 48dp × 48dp |
|
|
280
|
+
| **Back Navigation** | Edge swipe left | System back button/gesture |
|
|
281
|
+
| **Bottom Tab Icons** | SF Symbols | Material Symbols |
|
|
282
|
+
| **Action Sheet** | UIActionSheet from bottom | Bottom Sheet / Dialog |
|
|
283
|
+
| **Progress** | Spinner | Linear progress (Material) |
|
|
284
|
+
| **Pull to Refresh** | Native UIRefreshControl | SwipeRefreshLayout |
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## 🧠 Mobile UX Psychology (Quick Reference)
|
|
289
|
+
|
|
290
|
+
### Fitts' Law for Touch
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
Desktop: Cursor is precise (1px)
|
|
294
|
+
Mobile: Finger is imprecise (~7mm contact area)
|
|
295
|
+
|
|
296
|
+
→ Touch targets MUST be 44-48px minimum
|
|
297
|
+
→ Important actions in THUMB ZONE (bottom of screen)
|
|
298
|
+
→ Destructive actions AWAY from easy reach
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Thumb Zone (One-Handed Usage)
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
┌─────────────────────────────┐
|
|
305
|
+
│ HARD TO REACH │ ← Navigation, menu, back
|
|
306
|
+
│ (stretch) │
|
|
307
|
+
├─────────────────────────────┤
|
|
308
|
+
│ OK TO REACH │ ← Secondary actions
|
|
309
|
+
│ (natural) │
|
|
310
|
+
├─────────────────────────────┤
|
|
311
|
+
│ EASY TO REACH │ ← PRIMARY CTAs, tab bar
|
|
312
|
+
│ (thumb's natural arc) │ ← Main content interaction
|
|
313
|
+
└─────────────────────────────┘
|
|
314
|
+
[ HOME ]
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Mobile-Specific Cognitive Load
|
|
318
|
+
|
|
319
|
+
| Desktop | Mobile Difference |
|
|
320
|
+
|---------|-------------------|
|
|
321
|
+
| Multiple windows | ONE task at a time |
|
|
322
|
+
| Keyboard shortcuts | Touch gestures |
|
|
323
|
+
| Hover states | NO hover (tap or nothing) |
|
|
324
|
+
| Large viewport | Limited space, scroll vertical |
|
|
325
|
+
| Stable attention | Interrupted constantly |
|
|
326
|
+
|
|
327
|
+
For deep dive: [touch-psychology.md](touch-psychology.md)
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## ⚡ Performance Principles (Quick Reference)
|
|
332
|
+
|
|
333
|
+
### React Native Critical Rules
|
|
334
|
+
```typescript
|
|
335
|
+
// ✅ CORRECT: Memoized renderItem + React.memo wrapper
|
|
336
|
+
const ListItem = React.memo(({ item }: { item: Item }) => (
|
|
337
|
+
<View style={styles.item}>
|
|
338
|
+
<Text>{item.title}</Text>
|
|
339
|
+
</View>
|
|
340
|
+
));
|
|
341
|
+
|
|
342
|
+
const renderItem = useCallback(
|
|
343
|
+
({ item }: { item: Item }) => <ListItem item={item} />,
|
|
344
|
+
[]
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
// ✅ CORRECT: FlatList with all optimizations
|
|
348
|
+
<FlatList
|
|
349
|
+
data={items}
|
|
350
|
+
renderItem={renderItem}
|
|
351
|
+
keyExtractor={(item) => item.id} // Stable ID, NOT index
|
|
352
|
+
getItemLayout={(data, index) => ({
|
|
353
|
+
length: ITEM_HEIGHT,
|
|
354
|
+
offset: ITEM_HEIGHT * index,
|
|
355
|
+
index,
|
|
356
|
+
})}
|
|
357
|
+
removeClippedSubviews={true}
|
|
358
|
+
maxToRenderPerBatch={10}
|
|
359
|
+
windowSize={5}
|
|
360
|
+
/>
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Flutter Critical Rules
|
|
364
|
+
```dart
|
|
365
|
+
// ✅ CORRECT: const constructors prevent rebuilds
|
|
366
|
+
class MyWidget extends StatelessWidget {
|
|
367
|
+
const MyWidget({super.key}); // CONST!
|
|
368
|
+
|
|
369
|
+
@override
|
|
370
|
+
Widget build(BuildContext context) {
|
|
371
|
+
return const Column( // CONST!
|
|
372
|
+
children: [
|
|
373
|
+
Text('Static content'),
|
|
374
|
+
MyConstantWidget(),
|
|
375
|
+
],
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// ✅ CORRECT: Targeted state with ValueListenableBuilder
|
|
381
|
+
ValueListenableBuilder<int>(
|
|
382
|
+
valueListenable: counter,
|
|
383
|
+
builder: (context, value, child) => Text('$value'),
|
|
384
|
+
child: const ExpensiveWidget(), // Won't rebuild!
|
|
385
|
+
)
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Kotlin Multiplatform Critical Rules
|
|
389
|
+
```kotlin
|
|
390
|
+
// ✅ CORRECT: Immutable data classes for thread safety
|
|
391
|
+
@Serializable
|
|
392
|
+
data class User(
|
|
393
|
+
val id: String,
|
|
394
|
+
val name: String,
|
|
395
|
+
val email: String
|
|
396
|
+
) // Immutable by default!
|
|
397
|
+
|
|
398
|
+
// ✅ CORRECT: StateFlow for reactive state (thread-safe)
|
|
399
|
+
class UserRepository {
|
|
400
|
+
private val _users = MutableStateFlow<List<User>>(emptyList())
|
|
401
|
+
val users: StateFlow<List<User>> = _users.asStateFlow() // Read-only
|
|
402
|
+
|
|
403
|
+
suspend fun loadUsers() {
|
|
404
|
+
val result = apiClient.getUsers()
|
|
405
|
+
_users.value = result // Thread-safe update
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// ✅ CORRECT: Coroutines with proper scope
|
|
410
|
+
class UserViewModel {
|
|
411
|
+
private val scope = MainScope() // For iOS compatibility
|
|
412
|
+
|
|
413
|
+
fun loadData() {
|
|
414
|
+
scope.launch {
|
|
415
|
+
try {
|
|
416
|
+
repository.loadUsers()
|
|
417
|
+
} catch (e: Exception) {
|
|
418
|
+
handleError(e)
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
fun onCleared() {
|
|
424
|
+
scope.cancel() // ALWAYS cleanup!
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// ✅ CORRECT: Platform-specific optimization with expect/actual
|
|
429
|
+
// commonMain
|
|
430
|
+
expect fun <T> runOnBackground(block: suspend () -> T): T
|
|
431
|
+
|
|
432
|
+
// androidMain
|
|
433
|
+
actual fun <T> runOnBackground(block: suspend () -> T): T {
|
|
434
|
+
return runBlocking(Dispatchers.IO) { block() }
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// iosMain
|
|
438
|
+
actual fun <T> runOnBackground(block: suspend () -> T): T {
|
|
439
|
+
return runBlocking(Dispatchers.Default) { block() }
|
|
440
|
+
}
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### Jetpack Compose Critical Rules
|
|
444
|
+
```kotlin
|
|
445
|
+
// ✅ CORRECT: Stable keys for LazyColumn
|
|
446
|
+
LazyColumn {
|
|
447
|
+
items(
|
|
448
|
+
items = userList,
|
|
449
|
+
key = { user -> user.id } // Stable key for animations
|
|
450
|
+
) { user ->
|
|
451
|
+
UserRow(user = user)
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// ✅ CORRECT: remember for expensive computations
|
|
456
|
+
@Composable
|
|
457
|
+
fun ExpensiveComponent(data: List<Int>) {
|
|
458
|
+
val processedData = remember(data) {
|
|
459
|
+
data.map { /* expensive operation */ }
|
|
460
|
+
} // Only recomputes when 'data' changes
|
|
461
|
+
|
|
462
|
+
// Use processedData...
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// ✅ CORRECT: derivedStateOf for computed values
|
|
466
|
+
@Composable
|
|
467
|
+
fun FilteredList(items: List<Item>, query: String) {
|
|
468
|
+
val filteredItems by remember {
|
|
469
|
+
derivedStateOf {
|
|
470
|
+
items.filter { it.name.contains(query, ignoreCase = true) }
|
|
471
|
+
}
|
|
472
|
+
} // Only recomputes when items or query changes
|
|
473
|
+
|
|
474
|
+
LazyColumn {
|
|
475
|
+
items(filteredItems) { item ->
|
|
476
|
+
ItemRow(item)
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// ✅ CORRECT: Avoid side effects in composition
|
|
482
|
+
@Composable
|
|
483
|
+
fun UserProfile(userId: String, viewModel: UserViewModel) {
|
|
484
|
+
// ❌ WRONG: Side effect in composition
|
|
485
|
+
// viewModel.loadUser(userId)
|
|
486
|
+
|
|
487
|
+
// ✅ CORRECT: Use LaunchedEffect
|
|
488
|
+
LaunchedEffect(userId) {
|
|
489
|
+
viewModel.loadUser(userId)
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
val user by viewModel.user.collectAsState()
|
|
493
|
+
// Render user...
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// ✅ CORRECT: Cleanup with DisposableEffect
|
|
497
|
+
@Composable
|
|
498
|
+
fun LocationTracker() {
|
|
499
|
+
DisposableEffect(Unit) {
|
|
500
|
+
val listener = LocationListener()
|
|
501
|
+
locationManager.addListener(listener)
|
|
502
|
+
|
|
503
|
+
onDispose {
|
|
504
|
+
locationManager.removeListener(listener) // CLEANUP!
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### Compose Multiplatform Critical Rules
|
|
511
|
+
```kotlin
|
|
512
|
+
// ✅ CORRECT: Platform-specific optimizations
|
|
513
|
+
@Composable
|
|
514
|
+
expect fun PlatformOptimizedList(
|
|
515
|
+
items: List<Item>,
|
|
516
|
+
onItemClick: (Item) -> Unit
|
|
517
|
+
)
|
|
518
|
+
|
|
519
|
+
// androidMain - Use LazyColumn
|
|
520
|
+
@Composable
|
|
521
|
+
actual fun PlatformOptimizedList(
|
|
522
|
+
items: List<Item>,
|
|
523
|
+
onItemClick: (Item) -> Unit
|
|
524
|
+
) {
|
|
525
|
+
LazyColumn {
|
|
526
|
+
items(items, key = { it.id }) { item ->
|
|
527
|
+
ItemRow(item, onItemClick)
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// iosMain - Use LazyColumn (same in Compose MP)
|
|
533
|
+
@Composable
|
|
534
|
+
actual fun PlatformOptimizedList(
|
|
535
|
+
items: List<Item>,
|
|
536
|
+
onItemClick: (Item) -> Unit
|
|
537
|
+
) {
|
|
538
|
+
LazyColumn {
|
|
539
|
+
items(items, key = { it.id }) { item ->
|
|
540
|
+
ItemRow(item, onItemClick)
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// ✅ CORRECT: Shared ViewModel with proper lifecycle
|
|
546
|
+
class SharedViewModel {
|
|
547
|
+
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
|
548
|
+
|
|
549
|
+
private val _state = MutableStateFlow(UiState.Loading)
|
|
550
|
+
val state = _state.asStateFlow()
|
|
551
|
+
|
|
552
|
+
fun onCleared() {
|
|
553
|
+
scope.cancel() // Called from platform-specific cleanup
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Android integration
|
|
558
|
+
class MyActivity : ComponentActivity() {
|
|
559
|
+
private val viewModel = SharedViewModel()
|
|
560
|
+
|
|
561
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
562
|
+
super.onCreate(savedInstanceState)
|
|
563
|
+
setContent {
|
|
564
|
+
val state by viewModel.state.collectAsState()
|
|
565
|
+
MyScreen(state)
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
override fun onDestroy() {
|
|
570
|
+
super.onDestroy()
|
|
571
|
+
viewModel.onCleared()
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// iOS integration (Swift)
|
|
576
|
+
class MyViewController: UIViewController {
|
|
577
|
+
private let viewModel = SharedViewModel()
|
|
578
|
+
|
|
579
|
+
deinit {
|
|
580
|
+
viewModel.onCleared()
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
### Performance Comparison
|
|
588
|
+
|
|
589
|
+
| Framework | Key Optimization | Why |
|
|
590
|
+
|-----------|-----------------|-----|
|
|
591
|
+
| **React Native** | `React.memo` + `useCallback` | Prevent unnecessary re-renders of list items |
|
|
592
|
+
| **Flutter** | `const` constructors | Skip rebuild during parent widget updates |
|
|
593
|
+
| **Jetpack Compose** | `remember` + `derivedStateOf` | Cache expensive computations |
|
|
594
|
+
| **KMP (Shared Logic)** | Immutable data + `StateFlow` | Thread-safe reactive state |
|
|
595
|
+
| **Compose Multiplatform** | Same as Jetpack Compose | Consistent optimization across platforms |
|
|
596
|
+
|
|
597
|
+
---
|
|
598
|
+
|
|
599
|
+
### Animation Performance
|
|
600
|
+
```
|
|
601
|
+
GPU-accelerated (FAST): CPU-bound (SLOW):
|
|
602
|
+
├── transform ├── width, height
|
|
603
|
+
├── opacity ├── top, left, right, bottom
|
|
604
|
+
└── (use these ONLY) ├── margin, padding
|
|
605
|
+
└── (AVOID animating these)
|
|
606
|
+
|
|
607
|
+
React Native:
|
|
608
|
+
useNativeDriver: true // ✅ GPU
|
|
609
|
+
useNativeDriver: false // ❌ JS thread
|
|
610
|
+
|
|
611
|
+
Flutter:
|
|
612
|
+
Transform.translate() // ✅ GPU
|
|
613
|
+
Container(width: animated) // ❌ CPU
|
|
614
|
+
|
|
615
|
+
Compose:
|
|
616
|
+
Modifier.graphicsLayer { // ✅ GPU
|
|
617
|
+
translationX = animatedValue
|
|
618
|
+
}
|
|
619
|
+
Modifier.offset { // ❌ Recomposition
|
|
620
|
+
IntOffset(animatedValue.toInt(), 0)
|
|
621
|
+
}
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
---
|
|
625
|
+
|
|
626
|
+
### Memory Management
|
|
627
|
+
```kotlin
|
|
628
|
+
// ✅ KMP: Proper coroutine cleanup
|
|
629
|
+
class Repository {
|
|
630
|
+
private val scope = CoroutineScope(SupervisorJob())
|
|
631
|
+
|
|
632
|
+
fun fetchData() {
|
|
633
|
+
scope.launch {
|
|
634
|
+
// Async work
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
fun dispose() {
|
|
639
|
+
scope.cancel() // CRITICAL: Cancel all coroutines
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// ✅ React Native: Cleanup subscriptions
|
|
644
|
+
useEffect(() => {
|
|
645
|
+
const subscription = api.subscribe(data => {
|
|
646
|
+
setState(data);
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
return () => subscription.unsubscribe(); // CLEANUP!
|
|
650
|
+
}, []);
|
|
651
|
+
|
|
652
|
+
// ✅ Flutter: Dispose controllers
|
|
653
|
+
class _MyWidgetState extends State<MyWidget> {
|
|
654
|
+
late final AnimationController _controller;
|
|
655
|
+
|
|
656
|
+
@override
|
|
657
|
+
void initState() {
|
|
658
|
+
super.initState();
|
|
659
|
+
_controller = AnimationController(vsync: this);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
@override
|
|
663
|
+
void dispose() {
|
|
664
|
+
_controller.dispose(); // CLEANUP!
|
|
665
|
+
super.dispose();
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// ✅ Compose: DisposableEffect
|
|
670
|
+
@Composable
|
|
671
|
+
fun MyComponent() {
|
|
672
|
+
DisposableEffect(Unit) {
|
|
673
|
+
val resource = createResource()
|
|
674
|
+
onDispose {
|
|
675
|
+
resource.release() // CLEANUP!
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
---
|
|
682
|
+
|
|
683
|
+
### Database Performance (KMP with SQLDelight)
|
|
684
|
+
```kotlin
|
|
685
|
+
// ✅ CORRECT: Batch operations
|
|
686
|
+
fun insertUsers(users: List<User>) {
|
|
687
|
+
database.transaction {
|
|
688
|
+
users.forEach { user ->
|
|
689
|
+
queries.insertUser(user.id, user.name, user.email)
|
|
690
|
+
}
|
|
691
|
+
} // Single transaction = much faster
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// ✅ CORRECT: Indexed queries
|
|
695
|
+
// In .sq file
|
|
696
|
+
CREATE TABLE User (
|
|
697
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
698
|
+
email TEXT NOT NULL,
|
|
699
|
+
createdAt INTEGER NOT NULL
|
|
700
|
+
);
|
|
701
|
+
|
|
702
|
+
CREATE INDEX user_email ON User(email); // Index for fast lookup
|
|
703
|
+
|
|
704
|
+
// ❌ WRONG: Query in loop
|
|
705
|
+
fun getUsers(): List<UserWithPosts> {
|
|
706
|
+
val users = queries.selectAllUsers().executeAsList()
|
|
707
|
+
return users.map { user ->
|
|
708
|
+
val posts = queries.selectPostsByUserId(user.id).executeAsList()
|
|
709
|
+
UserWithPosts(user, posts) // N+1 query problem!
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// ✅ CORRECT: Join query
|
|
714
|
+
// In .sq file
|
|
715
|
+
selectUsersWithPosts:
|
|
716
|
+
SELECT User.*, Post.*
|
|
717
|
+
FROM User
|
|
718
|
+
LEFT JOIN Post ON User.id = Post.userId;
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
---
|
|
722
|
+
|
|
723
|
+
### Network Performance (KMP with Ktor)
|
|
724
|
+
```kotlin
|
|
725
|
+
// ✅ CORRECT: Connection pooling + timeout
|
|
726
|
+
val client = HttpClient {
|
|
727
|
+
engine {
|
|
728
|
+
// Android (OkHttp)
|
|
729
|
+
threadsCount = 4
|
|
730
|
+
pipelining = true
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
install(HttpTimeout) {
|
|
734
|
+
requestTimeoutMillis = 10_000
|
|
735
|
+
connectTimeoutMillis = 5_000
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
install(ContentNegotiation) {
|
|
739
|
+
json(Json {
|
|
740
|
+
ignoreUnknownKeys = true // Don't parse unused fields
|
|
741
|
+
})
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// ✅ CORRECT: Batch API calls
|
|
746
|
+
suspend fun loadDashboard(): Dashboard {
|
|
747
|
+
// Parallel requests
|
|
748
|
+
val (user, posts, notifications) = coroutineScope {
|
|
749
|
+
val userDeferred = async { api.getUser() }
|
|
750
|
+
val postsDeferred = async { api.getPosts() }
|
|
751
|
+
val notificationsDeferred = async { api.getNotifications() }
|
|
752
|
+
|
|
753
|
+
Triple(
|
|
754
|
+
userDeferred.await(),
|
|
755
|
+
postsDeferred.await(),
|
|
756
|
+
notificationsDeferred.await()
|
|
757
|
+
)
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
return Dashboard(user, posts, notifications)
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// ❌ WRONG: Sequential requests
|
|
764
|
+
suspend fun loadDashboardSlow(): Dashboard {
|
|
765
|
+
val user = api.getUser() // Wait...
|
|
766
|
+
val posts = api.getPosts() // Wait...
|
|
767
|
+
val notifications = api.getNotifications() // Wait...
|
|
768
|
+
return Dashboard(user, posts, notifications)
|
|
769
|
+
}
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
---
|
|
773
|
+
|
|
774
|
+
### iOS-Specific KMP Performance
|
|
775
|
+
```kotlin
|
|
776
|
+
// ✅ CORRECT: Use MainScope for iOS compatibility
|
|
777
|
+
class iOSViewModel {
|
|
778
|
+
private val scope = MainScope() // Works on iOS main thread
|
|
779
|
+
|
|
780
|
+
fun loadData() {
|
|
781
|
+
scope.launch {
|
|
782
|
+
val data = repository.fetchData()
|
|
783
|
+
updateUI(data)
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// ✅ CORRECT: Freeze immutable data for iOS (pre-new memory model)
|
|
789
|
+
data class User(val id: String, val name: String) {
|
|
790
|
+
init {
|
|
791
|
+
freeze() // For Kotlin/Native < 1.6
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
// ✅ CORRECT: Use new memory model (Kotlin 1.6+)
|
|
796
|
+
// In gradle.properties:
|
|
797
|
+
kotlin.native.binary.memoryModel=experimental
|
|
798
|
+
|
|
799
|
+
// No more freezing needed! 🎉
|
|
800
|
+
```
|
|
801
|
+
---
|
|
802
|
+
### Animation Performance
|
|
803
|
+
|
|
804
|
+
```
|
|
805
|
+
GPU-accelerated (FAST): CPU-bound (SLOW):
|
|
806
|
+
├── transform ├── width, height
|
|
807
|
+
├── opacity ├── top, left, right, bottom
|
|
808
|
+
└── (use these ONLY) ├── margin, padding
|
|
809
|
+
└── (AVOID animating these)
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
For complete guide: [mobile-performance.md](mobile-performance.md)
|
|
813
|
+
|
|
814
|
+
---
|
|
815
|
+
|
|
816
|
+
## 📝 CHECKPOINT (MANDATORY Before Any Mobile Work)
|
|
817
|
+
|
|
818
|
+
> **Before writing ANY mobile code, you MUST complete this checkpoint:**
|
|
819
|
+
|
|
820
|
+
```
|
|
821
|
+
🧠 CHECKPOINT:
|
|
822
|
+
|
|
823
|
+
Platform: [ iOS / Android / Both ]
|
|
824
|
+
Framework: [ React Native / Flutter / SwiftUI / Kotlin ]
|
|
825
|
+
Files Read: [ List the skill files you've read ]
|
|
826
|
+
|
|
827
|
+
3 Principles I Will Apply:
|
|
828
|
+
1. _______________
|
|
829
|
+
2. _______________
|
|
830
|
+
3. _______________
|
|
831
|
+
|
|
832
|
+
Anti-Patterns I Will Avoid:
|
|
833
|
+
1. _______________
|
|
834
|
+
2. _______________
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
**Example:**
|
|
838
|
+
```
|
|
839
|
+
🧠 CHECKPOINT:
|
|
840
|
+
|
|
841
|
+
Platform: iOS + Android (Cross-platform)
|
|
842
|
+
Framework: React Native + Expo
|
|
843
|
+
Files Read: touch-psychology.md, mobile-performance.md, platform-ios.md, platform-android.md
|
|
844
|
+
|
|
845
|
+
3 Principles I Will Apply:
|
|
846
|
+
1. FlatList with React.memo + useCallback for all lists
|
|
847
|
+
2. 48px touch targets, thumb zone for primary CTAs
|
|
848
|
+
3. Platform-specific navigation (edge swipe iOS, back button Android)
|
|
849
|
+
|
|
850
|
+
Anti-Patterns I Will Avoid:
|
|
851
|
+
1. ScrollView for lists → FlatList
|
|
852
|
+
2. Inline renderItem → Memoized
|
|
853
|
+
3. AsyncStorage for tokens → SecureStore
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
> 🔴 **Can't fill the checkpoint? → GO BACK AND READ THE SKILL FILES.**
|
|
857
|
+
|
|
858
|
+
---
|
|
859
|
+
|
|
860
|
+
## 🔧 Framework Decision Tree
|
|
861
|
+
|
|
862
|
+
```
|
|
863
|
+
WHAT ARE YOU BUILDING?
|
|
864
|
+
│
|
|
865
|
+
├── Need OTA updates + rapid iteration + web team
|
|
866
|
+
│ └── ✅ React Native + Expo
|
|
867
|
+
│
|
|
868
|
+
├── Need pixel-perfect custom UI + performance critical
|
|
869
|
+
│ └── ✅ Flutter
|
|
870
|
+
│
|
|
871
|
+
├── Deep native features + single platform focus
|
|
872
|
+
│ ├── iOS only → SwiftUI
|
|
873
|
+
│ └── Android only → Kotlin + Jetpack Compose
|
|
874
|
+
│
|
|
875
|
+
├── Existing RN codebase + new features
|
|
876
|
+
│ └── ✅ React Native (bare workflow)
|
|
877
|
+
│
|
|
878
|
+
└── Enterprise + existing Flutter codebase
|
|
879
|
+
└── ✅ Flutter
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
For complete decision trees: [decision-trees.md](decision-trees.md)
|
|
883
|
+
|
|
884
|
+
---
|
|
885
|
+
|
|
886
|
+
## 📋 Pre-Development Checklist
|
|
887
|
+
|
|
888
|
+
### Before Starting ANY Mobile Project
|
|
889
|
+
|
|
890
|
+
- [ ] **Platform confirmed?** (iOS / Android / Both)
|
|
891
|
+
- [ ] **Framework chosen?** (RN / Flutter / Native)
|
|
892
|
+
- [ ] **Navigation pattern decided?** (Tabs / Stack / Drawer)
|
|
893
|
+
- [ ] **State management selected?** (Zustand / Redux / Riverpod / BLoC)
|
|
894
|
+
- [ ] **Offline requirements known?**
|
|
895
|
+
- [ ] **Deep linking planned from day one?**
|
|
896
|
+
- [ ] **Target devices defined?** (Phone / Tablet / Both)
|
|
897
|
+
|
|
898
|
+
### Before Every Screen
|
|
899
|
+
|
|
900
|
+
- [ ] **Touch targets ≥ 44-48px?**
|
|
901
|
+
- [ ] **Primary CTA in thumb zone?**
|
|
902
|
+
- [ ] **Loading state exists?**
|
|
903
|
+
- [ ] **Error state with retry exists?**
|
|
904
|
+
- [ ] **Offline handling considered?**
|
|
905
|
+
- [ ] **Platform conventions followed?**
|
|
906
|
+
|
|
907
|
+
### Before Release
|
|
908
|
+
|
|
909
|
+
- [ ] **console.log removed?**
|
|
910
|
+
- [ ] **SecureStore for sensitive data?**
|
|
911
|
+
- [ ] **SSL pinning enabled?**
|
|
912
|
+
- [ ] **Lists optimized (memo, keyExtractor)?**
|
|
913
|
+
- [ ] **Memory cleanup on unmount?**
|
|
914
|
+
- [ ] **Tested on low-end devices?**
|
|
915
|
+
- [ ] **Accessibility labels on all interactive elements?**
|
|
916
|
+
|
|
917
|
+
---
|
|
918
|
+
|
|
919
|
+
## 📚 Reference Files
|
|
920
|
+
|
|
921
|
+
For deeper guidance on specific areas:
|
|
922
|
+
|
|
923
|
+
| File | When to Use |
|
|
924
|
+
|------|-------------|
|
|
925
|
+
| [mobile-design-thinking.md](mobile-design-thinking.md) | **FIRST! Anti-memorization, forces context-based thinking** |
|
|
926
|
+
| [touch-psychology.md](touch-psychology.md) | Understanding touch interaction, Fitts' Law, gesture design |
|
|
927
|
+
| [mobile-performance.md](mobile-performance.md) | Optimizing RN/Flutter, 60fps, memory/battery |
|
|
928
|
+
| [platform-ios.md](platform-ios.md) | iOS-specific design, HIG compliance |
|
|
929
|
+
| [platform-android.md](platform-android.md) | Android-specific design, Material Design 3 |
|
|
930
|
+
| [mobile-navigation.md](mobile-navigation.md) | Navigation patterns, deep linking |
|
|
931
|
+
| [mobile-typography.md](mobile-typography.md) | Type scale, system fonts, accessibility |
|
|
932
|
+
| [mobile-color-system.md](mobile-color-system.md) | OLED optimization, dark mode, battery |
|
|
933
|
+
| [decision-trees.md](decision-trees.md) | Framework, state, storage decisions |
|
|
934
|
+
|
|
935
|
+
---
|
|
936
|
+
|
|
937
|
+
> **Remember:** Mobile users are impatient, interrupted, and using imprecise fingers on small screens. Design for the WORST conditions: bad network, one hand, bright sun, low battery. If it works there, it works everywhere.
|