@shaykec/app-agent 1.0.8 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/.claude/agents/android-customizer.md +9 -1
  2. package/.claude/agents/catalog-analyzer.md +57 -0
  3. package/.claude/agents/ios-customizer.md +9 -1
  4. package/.claude/agents/react-native-customizer.md +71 -0
  5. package/.claude/skills/android-customizer/SKILL.md +108 -23
  6. package/.claude/skills/bug-fixer/SKILL.md +59 -0
  7. package/.claude/skills/catalog-analyzer/SKILL.md +96 -0
  8. package/.claude/skills/customization-planner/SKILL.md +44 -5
  9. package/.claude/skills/design-selector/SKILL.md +3 -1
  10. package/.claude/skills/design-system/SKILL.md +1 -1
  11. package/.claude/skills/exploratory-tester/SKILL.md +82 -0
  12. package/.claude/skills/ios-customizer/SKILL.md +123 -23
  13. package/.claude/skills/module-integrator/SKILL.md +1 -1
  14. package/.claude/skills/react-native-customizer/SKILL.md +97 -11
  15. package/.claude/skills/test-planner/SKILL.md +72 -0
  16. package/.cursor/agents/README.md +3 -1
  17. package/.cursor/agents/android-customizer.md +15 -11
  18. package/.cursor/agents/catalog-analyzer.md +83 -0
  19. package/.cursor/agents/ios-customizer.md +15 -10
  20. package/.cursor/agents/react-native-customizer.md +170 -0
  21. package/.cursor/mcp.json +2 -10
  22. package/.cursor/rules/safety-guardrails.mdc +1 -1
  23. package/.cursor/rules/workflow.mdc +52 -18
  24. package/.cursor/skills/android-customizer/SKILL.md +46 -22
  25. package/.cursor/skills/bug-fixer/SKILL.md +189 -0
  26. package/.cursor/skills/catalog-analyzer/SKILL.md +222 -0
  27. package/.cursor/skills/customization-planner/SKILL.md +55 -8
  28. package/.cursor/skills/design-selector/SKILL.md +6 -5
  29. package/.cursor/skills/design-system/SKILL.md +8 -7
  30. package/.cursor/skills/exploratory-tester/SKILL.md +223 -0
  31. package/.cursor/skills/ios-customizer/SKILL.md +50 -15
  32. package/.cursor/skills/module-integrator/SKILL.md +2 -2
  33. package/.cursor/skills/output-validator/SKILL.md +1 -1
  34. package/.cursor/skills/react-native-customizer/SKILL.md +115 -25
  35. package/.cursor/skills/test-planner/SKILL.md +199 -0
  36. package/AGENTS.md +32 -11
  37. package/CLAUDE.md +78 -33
  38. package/README.md +77 -11
  39. package/designs/DESIGN_CATALOG.md +17 -15
  40. package/designs/DESIGN_PRINCIPLES.md +53 -0
  41. package/designs/brands/accessible-high-contrast.md +14 -0
  42. package/designs/brands/corporate-professional.md +14 -0
  43. package/designs/brands/dark-luxe.md +14 -0
  44. package/designs/brands/kids-playful.md +14 -0
  45. package/designs/brands/medical-clinical.md +14 -0
  46. package/designs/brands/modern-minimal.md +14 -0
  47. package/designs/brands/nature-organic.md +14 -0
  48. package/designs/brands/neo-brutalist.md +14 -0
  49. package/designs/brands/retro-vintage.md +14 -0
  50. package/designs/brands/soft-gradient.md +14 -0
  51. package/designs/brands/sport-athletic.md +14 -0
  52. package/designs/brands/tech-dynamic.md +14 -0
  53. package/designs/brands/vibrant-playful.md +14 -0
  54. package/dist/cli.d.ts +4 -2
  55. package/dist/cli.d.ts.map +1 -1
  56. package/dist/cli.js +91 -1
  57. package/dist/cli.js.map +1 -1
  58. package/dist/config.d.ts +2 -0
  59. package/dist/config.d.ts.map +1 -1
  60. package/dist/config.js +2 -0
  61. package/dist/config.js.map +1 -1
  62. package/dist/engines/claude-engine.d.ts.map +1 -1
  63. package/dist/engines/claude-engine.js +16 -4
  64. package/dist/engines/claude-engine.js.map +1 -1
  65. package/dist/engines/types.d.ts +1 -1
  66. package/dist/engines/types.d.ts.map +1 -1
  67. package/dist/engines/types.js +31 -2
  68. package/dist/engines/types.js.map +1 -1
  69. package/dist/github.d.ts +3 -0
  70. package/dist/github.d.ts.map +1 -1
  71. package/dist/github.js +47 -4
  72. package/dist/github.js.map +1 -1
  73. package/dist/index.js +217 -9
  74. package/dist/index.js.map +1 -1
  75. package/dist/prompt-builder.d.ts +11 -1
  76. package/dist/prompt-builder.d.ts.map +1 -1
  77. package/dist/prompt-builder.js +216 -1
  78. package/dist/prompt-builder.js.map +1 -1
  79. package/dist/validator.d.ts +7 -2
  80. package/dist/validator.d.ts.map +1 -1
  81. package/dist/validator.js +61 -41
  82. package/dist/validator.js.map +1 -1
  83. package/dist/workspace.js +2 -2
  84. package/dist/workspace.js.map +1 -1
  85. package/package.json +2 -2
  86. package/prompts/agent-prompt.md +35 -18
  87. package/prompts/deep-test-agent-prompt.md +122 -0
  88. package/prompts/fix-agent-prompt.md +90 -0
  89. package/prompts/quick-agent-prompt.md +32 -2
  90. package/prompts/scratch-agent-prompt.md +5 -8
  91. package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  92. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  93. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/conversations/ConversationsScreen.kt +1 -1
  94. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  95. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/navigation/MainScreen.kt +1 -0
  96. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  97. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/navigation/MainNavigation.kt +5 -1
  98. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  99. package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  100. package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/core/animation/MotionPreferencesScreen.kt +3 -3
  101. package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/features/navigation/Navigation.kt +1 -1
  102. package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/features/settings/SettingsScreen.kt +1 -1
  103. package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  104. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  105. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  106. package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  107. package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/features/settings/SettingsScreen.kt +3 -2
  108. package/templates/android/ReferenceTemplate/app/src/main/kotlin/com/appship/reference/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  109. package/templates/android/ReferenceTemplate/app/src/main/kotlin/com/appship/reference/features/settings/SettingsScreen.kt +1 -1
  110. package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  111. package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/features/cart/CartScreen.kt +3 -2
  112. package/templates/android/Skeleton/TESTING_MANIFEST.md +2 -1
  113. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/MainActivity.kt +23 -2
  114. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  115. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/core/theme/AppearanceManager.kt +42 -0
  116. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/features/profile/ProfileScreen.kt +20 -8
  117. package/templates/android/Skeleton/tests/03_detail_screen.yaml +3 -2
  118. package/templates/android/Skeleton/tests/04_favorites.yaml +3 -2
  119. package/templates/android/Skeleton/tests/08_full_e2e.yaml +9 -2
  120. package/templates/android/Skeleton/tests/09_dark_mode.yaml +50 -0
  121. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  122. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  123. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/settings/SettingsScreen.kt +3 -2
  124. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/core/animation/AnimatedTransitionsModifiers.kt +188 -0
  125. package/templates/ios/BookTemplate/BookTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  126. package/templates/ios/ChatTemplate/ChatTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  127. package/templates/ios/DashTemplate/DashTemplate/App/AppConfig.swift +1 -0
  128. package/templates/ios/DashTemplate/DashTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  129. package/templates/ios/DashTemplate/DashTemplate/Core/Strings.swift +13 -0
  130. package/templates/ios/DashTemplate/DashTemplate.xcodeproj/project.pbxproj +32 -20
  131. package/templates/ios/FamilyTemplate/FamilyTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  132. package/templates/ios/FinanceTemplate/FinanceTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  133. package/templates/ios/FinanceTemplate/FinanceTemplate/Core/Strings.swift +42 -0
  134. package/templates/ios/FinanceTemplate/FinanceTemplate.xcodeproj/project.pbxproj +36 -30
  135. package/templates/ios/GameTemplate/GameTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  136. package/templates/ios/HealthTemplate/HealthTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  137. package/templates/ios/LearnTemplate/LearnTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  138. package/templates/ios/MapTemplate/MapTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  139. package/templates/ios/MediaTemplate/MediaTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  140. package/templates/ios/ReferenceTemplate/ReferenceTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  141. package/templates/ios/ReferenceTemplate/ReferenceTemplate/Core/Strings.swift +12 -0
  142. package/templates/ios/ReferenceTemplate/ReferenceTemplate/Features/SkeletonLoading/SkeletonLoadingView.swift +2 -37
  143. package/templates/ios/ShopTemplate/ShopTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  144. package/templates/ios/Skeleton/Skeleton/Core/Animation/AnimatedTransitionsView.swift +201 -0
  145. package/templates/ios/Skeleton/tests/08_full_e2e.yaml +4 -0
  146. package/templates/ios/Skeleton/tests/09_dark_mode.yaml +52 -0
  147. package/templates/ios/SocialTemplate/SocialTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  148. package/templates/ios/TaskTemplate/TaskTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  149. package/templates/ios/TrackTemplate/TrackTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
  150. package/templates/react-native/BookTemplate/src/animation/useAnimatedList.ts +219 -2
  151. package/templates/react-native/BookTemplate/src/animation/useMotionPreferences.ts +23 -9
  152. package/templates/react-native/BookTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  153. package/templates/react-native/ChatTemplate/src/animation/useAnimatedList.ts +219 -2
  154. package/templates/react-native/ChatTemplate/src/animation/useMotionPreferences.ts +23 -9
  155. package/templates/react-native/ChatTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  156. package/templates/react-native/DashTemplate/src/animation/useAnimatedList.ts +219 -2
  157. package/templates/react-native/DashTemplate/src/animation/useMotionPreferences.ts +23 -9
  158. package/templates/react-native/DashTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  159. package/templates/react-native/FamilyTemplate/src/animation/useAnimatedList.ts +219 -2
  160. package/templates/react-native/FamilyTemplate/src/animation/useMotionPreferences.ts +23 -9
  161. package/templates/react-native/FamilyTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  162. package/templates/react-native/FinanceTemplate/src/animation/useAnimatedList.ts +219 -2
  163. package/templates/react-native/FinanceTemplate/src/animation/useMotionPreferences.ts +23 -9
  164. package/templates/react-native/FinanceTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  165. package/templates/react-native/GameTemplate/src/animation/useAnimatedList.ts +219 -2
  166. package/templates/react-native/GameTemplate/src/animation/useMotionPreferences.ts +23 -9
  167. package/templates/react-native/GameTemplate/src/screens/GameDetail/GameDetailScreen.tsx +2 -1
  168. package/templates/react-native/GameTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  169. package/templates/react-native/HealthTemplate/src/animation/useAnimatedList.ts +219 -2
  170. package/templates/react-native/HealthTemplate/src/animation/useMotionPreferences.ts +23 -9
  171. package/templates/react-native/HealthTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  172. package/templates/react-native/HealthTemplate/src/screens/WorkoutDetail/WorkoutDetailScreen.tsx +1 -1
  173. package/templates/react-native/LearnTemplate/src/animation/useAnimatedList.ts +219 -2
  174. package/templates/react-native/LearnTemplate/src/animation/useMotionPreferences.ts +23 -9
  175. package/templates/react-native/LearnTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  176. package/templates/react-native/MapTemplate/src/animation/useAnimatedList.ts +219 -2
  177. package/templates/react-native/MapTemplate/src/animation/useMotionPreferences.ts +23 -9
  178. package/templates/react-native/MapTemplate/src/screens/Map/MapScreen.tsx +14 -0
  179. package/templates/react-native/MapTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  180. package/templates/react-native/MediaTemplate/src/animation/useAnimatedList.ts +219 -2
  181. package/templates/react-native/MediaTemplate/src/animation/useMotionPreferences.ts +23 -9
  182. package/templates/react-native/MediaTemplate/src/screens/PlaylistDetail/PlaylistDetailScreen.tsx +1 -1
  183. package/templates/react-native/MediaTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  184. package/templates/react-native/ReferenceTemplate/src/animation/useAnimatedList.ts +219 -2
  185. package/templates/react-native/ReferenceTemplate/src/animation/useMotionPreferences.ts +23 -9
  186. package/templates/react-native/ReferenceTemplate/src/screens/Settings/SettingsScreen.tsx +1 -1
  187. package/templates/react-native/ShopTemplate/src/animation/useAnimatedList.ts +219 -2
  188. package/templates/react-native/ShopTemplate/src/animation/useMotionPreferences.ts +23 -9
  189. package/templates/react-native/ShopTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  190. package/templates/react-native/Skeleton/TESTING_MANIFEST.md +2 -1
  191. package/templates/react-native/Skeleton/src/animation/useAnimatedList.ts +219 -2
  192. package/templates/react-native/Skeleton/src/animation/useMotionPreferences.ts +23 -9
  193. package/templates/react-native/Skeleton/src/screens/Profile/ProfileScreen.tsx +1 -1
  194. package/templates/react-native/Skeleton/tests/07_profile.yaml +3 -2
  195. package/templates/react-native/Skeleton/tests/08_full_e2e.yaml +12 -1
  196. package/templates/react-native/Skeleton/tests/09_dark_mode.yaml +46 -0
  197. package/templates/react-native/SocialTemplate/src/animation/useAnimatedList.ts +219 -2
  198. package/templates/react-native/SocialTemplate/src/animation/useMotionPreferences.ts +23 -9
  199. package/templates/react-native/SocialTemplate/src/screens/Feed/FeedScreen.tsx +1 -0
  200. package/templates/react-native/SocialTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  201. package/templates/react-native/TaskTemplate/src/animation/useAnimatedList.ts +219 -2
  202. package/templates/react-native/TaskTemplate/src/animation/useMotionPreferences.ts +23 -9
  203. package/templates/react-native/TaskTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
  204. package/templates/react-native/TrackTemplate/src/animation/useAnimatedList.ts +219 -2
  205. package/templates/react-native/TrackTemplate/src/animation/useMotionPreferences.ts +23 -9
  206. package/templates/react-native/TrackTemplate/src/screens/Settings/SettingsScreen.tsx +1 -1
  207. package/templates/shared/ios/AnimatedTransitions/AnimatedTransitionsView.swift +233 -93
  208. package/.claude/agents/template-selector.md +0 -39
  209. package/.claude/skills/module-selector/SKILL.md +0 -81
  210. package/.claude/skills/template-selector/SKILL.md +0 -44
  211. package/.cursor/agents/template-selector.md +0 -52
  212. package/.cursor/skills/module-selector/SKILL.md +0 -135
  213. package/.cursor/skills/template-selector/SKILL.md +0 -123
@@ -0,0 +1,82 @@
1
+ ---
2
+ name: exploratory-tester
3
+ description: Screenshot and accessibility-tree driven exploratory testing. Does NOT read source code — tests purely through what the AI sees on screen. Discovers visual bugs, accessibility issues, UX problems, and content issues.
4
+ allowed-tools: inspect, act, assert, wait, navigate, device, logs, Read, Write
5
+ context: fork
6
+ ---
7
+
8
+ # Exploratory Tester Skill
9
+
10
+ Test the app by exploring it visually — screenshots and accessibility tree as your only inputs. Do NOT read source code.
11
+
12
+ ## Context
13
+
14
+ - **Platform**, **Bundle ID**, **Simulator name** — for ai-tester MCP calls
15
+ - **App directory** — only for writing the bug report
16
+
17
+ ## Instructions
18
+
19
+ ### Phase A — Screen Discovery
20
+
21
+ 1. Launch app: `inspect({ platform, app: bundleId, deviceName })`
22
+ 2. Wait 3-5s, `inspect()` again
23
+ 3. Map tab bar — identify all tabs from element tree
24
+ 4. Visit each tab — `inspect()` on each
25
+ 5. Discover sub-screens — tap list items, buttons, links
26
+ 6. Build screen map (tab → screen → sub-screen)
27
+
28
+ ### Phase B — Per-Screen Audit
29
+
30
+ For each screen, `inspect()` then:
31
+
32
+ **B1 — Visual Analysis (screenshot):**
33
+ - No overlapping/cut-off text, proper spacing, correct alignment
34
+ - Real domain text (not "Lorem ipsum", "Item 1", "Template")
35
+ - Images loaded, icons match context
36
+ - Consistent typography and colors
37
+ - Template leftover detection
38
+
39
+ **B2 — Accessibility Tree Audit:**
40
+ - Every button/link has non-empty label
41
+ - Images have a11y descriptions
42
+ - Form fields have labels
43
+ - No orphaned elements (in tree but not visible, or visible but not in tree)
44
+ - Touch targets >= 44x44pt (iOS) / 48x48dp (Android)
45
+
46
+ **B3 — Interactive Exploration:**
47
+ - Tap every button — verify something happens (flag dead buttons)
48
+ - Type into every text field — normal text + edge cases (empty, long, special chars)
49
+ - Toggle every switch — verify state change
50
+ - Scroll every list to bottom and back up
51
+ - Navigate 3+ levels deep, verify back nav works all the way
52
+ - Switch tabs rapidly — verify correct content
53
+ - Test state persistence (favorite, form text, scroll position)
54
+
55
+ **B4 — Before/After Comparison:**
56
+ - `inspect()` after interactions, compare element trees
57
+ - Flag unexpected changes (disappeared elements, count mismatches)
58
+
59
+ ### Phase C — Bug Classification
60
+
61
+ | Tag | Category | Examples |
62
+ |-----|----------|----------|
63
+ | `[VISUAL]` | Layout | Overlap, truncation, wrong colors |
64
+ | `[A11Y]` | Accessibility | Missing labels, small targets |
65
+ | `[UX]` | Experience | Dead buttons, confusing nav |
66
+ | `[CONTENT]` | Content | Template leftovers, placeholders |
67
+ | `[STATE]` | State | Not persisting, stale views |
68
+ | `[CRASH]` | Crash | App crash on interaction |
69
+
70
+ Format: `BUG-{NNN}: [{SEVERITY}][EXPLORATORY][{TAG}] {description}` with screen, element, steps, expected, actual.
71
+
72
+ ### Phase D — Write Bug Report
73
+
74
+ Write/append to `output/{app-name}/reports/11-bug-report.md` with: summary counts, accessibility summary, screen map, all bugs.
75
+
76
+ ## Rules
77
+
78
+ - **DO NOT read source code** — only screenshots + element tree from `inspect()`
79
+ - **DO NOT follow a test plan** — explore freely
80
+ - Test EVERY interactive element in the element tree
81
+ - Use ai-tester MCP tools for ALL interaction
82
+ - Write findings to bug report — do NOT fix bugs
@@ -9,7 +9,7 @@ Use this skill to perform deep iOS/SwiftUI customization on a cloned template.
9
9
 
10
10
  ## When to Use
11
11
 
12
- - At Step 8 of the AppAgent workflow, when the platform is iOS
12
+ - At Step 5 of the AppAgent workflow, when the platform is iOS
13
13
  - After AppConfig, mock data, and design tokens are already in place
14
14
  - When you need to modify SwiftUI views, navigation, and themes
15
15
 
@@ -100,6 +100,28 @@ iOS templates use a `Colors.swift` theme file:
100
100
  - Use semantic colors where possible (`Color.primary`, `Color.secondary`)
101
101
  - Apply corner radius and spacing tokens from the design brief
102
102
 
103
+ ### Step 4.5 — Visual Polish Application
104
+
105
+ Apply the **Visual Polish Plan** from the manifest. MANDATORY for every build.
106
+
107
+ 1. **Shadows**: Apply `.cardShadow()` or `shadow(color:radius:x:y:)` to every card/elevated surface using manifest shadow tokens.
108
+ 2. **Gradients**: Apply `LinearGradient` to hero sections and primary CTAs (primary → secondary, 135deg).
109
+ 3. **Press feedback**: All buttons use `.scaleOnPress()` (scale 0.95, spring return). Add `UIImpactFeedbackGenerator` to favorite toggles and submit buttons.
110
+ 4. **Staggered animations**: All list views use `.staggeredAppear(index:)` on each item.
111
+ 5. **Empty states**: Gradient circle behind icon + `.slideIn()` animation.
112
+ 6. **Glass/blur**: `.ultraThinMaterial` on sheet backgrounds and overlays.
113
+ 7. **Haptic**: Feedback on favorite toggles, pull-to-refresh, primary actions.
114
+
115
+ ### Step 4.6 — Generate App Launcher Icon
116
+
117
+ Generate a domain-specific app icon using the manifest's **App Launcher Icon** section:
118
+
119
+ 1. Read the icon spec: `iOS SF Symbol` (e.g., `bag.fill`) and `Background` hex color
120
+ 2. Run: `swift scripts/generate-app-icon.swift "{symbol}" "{background}" "output/{app-name}/{AppName}/Resources/Assets.xcassets/AppIcon.appiconset/"`
121
+ 3. Verify `AppIcon-1024.png` exists in the output directory
122
+
123
+ If `scripts/generate-app-icon.swift` does not exist or fails, skip — the template's default icon will be used.
124
+
103
125
  ### Step 5 — Data Layer & Offline Infrastructure
104
126
 
105
127
  Templates now include an **offline-first data layer**. Understand these components:
@@ -118,18 +140,31 @@ Templates now include an **offline-first data layer**. Understand these componen
118
140
  - `Data/SyncManager.swift` — if entity types were renamed, update domain methods
119
141
 
120
142
  **ViewModel patterns** (how views consume data):
143
+
144
+ ViewModels use the `DataRepository` protocol abstraction, not `MockDataProvider` directly:
121
145
  ```swift
122
- // ViewModels observe MockDataProvider.shared
123
- @ObservedObject var store = MockDataProvider.shared
146
+ // ViewModels depend on the DataRepository protocol
147
+ private let repository: any DataRepository
148
+
149
+ init(repository: any DataRepository = DataSourceResolver.repository) {
150
+ self.repository = repository
151
+ }
152
+
153
+ // Read data via the protocol
154
+ let items = repository.items
155
+ let categories = repository.categories
124
156
 
125
- // Or use EnvironmentObject if injected
126
- @EnvironmentObject var store: MockDataProvider
157
+ // CRUD via the protocol
158
+ repository.addItem(newItem)
159
+ repository.deleteItem(item)
160
+ repository.toggleFavorite(item)
127
161
 
128
- // CRUD via SyncManager
162
+ // If SyncManager exists, it wraps the repository
129
163
  SyncManager.shared.addProduct(newProduct)
130
- SyncManager.shared.deleteProduct(id)
131
164
  ```
132
165
 
166
+ When customizing ViewModels, ALWAYS use `repository` (from `DataSourceResolver`), never `MockDataProvider.shared` directly. This ensures the app works with any data source.
167
+
133
168
  **OfflineBanner integration** — add to main navigation views:
134
169
  ```swift
135
170
  VStack(spacing: 0) {
@@ -138,27 +173,87 @@ VStack(spacing: 0) {
138
173
  }
139
174
  ```
140
175
 
141
- ### Step 6 — MockDataProvider Verification
176
+ ### Step 6 — Data Layer Verification
142
177
 
143
- Verify the MockDataProvider uses the correct patterns:
178
+ Verify the data layer uses the correct patterns:
144
179
 
180
+ **DataRepository protocol:**
145
181
  ```swift
146
- class MockDataProvider: ObservableObject {
182
+ protocol DataRepository: AnyObject {
183
+ var items: [Item] { get }
184
+ var categories: [Category] { get }
185
+ var favoriteItems: [Item] { get }
186
+ func loadData()
187
+ func addItem(_ item: Item)
188
+ // ... all CRUD + query methods
189
+ }
190
+ ```
191
+
192
+ **MockDataProvider (conforms to DataRepository):**
193
+ ```swift
194
+ class MockDataProvider: ObservableObject, DataRepository {
147
195
  static let shared = MockDataProvider()
148
-
149
- @Published var products: [Product] // Reactive, mutable
150
-
151
- static let defaultProducts: [Product] = [...] // Seed data
152
-
153
- func addProduct(_ product: Product) { ... } // CRUD
154
- func reset() { ... } // Reset to defaults
196
+ @Published var products: [Product]
197
+ static let defaultProducts: [Product] = [...]
198
+ func addProduct(_ product: Product) { ... }
199
+ func reset() { ... }
155
200
  }
156
201
  ```
157
202
 
158
- - Verify seed data matches the new domain
159
- - Ensure CRUD methods reference correct entity types
160
- - Verify `reset()` works correctly
161
- - Check that `@Published` properties are being observed by ViewModels
203
+ **DataSourceResolver:**
204
+ ```swift
205
+ enum DataSourceResolver {
206
+ static var repository: any DataRepository {
207
+ switch AppConfig.DataSource.active {
208
+ case .mock: return MockDataProvider.shared
209
+ case .localStorage: return MockDataProvider.shared // TODO: LocalStorageProvider
210
+ }
211
+ }
212
+ }
213
+ ```
214
+
215
+ Verify:
216
+ - DataRepository protocol matches MockDataProvider's public interface
217
+ - MockDataProvider conforms to DataRepository
218
+ - DataSourceResolver returns the correct implementation
219
+ - ViewModels use `DataSourceResolver.repository`, not `MockDataProvider.shared` directly
220
+ - Seed data matches the new domain
221
+ - CRUD methods reference correct entity types
222
+
223
+ ### Step 6.5 — Apply Animation Modifiers (if animation modules are integrated)
224
+
225
+ If the customization manifest includes an **"Animation & Sensory Plan"** section:
226
+
227
+ 1. Read the "Per-Screen Animation Modifiers" table from the manifest
228
+ 2. For each screen in your batch, apply the assigned modifiers:
229
+
230
+ ```swift
231
+ // Built-in press feedback (always available)
232
+ Button("Add to Cart") { ... }
233
+ .scaleOnPress()
234
+ .hapticFeedback(.medium)
235
+
236
+ // Built-in staggered list items (always available)
237
+ ItemRow(item: items[index]).staggeredAppear(index: index)
238
+
239
+ // Built-in shadow and slide (always available)
240
+ CardView(item: item).cardShadow()
241
+ EmptyStateView().slideIn()
242
+
243
+ // Built-in shimmer, pulse, heartBounce (always available)
244
+ RoundedRectangle(cornerRadius: 8).fill(Color(.systemGray5)).shimmer()
245
+ Circle().fill(.red).frame(width: 8).pulse()
246
+ Image(systemName: "heart.fill").heartBounce(isActive: isFavorite)
247
+
248
+ // ScrollEffects module (if integrated)
249
+ ParallaxHeaderView(height: 280) { AsyncImage(url: item.imageURL) }
250
+
251
+ // CelebrationEffects module (if integrated)
252
+ .celebrationOverlay(isPresented: $showCelebration, style: .confetti)
253
+ ```
254
+
255
+ 3. Wrap all applied animations with `.motionAware()` if MotionPreferences is integrated
256
+ 4. Do NOT add animation modifiers to screens not listed in the manifest
162
257
 
163
258
  ## Report Output
164
259
 
@@ -167,7 +262,7 @@ Write the report to `output/{app-name}/reports/05-customization.md` (append iOS
167
262
  ```markdown
168
263
  # Customization Report
169
264
 
170
- **Step:** 8
265
+ **Step:** 5
171
266
  **Skill:** ios-customizer
172
267
  **Timestamp:** {ISO 8601}
173
268
  **Result:** PASS
@@ -201,6 +296,11 @@ iOS (Swift / SwiftUI)
201
296
  - SyncManager methods updated: {list or "no changes needed"}
202
297
  - Data persistence verified: {yes/no}
203
298
 
299
+ ## Animation Modifiers Applied
300
+
301
+ - {modifier}: applied to {screen} — {description}
302
+ - MotionPreferences respected: {yes/no/N/A}
303
+
204
304
  ## Potential Issues
205
305
 
206
306
  - {any concerns or items needing manual review}
@@ -212,7 +312,7 @@ Update `output/{app-name}/reports/summary.json` — read the file, append this s
212
312
 
213
313
  ```json
214
314
  {
215
- "step": 8,
315
+ "step": 5,
216
316
  "name": "ios-customization",
217
317
  "startedAt": "{ISO 8601 timestamp}",
218
318
  "durationSeconds": 0,
@@ -9,7 +9,7 @@ Integrate selected shared modules by reading reference implementations from `tem
9
9
 
10
10
  ## Context You Need
11
11
 
12
- - Module selection report (`reports/02b-module-selection.md`)
12
+ - Catalog analysis report (`reports/02-catalog-analysis.md`) — template + module selection
13
13
  - Customization manifest (`reports/customization-manifest.md`) — module integration plan
14
14
  - Platform, app name, bundle ID
15
15
  - AppConfig file path
@@ -91,27 +91,100 @@ React Native templates use a `ThemeContext.tsx`:
91
91
  - Apply corner radius and spacing tokens
92
92
  - Apply typography settings (font sizes, weights)
93
93
 
94
- ### Step 5 — Data Layer & Mock Data
94
+ ### Step 4.5 — Visual Polish Application
95
+
96
+ Apply the **Visual Polish Plan** from the manifest. MANDATORY for every build.
97
+
98
+ 1. **Shadows**: Platform-aware shadow styles on all cards (`shadowColor`/`shadowOffset`/`shadowRadius` + `elevation`).
99
+ 2. **Gradients**: `expo-linear-gradient` `LinearGradient` on hero sections and CTAs.
100
+ 3. **Press feedback**: Scale animation (0.95, spring) on all TouchableOpacity. Wrap in `ScaleButton` component.
101
+ 4. **Staggered animations**: `useStaggeredAppear(index)` on all FlatList items.
102
+ 5. **Empty states**: Gradient circle behind icon + `useSlideIn()` animation.
103
+ 6. **Blur/glass**: `expo-blur` BlurView on modal/sheet backgrounds.
104
+ 7. **Haptic**: `expo-haptics` on favorite toggles and primary actions.
105
+
106
+ ### Step 5 — Data Layer & Offline Infrastructure
107
+
108
+ Templates include an **offline-first data layer**:
95
109
 
96
110
  **Files you should NOT modify** (generic infrastructure):
97
111
  - `src/data/DataRepository.ts` — interface definition
112
+ - `src/data/NetworkMonitor.ts` — connectivity detection
113
+ - `src/data/LocalPersistence.ts` — JSON file persistence
114
+ - `src/components/OfflineBanner.tsx` — offline status banner
98
115
  - `src/theme/ThemeContext.tsx` — theme provider
99
116
 
100
117
  **Files you MAY need to update** (domain-specific):
101
- - `src/mock/MockDataProvider.ts` — seed data already updated in Step 4. Verify:
102
- - Seed data matches the new domain
103
- - All CRUD methods work with correct entity types
104
- - Subscription/onChange pattern is working
105
- - Reset method references correct defaults
118
+ - `src/mock/MockDataProvider.ts` — seed data already updated in Step 4. Verify seed data, CRUD methods, subscription pattern, and reset defaults
119
+ - `src/data/SyncManager.ts` if entity types were renamed, update domain methods
120
+
121
+ **ViewModel patterns** use `DataSourceResolver`, not `MockDataProvider` directly:
122
+ ```tsx
123
+ import { DataSourceResolver } from '../data/DataSourceResolver';
124
+
125
+ export function useHomeViewModel() {
126
+ const repository = DataSourceResolver.repository;
127
+ const [items, setItems] = useState<Item[]>([]);
128
+ useEffect(() => {
129
+ setItems(repository.getItems());
130
+ const unsubscribe = repository.subscribe(() => setItems(repository.getItems()));
131
+ return unsubscribe;
132
+ }, []);
133
+ return { items };
134
+ }
135
+ ```
106
136
 
107
- ### Step 6 MockDataProvider Verification
137
+ **OfflineBanner integration**add to main navigation screens:
138
+ ```tsx
139
+ <View style={{ flex: 1 }}>
140
+ <OfflineBanner />
141
+ {/* ... rest of screen content */}
142
+ </View>
143
+ ```
144
+
145
+ ### Step 6 — Data Layer Verification
108
146
 
109
- Verify the MockDataProvider uses correct patterns:
110
- - Implements all DataRepository methods
111
- - ViewModel hooks use MockDataProvider correctly
147
+ Verify:
148
+ - `DataRepository` interface matches MockDataProvider's public methods
149
+ - MockDataProvider implements DataRepository
150
+ - `DataSourceResolver` returns the correct implementation
151
+ - ViewModel hooks use `DataSourceResolver.repository`, not `MockDataProvider` directly
112
152
  - Seed data matches the new domain
113
153
  - CRUD methods reference correct entity types
114
154
 
155
+ ### Step 6.5 — Apply Animation Modifiers (if animation modules are integrated)
156
+
157
+ If the manifest includes an **"Animation & Sensory Plan"** section:
158
+
159
+ 1. Read the "Per-Screen Animation Modifiers" table
160
+ 2. Apply the assigned modifiers using imported module hooks/components:
161
+
162
+ ```typescript
163
+ // Built-in (always available)
164
+ import { useScaleOnPress, useStaggeredAppear, useSlideIn, cardShadowStyle, useShimmer, usePulse, useHeartBounce } from '../animation/useAnimatedList';
165
+ const { style: pressStyle, onPressIn, onPressOut } = useScaleOnPress();
166
+ const listItemStyle = useStaggeredAppear(index);
167
+ <View style={[styles.card, cardShadowStyle()]}>{/* content */}</View>
168
+ <Animated.View style={[styles.placeholder, useShimmer()]} /> // loading
169
+ <Animated.View style={[styles.dot, usePulse()]} /> // live indicator
170
+ <Animated.View style={useHeartBounce(isFav)}><HeartIcon /></Animated.View> // favorite
171
+
172
+ // Modules (if integrated)
173
+ import { ParallaxHeader } from '../shared/ScrollEffects';
174
+ <ParallaxHeader height={280} imageSource={item.imageUrl} />
175
+ ```
176
+
177
+ 3. Wrap with `useMotionPreferences` checks if MotionPreferences is integrated
178
+ 4. Do NOT add animation modifiers to screens not listed in the manifest
179
+
180
+ ### Step 6.7 — App Icon (if applicable)
181
+
182
+ React Native apps target both iOS and Android. App icon customization is handled per-platform:
183
+ - **iOS**: If `scripts/generate-app-icon.swift` exists, run it with SF Symbol + background color from manifest
184
+ - **Android**: If `templates/android/ICON_VECTORS.md` exists, update `ic_launcher_foreground.xml` and `ic_launcher_background` color
185
+
186
+ If scripts/resources are not available, skip — default icons will be used.
187
+
115
188
  ## Report Output
116
189
 
117
190
  Write the report to `output/{app-name}/reports/05-customization.md`:
@@ -144,6 +217,17 @@ React Native (TypeScript)
144
217
  - Empty states: {count}
145
218
  - CTAs updated: {count}
146
219
 
220
+ ## Offline Infrastructure
221
+
222
+ - OfflineBanner integrated: {yes/no}
223
+ - SyncManager methods updated: {list or "no changes needed"}
224
+ - Data persistence verified: {yes/no}
225
+
226
+ ## Animation Modifiers Applied
227
+
228
+ - {modifier}: applied to {screen} — {description}
229
+ - MotionPreferences respected: {yes/no/N/A}
230
+
147
231
  ## Potential Issues
148
232
 
149
233
  - {any concerns}
@@ -191,8 +275,10 @@ Templates include `testID` props on all interactive elements and a `TESTING_MANI
191
275
  - ONLY edit files under `output/` — never touch `templates/`
192
276
  - Ensure all imports resolve after your changes
193
277
  - Preserve `MockDataProvider` CRUD methods and `reset()` function
278
+ - Do NOT modify NetworkMonitor, LocalPersistence, or OfflineBanner
279
+ - Ensure OfflineBanner is integrated into main navigation screens
194
280
  - Use `testID` props on ALL interactive elements
195
- - Follow `{screen}_{element}_{role}` convention for new test IDs
281
+ - Follow `{screen}_{element}_{role}` convention for new test IDs (see `templates/TEST_ID_CONVENTIONS.md`)
196
282
  - Use `StyleSheet.create()` for styles, not inline objects
197
283
  - Use functional components with TypeScript
198
284
  - Keep React Navigation structure intact
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: test-planner
3
+ description: Analyzes app source code to generate a structured test plan before any simulator interaction. Reads Views, ViewModels, AppConfig, MockDataProvider, and TESTING_MANIFEST to produce a comprehensive test matrix.
4
+ allowed-tools: Read, Grep, Glob, LS
5
+ context: fork
6
+ agent: Explore
7
+ ---
8
+
9
+ # Test Planner Skill
10
+
11
+ Analyze app source code and produce a structured test plan. Runs offline — no simulator needed.
12
+
13
+ ## Instructions
14
+
15
+ ### Step 1 — Gather App Inventory
16
+
17
+ Read from the app directory:
18
+ 1. `TESTING_MANIFEST.md` — test IDs, screen inventory, element counts
19
+ 2. `AppConfig` — feature flags, business rules (`.swift`/`.kt`/`.ts`)
20
+ 3. `MockDataProvider` — data counts, categories, structure
21
+ 4. `customization-manifest.md` (if exists) — screen descriptions, expected behavior
22
+ 5. `summary.json` (if exists) — previous results, template, brand
23
+ 6. `requirements.md` or `PRD.md` (if exists) — business-logic test cases
24
+
25
+ ### Step 2 — Scan Screens + ViewModels
26
+
27
+ Read all View files (`*View.swift`, `*Screen.kt`, `*Screen.tsx`) and ViewModel files. Extract per screen:
28
+ - Interactive elements (buttons, toggles, fields, list items, FABs)
29
+ - Navigation targets
30
+ - Data dependencies from MockDataProvider
31
+ - Feature flags controlling visibility
32
+ - State transitions and CRUD operations
33
+
34
+ ### Step 3 — Build Test Matrix
35
+
36
+ For each screen, create a checklist:
37
+
38
+ ```markdown
39
+ ### Screen: {Name}
40
+ **File:** {path} | **Elements:** {N}
41
+
42
+ #### Rendering
43
+ - [ ] Renders without crash
44
+ - [ ] Correct data shown ({N} items)
45
+ - [ ] No template leftover text
46
+
47
+ #### Navigation
48
+ - [ ] Navigate to screen, navigate back
49
+
50
+ #### Interactions
51
+ - [ ] {Button}: tap triggers {action}
52
+ - [ ] {Toggle}: state changes
53
+ ```
54
+
55
+ Add sections for: Edge Cases (empty states, long text, rapid taps, deep navigation), Regression Checks (leftovers, a11y IDs, images, back nav), Requirements-Based Tests (if PRD exists).
56
+
57
+ ### Step 4 — Assign Priorities
58
+
59
+ - **P0** — crashes, data loss, broken navigation
60
+ - **P1** — features don't work, wrong data
61
+ - **P2** — visual, accessibility, minor UX
62
+ - **P3** — cosmetic
63
+
64
+ ## Report Output
65
+
66
+ Write `output/{app-name}/reports/10-test-plan.md`. Update `summary.json` with step entry (step: 10, name: "test-plan").
67
+
68
+ ## Rules
69
+
70
+ - READ-ONLY — do NOT modify source files or boot simulators
71
+ - Every interactive element must have at least one test case
72
+ - Test plan must be detailed enough for another agent to execute without reading source
@@ -12,8 +12,10 @@ These agent definition files (`.md`) are **preserved as a fallback** for when Cu
12
12
  |---|---|
13
13
  | `security-auditor.md` (Phase 1) | `.cursor/skills/prompt-validator/SKILL.md` |
14
14
  | `security-auditor.md` (Phase 2) | `.cursor/skills/code-auditor/SKILL.md` |
15
- | `template-selector.md` | `.cursor/skills/template-selector/SKILL.md` |
15
+ | `template-selector.md` | `.cursor/skills/catalog-analyzer/SKILL.md` (merged with module-selector) |
16
16
  | `design-selector.md` | `.cursor/skills/design-selector/SKILL.md` |
17
+ | `catalog-analyzer.md` | `.cursor/skills/catalog-analyzer/SKILL.md` (template + module selection) |
18
+ | `react-native-customizer.md` | `.cursor/skills/react-native-customizer/SKILL.md` |
17
19
  | `ios-customizer.md` | `.cursor/skills/ios-customizer/SKILL.md` |
18
20
  | `android-customizer.md` | `.cursor/skills/android-customizer/SKILL.md` |
19
21
  | `build-tester.md` | `.cursor/skills/build-tester/SKILL.md` |
@@ -123,18 +123,19 @@ private val LightColorScheme = lightColorScheme(
123
123
  - Use Material 3 color roles (primary, secondary, tertiary, surface, etc.)
124
124
  - Keep `dynamicColor` support if present
125
125
 
126
- ### MockDataProvider Updates
127
- Android MockDataProvider uses companion object with functions:
126
+ ### Data Layer
127
+ Templates use a `DataRepository` interface with `DataSourceResolver`:
128
128
  ```kotlin
129
- object MockDataProvider {
130
- fun getServices(): List<Service> = listOf(...)
131
- fun getProviders(): List<Provider> = listOf(...)
132
- }
129
+ // Screens get the repository from DataSourceResolver
130
+ val repository = remember { DataSourceResolver.repository }
131
+ val items by repository.items.collectAsState()
132
+ repository.addItem(newItem)
133
133
  ```
134
- - Keep the same function signatures
135
- - Update return values with domain-specific data
136
- - Use `UUID.randomUUID().toString()` for IDs
137
- - Use `LocalDateTime.now()` and `LocalDate` for dates
134
+ - ALWAYS use `DataSourceResolver.repository`, never `MockDataProvider` directly
135
+ - Preserve MockDataProvider CRUD functions and `reset()` method
136
+ - Do NOT modify NetworkMonitor, LocalPersistence, or OfflineBanner
137
+ - Verify NetworkMonitor is registered in the Application class
138
+ - Ensure OfflineBanner is integrated into main navigation composables
138
139
 
139
140
  ## Output
140
141
 
@@ -155,5 +156,8 @@ POTENTIAL ISSUES:
155
156
  - Ensure all `import` statements resolve after renaming
156
157
  - Keep `@HiltAndroidApp`, `@HiltViewModel`, `@AndroidEntryPoint` intact
157
158
  - Keep `build.gradle.kts` syntactically valid Kotlin DSL
158
- - Preserve `MockDataProvider` function signatures
159
+ - Preserve `MockDataProvider` CRUD functions and `reset()` method
160
+ - Do NOT modify NetworkMonitor, LocalPersistence, or OfflineBanner
159
161
  - Use Material 3 components (not legacy Material 2)
162
+ - Preserve ALL `Modifier.testTag()` calls — do NOT remove test IDs
163
+ - Follow `{screen}_{element}_{role}` convention for new test tags (see `templates/TEST_ID_CONVENTIONS.md`)
@@ -0,0 +1,83 @@
1
+ ---
2
+ name: catalog-analyzer
3
+ description: Selects the best template from CATALOG.md and shared modules from MODULES_CATALOG.md in a single pass. Uses selected template context to boost module selection accuracy via "Relevant Templates" column.
4
+ tools:
5
+ - Read
6
+ - Grep
7
+ - Glob
8
+ - LS
9
+ readonly: true
10
+ ---
11
+
12
+ # Catalog Analyzer
13
+
14
+ You are a specialised subagent for selecting the best mobile app template AND the best shared modules. You have deep knowledge of both catalogs and their selection criteria.
15
+
16
+ ## Logging Protocol
17
+
18
+ When you start, print:
19
+ `[SUBAGENT:catalog-analyzer] Starting — catalog analysis for "{app description}"`
20
+
21
+ When you finish, print:
22
+ `[SUBAGENT:catalog-analyzer] Completed — selected {TemplateName} (confidence: {high|medium|low}), {N} modules`
23
+
24
+ ## Instructions
25
+
26
+ ### Phase 1 — Template Selection
27
+
28
+ 1. Read `templates/CATALOG.md` thoroughly
29
+ 2. Given the user's app description and target platform, evaluate each template:
30
+ - Score against the "Best-For Keywords" in the decision matrix
31
+ - Check the "Best match when" criteria for each template
32
+ - Apply the "NOT a match when" rules to eliminate poor fits
33
+ - Consider the "Hybrid Apps" table if the app spans categories
34
+ 3. If no template is a strong match, follow the "When No Template Fits" guidance — pick the template with the most similar navigation and screen patterns
35
+ 4. Choose exactly ONE primary template
36
+
37
+ ### Phase 2 — Module Selection
38
+
39
+ 5. Read `templates/shared/MODULES_CATALOG.md` thoroughly
40
+ 6. For every module, match by keywords AND check "Relevant Templates" against the selected template:
41
+ - Keyword match + template match → strong include
42
+ - Keyword match + no template match → include with lower confidence
43
+ - No keyword match + template match → consider if implied by domain
44
+ 7. Apply BaaS heuristics (Firebase vs Supabase vs none)
45
+ 8. Check module dependencies — add missing ones
46
+ 9. Apply animation/sensory heuristics if description suggests premium feel
47
+ 10. Aim for 5-15 modules
48
+
49
+ ## Output Format
50
+
51
+ Return your answer in this exact format:
52
+
53
+ ```
54
+ SELECTED TEMPLATE: {TemplateName}
55
+ CONFIDENCE: high | medium | low
56
+ REASONING: {1-2 sentence explanation}
57
+ BORROW FROM: {other template name, if hybrid} or "none"
58
+ HYBRID NOTES: {what to borrow and why} or "n/a"
59
+
60
+ SELECTED MODULES ({N} total):
61
+ - {ModuleName}: {reason} [template boost: yes/no]
62
+ - ...
63
+
64
+ EXCLUDED MODULES:
65
+ - {ModuleName}: {reason for exclusion}
66
+ - ...
67
+
68
+ DEPENDENCIES ADDED:
69
+ - {ModuleName}: required by {other module}
70
+ - ...
71
+ ```
72
+
73
+ ## Rules
74
+
75
+ - Always recommend exactly ONE primary template
76
+ - If confidence is "low", explain what aspects of the user's request don't fit well
77
+ - For hybrid apps, identify which template to START with and what to borrow from the secondary template
78
+ - Do NOT recommend building from scratch — always pick the closest template
79
+ - Consider the platform (iOS vs Android vs React Native)
80
+ - Features covered by shared modules should NOT affect template scoring
81
+ - No modules are auto-included — every module must earn its place via keyword matching
82
+ - "Relevant Templates" is a boost signal, not a hard filter
83
+ - Aim for 5-15 modules — be selective, not exhaustive