@shaykec/app-agent 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/.claude/skills/ui-tester/SKILL.md +59 -0
  2. package/.cursor/skills/android-customizer/SKILL.md +50 -16
  3. package/.cursor/skills/appconfig-customization/SKILL.md +15 -0
  4. package/.cursor/skills/customization-planner/SKILL.md +17 -1
  5. package/.cursor/skills/ios-customizer/SKILL.md +54 -13
  6. package/.cursor/skills/mock-data-update/SKILL.md +11 -3
  7. package/.cursor/skills/ui-tester/SKILL.md +59 -0
  8. package/dist/cli.d.ts +18 -4
  9. package/dist/cli.d.ts.map +1 -1
  10. package/dist/cli.js +134 -14
  11. package/dist/cli.js.map +1 -1
  12. package/dist/github.d.ts +5 -0
  13. package/dist/github.d.ts.map +1 -1
  14. package/dist/github.js +27 -0
  15. package/dist/github.js.map +1 -1
  16. package/dist/index.js +218 -24
  17. package/dist/index.js.map +1 -1
  18. package/dist/preview-generator.d.ts +35 -0
  19. package/dist/preview-generator.d.ts.map +1 -0
  20. package/dist/preview-generator.js +546 -0
  21. package/dist/preview-generator.js.map +1 -0
  22. package/package.json +4 -1
  23. package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/features/booking/BookingScreen.kt +5 -3
  24. package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/features/bookings/BookingsScreen.kt +7 -5
  25. package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/features/discovery/DiscoveryViewModel.kt +3 -2
  26. package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/features/profile/ProfileScreen.kt +4 -2
  27. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/AppConfig.kt +9 -0
  28. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/data/DataRepository.kt +23 -0
  29. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/data/DataSourceResolver.kt +23 -0
  30. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/calls/CallsScreen.kt +4 -3
  31. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/contacts/ContactsScreen.kt +3 -2
  32. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/conversations/ChatScreen.kt +11 -10
  33. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/conversations/ConversationsScreen.kt +5 -5
  34. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/navigation/Navigation.kt +4 -2
  35. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/settings/SettingsScreen.kt +6 -4
  36. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/mock/MockDataProvider.kt +7 -7
  37. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/data/DataRepository.kt +46 -0
  38. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/data/DataSourceResolver.kt +23 -0
  39. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/alerts/AlertsScreen.kt +4 -3
  40. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/dashboard/DashboardScreen.kt +3 -2
  41. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/datasources/DataSourcesScreen.kt +3 -2
  42. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/reports/ReportsScreen.kt +3 -2
  43. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/mock/MockDataProvider.kt +16 -15
  44. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/AppConfig.kt +9 -0
  45. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/calendar/CalendarScreen.kt +5 -5
  46. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/chores/ChoreBoardScreen.kt +3 -3
  47. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/familyhub/FamilyHubScreen.kt +4 -4
  48. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/gallery/GalleryScreen.kt +3 -3
  49. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/members/MembersListScreen.kt +5 -5
  50. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/rewards/RewardsScreen.kt +5 -5
  51. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/settings/SettingsScreen.kt +3 -3
  52. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/mock/MockDataProvider.kt +29 -32
  53. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/AppConfig.kt +9 -0
  54. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/data/DataRepository.kt +70 -0
  55. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/data/DataSourceResolver.kt +23 -0
  56. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/features/budgets/BudgetsScreen.kt +3 -2
  57. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/features/goals/GoalsScreen.kt +5 -3
  58. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/features/home/HomeScreen.kt +8 -7
  59. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/features/settings/SettingsScreen.kt +0 -1
  60. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/features/transactions/TransactionsScreen.kt +9 -4
  61. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/mock/MockDataProvider.kt +103 -11
  62. package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/data/DataRepository.kt +19 -0
  63. package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/features/leaderboard/LeaderboardScreen.kt +2 -1
  64. package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/features/results/ResultsScreen.kt +3 -2
  65. package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/data/DataRepository.kt +46 -0
  66. package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/data/DataSourceResolver.kt +23 -0
  67. package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/features/dashboard/DashboardScreen.kt +3 -2
  68. package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/features/profile/ProfileScreen.kt +3 -2
  69. package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/features/workouts/WorkoutListScreen.kt +3 -2
  70. package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/mock/MockDataProvider.kt +13 -13
  71. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/AppConfig.kt +9 -0
  72. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/data/DataRepository.kt +48 -0
  73. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/data/DataSourceResolver.kt +23 -0
  74. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/features/courses/CourseListScreen.kt +4 -3
  75. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/features/leaderboard/LeaderboardScreen.kt +3 -2
  76. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/features/profile/ProfileScreen.kt +3 -2
  77. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/features/progress/ProgressDashboardScreen.kt +3 -2
  78. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/mock/MockDataProvider.kt +41 -11
  79. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/data/DataSourceResolver.kt +11 -6
  80. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/di/AppModule.kt +11 -2
  81. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/favorites/FavoritesViewModel.kt +4 -4
  82. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/map/MapViewModel.kt +4 -4
  83. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/place/PlaceDetailViewModel.kt +5 -5
  84. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/place/PlaceListViewModel.kt +4 -4
  85. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/profile/ProfileViewModel.kt +5 -5
  86. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/route/RouteViewModel.kt +3 -3
  87. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/search/SearchViewModel.kt +3 -3
  88. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/settings/SettingsViewModel.kt +3 -3
  89. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/mock/MockDataProvider.kt +54 -41
  90. package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/AppConfig.kt +9 -0
  91. package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/features/browse/BrowseScreen.kt +2 -1
  92. package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/features/detail/DetailScreen.kt +3 -1
  93. package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/features/home/HomeScreen.kt +3 -2
  94. package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/mock/MockDataProvider.kt +63 -132
  95. package/templates/android/ReferenceTemplate/app/src/main/kotlin/com/appship/reference/AppConfig.kt +9 -0
  96. package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/features/home/HomeViewModel.kt +2 -1
  97. package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/features/products/ProductViewModels.kt +12 -7
  98. package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/mock/MockDataProvider.kt +3 -3
  99. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/data/DataRepository.kt +0 -1
  100. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/createpost/CreatePostScreen.kt +3 -2
  101. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/feed/CommentsScreen.kt +4 -3
  102. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/feed/FeedScreen.kt +3 -2
  103. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/messages/MessagesScreen.kt +9 -8
  104. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/notifications/NotificationsScreen.kt +3 -2
  105. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/profile/ProfileScreen.kt +5 -4
  106. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/search/SearchScreen.kt +3 -2
  107. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/AppConfig.kt +9 -0
  108. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/data/DataRepository.kt +38 -0
  109. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/data/DataSourceResolver.kt +23 -0
  110. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/calendar/CalendarScreen.kt +0 -1
  111. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/inbox/InboxScreen.kt +4 -2
  112. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/kanban/KanbanBoardScreen.kt +5 -3
  113. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/projects/ProjectDetailScreen.kt +9 -5
  114. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/projects/ProjectListScreen.kt +6 -4
  115. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/search/SearchScreen.kt +1 -1
  116. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/tasks/TaskDetailScreen.kt +0 -1
  117. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/mock/MockDataProvider.kt +13 -12
  118. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/AppConfig.kt +9 -0
  119. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/data/DataRepository.kt +34 -0
  120. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/data/DataSourceResolver.kt +23 -0
  121. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/features/achievements/AchievementsViewModel.kt +4 -2
  122. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/features/dashboard/TodayViewModel.kt +4 -2
  123. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/features/habits/HabitDetailViewModel.kt +4 -2
  124. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/features/habits/HabitsListViewModel.kt +4 -2
  125. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/mock/MockDataProvider.kt +13 -11
  126. package/templates/ios/ChatTemplate/ChatTemplate/App/AppConfig.swift +9 -0
  127. package/templates/ios/ChatTemplate/ChatTemplate/Data/DataRepository.swift +43 -0
  128. package/templates/ios/ChatTemplate/ChatTemplate/Data/DataSourceResolver.swift +20 -0
  129. package/templates/ios/DashTemplate/DashTemplate/App/AppConfig.swift +9 -0
  130. package/templates/ios/DashTemplate/DashTemplate/Data/DataRepository.swift +53 -0
  131. package/templates/ios/DashTemplate/DashTemplate/MockData/MockDataProvider.swift +1 -1
  132. package/templates/ios/FamilyTemplate/FamilyTemplate/App/AppConfig.swift +9 -0
  133. package/templates/ios/FamilyTemplate/FamilyTemplate/App/FamilyTemplateApp.swift +4 -2
  134. package/templates/ios/FamilyTemplate/FamilyTemplate/MockData/MockDataProvider.swift +1 -1
  135. package/templates/ios/FinanceTemplate/FinanceTemplate/App/AppConfig.swift +9 -0
  136. package/templates/ios/FinanceTemplate/FinanceTemplate/Data/DataRepository.swift +75 -0
  137. package/templates/ios/FinanceTemplate/FinanceTemplate/Data/DataSourceResolver.swift +20 -0
  138. package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Budgets/BudgetsView.swift +3 -1
  139. package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Goals/GoalsView.swift +3 -1
  140. package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Home/HomeView.swift +13 -6
  141. package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Settings/SettingsView.swift +6 -2
  142. package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Transactions/AddTransactionView.swift +4 -2
  143. package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Transactions/TransactionsView.swift +3 -1
  144. package/templates/ios/FinanceTemplate/FinanceTemplate/MockData/MockDataProvider.swift +1 -1
  145. package/templates/ios/GameTemplate/GameTemplate/App/AppConfig.swift +9 -0
  146. package/templates/ios/GameTemplate/GameTemplate/Data/DataRepository.swift +30 -0
  147. package/templates/ios/GameTemplate/GameTemplate/Data/DataSourceResolver.swift +20 -0
  148. package/templates/ios/GameTemplate/GameTemplate/MockData/MockDataProvider.swift +1 -1
  149. package/templates/ios/HealthTemplate/HealthTemplate/App/AppConfig.swift +9 -0
  150. package/templates/ios/HealthTemplate/HealthTemplate/Data/DataRepository.swift +60 -0
  151. package/templates/ios/HealthTemplate/HealthTemplate/MockData/MockDataProvider.swift +1 -1
  152. package/templates/ios/LearnTemplate/LearnTemplate/App/AppConfig.swift +9 -0
  153. package/templates/ios/LearnTemplate/LearnTemplate/Features/Courses/CourseDetailView.swift +3 -2
  154. package/templates/ios/LearnTemplate/LearnTemplate/Features/Courses/CourseListView.swift +3 -2
  155. package/templates/ios/LearnTemplate/LearnTemplate/Features/Flashcards/FlashcardView.swift +2 -1
  156. package/templates/ios/LearnTemplate/LearnTemplate/Features/Leaderboard/LeaderboardView.swift +2 -1
  157. package/templates/ios/LearnTemplate/LearnTemplate/Features/Lessons/LessonPlayerView.swift +4 -2
  158. package/templates/ios/LearnTemplate/LearnTemplate/Features/Profile/ProfileView.swift +4 -2
  159. package/templates/ios/LearnTemplate/LearnTemplate/Features/Progress/ProgressDashboardView.swift +3 -2
  160. package/templates/ios/LearnTemplate/LearnTemplate/Features/Quiz/QuizView.swift +2 -1
  161. package/templates/ios/LearnTemplate/LearnTemplate/MockData/MockDataProvider.swift +1 -1
  162. package/templates/ios/MediaTemplate/MediaTemplate/App/AppConfig.swift +9 -0
  163. package/templates/ios/MediaTemplate/MediaTemplate/Data/DataRepository.swift +52 -0
  164. package/templates/ios/MediaTemplate/MediaTemplate/Data/DataSourceResolver.swift +20 -0
  165. package/templates/ios/MediaTemplate/MediaTemplate/MockData/MockDataProvider.swift +1 -1
  166. package/templates/ios/ReferenceTemplate/ReferenceTemplate/App/AppConfig.swift +9 -0
  167. package/templates/ios/ReferenceTemplate/ReferenceTemplate/Data/DataRepository.swift +28 -0
  168. package/templates/ios/ReferenceTemplate/ReferenceTemplate/Data/DataSourceResolver.swift +20 -0
  169. package/templates/ios/ReferenceTemplate/ReferenceTemplate/MockData/MockDataProvider.swift +1 -1
  170. package/templates/ios/TaskTemplate/TaskTemplate/App/AppConfig.swift +9 -0
  171. package/templates/ios/TaskTemplate/TaskTemplate/Data/DataRepository.swift +38 -0
  172. package/templates/ios/TaskTemplate/TaskTemplate/Data/DataSourceResolver.swift +20 -0
  173. package/templates/ios/TaskTemplate/TaskTemplate/Features/Calendar/CalendarView.swift +6 -2
  174. package/templates/ios/TaskTemplate/TaskTemplate/Features/Inbox/InboxView.swift +2 -1
  175. package/templates/ios/TaskTemplate/TaskTemplate/Features/Kanban/KanbanBoardView.swift +9 -3
  176. package/templates/ios/TaskTemplate/TaskTemplate/Features/Projects/ProjectDetailView.swift +3 -1
  177. package/templates/ios/TaskTemplate/TaskTemplate/Features/Projects/ProjectListView.swift +3 -1
  178. package/templates/ios/TaskTemplate/TaskTemplate/Features/Search/SearchView.swift +3 -1
  179. package/templates/ios/TaskTemplate/TaskTemplate/MockData/MockDataProvider.swift +1 -1
  180. package/templates/ios/TrackTemplate/TrackTemplate/App/AppConfig.swift +9 -0
  181. package/templates/ios/TrackTemplate/TrackTemplate/Data/DataRepository.swift +29 -0
  182. package/templates/ios/TrackTemplate/TrackTemplate/Data/DataSourceResolver.swift +20 -0
  183. package/templates/ios/TrackTemplate/TrackTemplate/MockData/MockDataProvider.swift +1 -1
  184. package/templates/ios/TrackTemplate/TrackTemplate/Services/HabitManager.swift +1 -1
@@ -432,6 +432,65 @@ Update `output/{app-name}/reports/summary.json` — read the file, append this s
432
432
  - Set `"filesWritten"` to the total count of files created/modified
433
433
  - Set `"duration"` to the total elapsed time
434
434
 
435
+ ## Preview Capture
436
+
437
+ During testing, save screenshots and element tree data for the web preview feature. This enables `--preview <app-name>` to generate a clickable prototype.
438
+
439
+ ### When to Capture
440
+
441
+ After inspecting each screen (in Phase 1, Step 2), save the screenshot and extract interactive element bounding boxes.
442
+
443
+ ### How to Capture
444
+
445
+ 1. **Create the preview directory** if it doesn't exist: `output/{app-name}/preview/`
446
+
447
+ 2. **For each screen you inspect**, save the screenshot:
448
+ - Use `inspect()` as normal — it returns a screenshot and element tree
449
+ - Save the screenshot image to `output/{app-name}/preview/{screen-id}.png`
450
+ - `screen-id` should be a kebab-case identifier: `home`, `explore`, `item-detail`, `settings`, `profile`, etc.
451
+ - From the element tree, extract bounding boxes of interactive elements (buttons, list items, tabs, etc.)
452
+ - Record which screen each interactive element navigates to (based on what you observed during testing)
453
+
454
+ 3. **After all screens are tested**, write `output/{app-name}/preview/screens.json`:
455
+
456
+ ```json
457
+ {
458
+ "appName": "{App Display Name}",
459
+ "platform": "{ios|android}",
460
+ "template": "{template name if known}",
461
+ "designBrand": "{brand name if known}",
462
+ "screens": [
463
+ {
464
+ "id": "{screen-id}",
465
+ "label": "{Human Readable Screen Name}",
466
+ "screenshot": "{screen-id}.png",
467
+ "hotspots": [
468
+ {
469
+ "x": 0, "y": 0, "w": 0, "h": 0,
470
+ "target": "{target-screen-id}",
471
+ "label": "{Element Label}"
472
+ }
473
+ ]
474
+ }
475
+ ],
476
+ "initialScreen": "{first-screen-id}"
477
+ }
478
+ ```
479
+
480
+ ### Hotspot Rules
481
+
482
+ - `x`, `y`, `w`, `h` are bounding box coordinates in screenshot pixel space
483
+ - `target` is the `id` of the screen that element navigates to (must match a screen in the `screens` array)
484
+ - Only include hotspots for elements that navigate to another screen in the app (tabs, list items, back buttons)
485
+ - Omit hotspots for elements that don't navigate (toggles, text fields, action sheets)
486
+ - If you don't know the target screen for an element, omit that hotspot
487
+
488
+ ### Important
489
+
490
+ - This capture is **in addition to** normal testing — do NOT skip any testing steps
491
+ - The preview directory and files are only used for the web preview feature
492
+ - If preview capture fails for any reason, log a warning but do NOT fail the test
493
+
435
494
  ## Important Rules
436
495
 
437
496
  - ONLY use ai-tester MCP tools for device interaction — NOT shell commands like `xcrun simctl`
@@ -144,19 +144,26 @@ Templates now include an **offline-first data layer**. Understand these componen
144
144
  - `reset()` function references correct defaults
145
145
  - `data/SyncManager.kt` — if entity types were renamed, update domain methods
146
146
 
147
- **ViewModel/Screen patterns** (how screens consume data):
147
+ **Screen/ViewModel patterns** (how screens consume data):
148
+
149
+ Screens and ViewModels use the `DataRepository` interface abstraction, not `MockDataProvider` directly:
148
150
  ```kotlin
149
- // Screens collect StateFlow
150
- val products by MockDataProvider.products.collectAsState()
151
+ // Screens get the repository from DataSourceResolver
152
+ val repository = remember { DataSourceResolver.repository }
153
+ val items by repository.items.collectAsState()
154
+ val categories by repository.categories.collectAsState()
151
155
 
152
- // ViewModels read from MockDataProvider
153
- val products = MockDataProvider.products.value
156
+ // CRUD via the repository
157
+ repository.addItem(newItem)
158
+ repository.deleteItem(item)
159
+ repository.toggleFavorite(item)
154
160
 
155
- // CRUD via SyncManager
161
+ // If SyncManager exists, it wraps the repository
156
162
  SyncManager.addProduct(newProduct)
157
- SyncManager.deleteProduct(id)
158
163
  ```
159
164
 
165
+ When customizing screens or ViewModels, ALWAYS use `DataSourceResolver.repository`, never `MockDataProvider` directly. This ensures the app works with any data source (mock, localStorage, Firebase, Supabase, custom API).
166
+
160
167
  **OfflineBanner integration** — add to main navigation:
161
168
  ```kotlin
162
169
  Column {
@@ -176,26 +183,53 @@ class MyApplication : Application() {
176
183
  }
177
184
  ```
178
185
 
179
- ### Step 7 — MockDataProvider Verification
186
+ ### Step 7 — Data Layer Verification
187
+
188
+ Verify the data layer uses the correct patterns:
180
189
 
181
- Verify MockDataProvider uses the correct patterns:
190
+ **DataRepository interface:**
191
+ ```kotlin
192
+ interface DataRepository {
193
+ val items: StateFlow<List<Item>> // Domain entities
194
+ val categories: StateFlow<List<Category>>
195
+ val favoriteItems: StateFlow<List<Item>>
196
+ fun loadData()
197
+ fun addItem(item: Item)
198
+ // ... all CRUD + query methods
199
+ }
200
+ ```
182
201
 
202
+ **MockDataProvider (implements DataRepository):**
183
203
  ```kotlin
184
- object MockDataProvider {
204
+ object MockDataProvider : DataRepository {
185
205
  private val _products = MutableStateFlow(defaultProducts)
186
- val products: StateFlow<List<Product>> = _products.asStateFlow()
206
+ override val products: StateFlow<List<Product>> = _products.asStateFlow()
187
207
 
188
208
  val defaultProducts = listOf(...) // Seed data
189
209
 
190
- fun addProduct(product: Product) { ... } // CRUD
210
+ override fun addProduct(product: Product) { ... } // CRUD
191
211
  fun reset() { ... } // Reset to defaults
192
212
  }
193
213
  ```
194
214
 
195
- - Verify seed data matches the new domain
196
- - Ensure CRUD functions reference correct entity types
197
- - Verify `reset()` works correctly
198
- - Check that helper functions use `.value` to read from StateFlows
215
+ **DataSourceResolver:**
216
+ ```kotlin
217
+ object DataSourceResolver {
218
+ val repository: DataRepository
219
+ get() = when (AppConfig.DataSource.active) {
220
+ AppConfig.DataSource.SourceType.LOCAL_STORAGE -> MockDataProvider // TODO: LocalStorageProvider
221
+ AppConfig.DataSource.SourceType.MOCK -> MockDataProvider
222
+ }
223
+ }
224
+ ```
225
+
226
+ Verify:
227
+ - DataRepository interface matches MockDataProvider's public members
228
+ - MockDataProvider implements DataRepository with `override` on all members
229
+ - DataSourceResolver returns the correct implementation
230
+ - Screens use `DataSourceResolver.repository`, not `MockDataProvider` directly
231
+ - Seed data matches the new domain
232
+ - CRUD functions reference correct entity types
199
233
 
200
234
  ## Report Output
201
235
 
@@ -67,6 +67,21 @@ Work through each category in order:
67
67
  - If the design-system skill has not run yet, choose colours appropriate for the app's domain
68
68
  - Dark mode support — keep enabled (dark mode is handled by platform theme files)
69
69
 
70
+ #### CUSTOMIZE:DATASOURCE
71
+ - `DataSource.active` — set the active data source type
72
+ - Default is `.mock` during initial customization (so screens show populated data for testing)
73
+ - Set to `.localStorage` for the final shipped app (so users start with empty state)
74
+ - Other options (`.firebase`, `.supabase`, `.custom`) require BaaS shared modules to be integrated
75
+ - Example:
76
+ ```swift
77
+ // iOS
78
+ static let active: SourceType = .mock // Use .localStorage for production
79
+ ```
80
+ ```kotlin
81
+ // Android
82
+ val active: SourceType = SourceType.MOCK // Use LOCAL_STORAGE for production
83
+ ```
84
+
70
85
  #### CUSTOMIZE:CATEGORIES (if applicable)
71
86
  - Update category lists to match the app's domain
72
87
  - E.g., for a pet grooming booking app: "Grooming", "Bath", "Nail Trim", "Full Package"
@@ -144,7 +144,23 @@ Based on the app domain and the existing MockDataProvider structure:
144
144
  - **Categories:** List of 6-8 domain categories with names and icons
145
145
  - **Sample items:** For each category, 3-5 items with realistic names, descriptions, and values
146
146
  - Keep the same item counts as the template
147
- - Note any entity type renames needed for SyncManager
147
+ - Note any entity type renames needed for DataRepository protocol, DataSourceResolver, and SyncManager
148
+ - **Data source:** Default data source is `localStorage` (Core Data / Room). Mock data is for testing/dev.
149
+
150
+ ### Step 5b — Produce Data Repository Spec
151
+
152
+ Document how the DataRepository protocol needs to be updated for the new domain:
153
+
154
+ ```
155
+ DATA REPOSITORY:
156
+ Entity renames:
157
+ - Item → {DomainEntity} (e.g., Item → Recipe)
158
+ - Category → {DomainCategory} (e.g., Category → CuisineType)
159
+ Protocol updates:
160
+ - Property renames: items → {domainPlural} (e.g., items → recipes)
161
+ - Method renames: addItem → add{Entity} (e.g., addItem → addRecipe)
162
+ DataSource default: .mock (agent sets .mock during customization; switch to .localStorage for shipped app)
163
+ ```
148
164
 
149
165
  ### Step 6 — Produce Module Integration Plan
150
166
 
@@ -137,18 +137,31 @@ Templates now include an **offline-first data layer**. Understand these componen
137
137
  - `Data/SyncManager.swift` — if entity types were renamed, update domain methods
138
138
 
139
139
  **ViewModel patterns** (how views consume data):
140
+
141
+ ViewModels use the `DataRepository` protocol abstraction, not `MockDataProvider` directly:
140
142
  ```swift
141
- // ViewModels observe MockDataProvider.shared
142
- @ObservedObject var store = MockDataProvider.shared
143
+ // ViewModels depend on the DataRepository protocol
144
+ private let repository: any DataRepository
145
+
146
+ init(repository: any DataRepository = DataSourceResolver.repository) {
147
+ self.repository = repository
148
+ }
149
+
150
+ // Read data via the protocol
151
+ let items = repository.items
152
+ let categories = repository.categories
143
153
 
144
- // Or use EnvironmentObject if injected
145
- @EnvironmentObject var store: MockDataProvider
154
+ // CRUD via the protocol
155
+ repository.addItem(newItem)
156
+ repository.deleteItem(item)
157
+ repository.toggleFavorite(item)
146
158
 
147
- // CRUD via SyncManager
159
+ // If SyncManager exists, it wraps the repository
148
160
  SyncManager.shared.addProduct(newProduct)
149
- SyncManager.shared.deleteProduct(id)
150
161
  ```
151
162
 
163
+ When customizing ViewModels, ALWAYS use `repository` (from `DataSourceResolver`), never `MockDataProvider.shared` directly. This ensures the app works with any data source (mock, localStorage, Firebase, Supabase, custom API).
164
+
152
165
  **OfflineBanner integration** — add to main navigation views:
153
166
  ```swift
154
167
  VStack(spacing: 0) {
@@ -157,12 +170,25 @@ VStack(spacing: 0) {
157
170
  }
158
171
  ```
159
172
 
160
- ### Step 6 — MockDataProvider Verification
173
+ ### Step 6 — Data Layer Verification
174
+
175
+ Verify the data layer uses the correct patterns:
161
176
 
162
- Verify the MockDataProvider uses the correct patterns:
177
+ **DataRepository protocol:**
178
+ ```swift
179
+ protocol DataRepository: AnyObject {
180
+ var items: [Item] { get } // Domain entities
181
+ var categories: [Category] { get }
182
+ var favoriteItems: [Item] { get }
183
+ func loadData()
184
+ func addItem(_ item: Item)
185
+ // ... all CRUD + query methods
186
+ }
187
+ ```
163
188
 
189
+ **MockDataProvider (conforms to DataRepository):**
164
190
  ```swift
165
- class MockDataProvider: ObservableObject {
191
+ class MockDataProvider: ObservableObject, DataRepository {
166
192
  static let shared = MockDataProvider()
167
193
 
168
194
  @Published var products: [Product] // Reactive, mutable
@@ -174,10 +200,25 @@ class MockDataProvider: ObservableObject {
174
200
  }
175
201
  ```
176
202
 
177
- - Verify seed data matches the new domain
178
- - Ensure CRUD methods reference correct entity types
179
- - Verify `reset()` works correctly
180
- - 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 .localStorage: return MockDataProvider.shared // TODO: LocalStorageProvider
209
+ case .mock: return MockDataProvider.shared
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
181
222
 
182
223
  ## Report Output
183
224
 
@@ -27,7 +27,7 @@ Templates use an **offline-first architecture** with these components:
27
27
 
28
28
  ## Instructions
29
29
 
30
- ### Step 1 — Read the Current MockDataProvider
30
+ ### Step 1 — Read the Current MockDataProvider and DataRepository
31
31
 
32
32
  Read `MockDataProvider.swift` (iOS) or `MockDataProvider.kt` (Android). Understand:
33
33
  - What data models exist (products, services, users, transactions, etc.)
@@ -38,6 +38,8 @@ Read `MockDataProvider.swift` (iOS) or `MockDataProvider.kt` (Android). Understa
38
38
  - What properties each model has
39
39
  - How the data is structured (arrays, dictionaries, nested objects)
40
40
 
41
+ Also read `DataRepository.swift` (iOS) or `DataRepository.kt` (Android) — the protocol/interface that MockDataProvider conforms to. You'll need to update it if entity types are renamed.
42
+
41
43
  ### Step 2 — Plan Domain-Specific Data
42
44
 
43
45
  Based on the user's app description, plan realistic sample data. Examples:
@@ -80,9 +82,13 @@ For each collection:
80
82
  6. **Use realistic dates** — recent dates, not 1970 or 2099
81
83
  7. **Use realistic image placeholder names** — even if images don't exist, name them descriptively
82
84
 
83
- ### Step 4 — Update SyncManager Domain Methods (if entity types changed)
85
+ ### Step 4 — Update DataRepository Protocol and SyncManager (if entity types changed)
86
+
87
+ If the domain entity types have changed names (e.g., "product" → "drink"):
84
88
 
85
- If the domain entity types have changed names (e.g., "product" "drink"), update the SyncManager's domain methods to match. This is only needed if entity types were renamed. If they kept the same names, no changes needed.
89
+ 1. **DataRepository** Update the `DataRepository.swift/.kt` protocol/interface to use the new entity type names. The protocol must always mirror MockDataProvider's public interface.
90
+ 2. **DataSourceResolver** — If the protocol name changed, update the resolver's return type.
91
+ 3. **SyncManager** — Update domain methods to match the new entity names. Only needed if entity types were renamed.
86
92
 
87
93
  ### Step 5 — Verify Consistency
88
94
 
@@ -117,6 +123,8 @@ After rewriting the mock data, update `output/{app-name}/reports/summary.json`
117
123
  - **NEVER change the infrastructure files** (NetworkMonitor, LocalPersistence, OfflineBanner)
118
124
  - **NEVER change model property names** — only change VALUES in seed data
119
125
  - **DO update `default*` / `makeDefault*` seed data properties** — these are what you customize
126
+ - **DO update DataRepository** if entity types are renamed — the protocol must mirror MockDataProvider
127
+ - **DO update DataSourceResolver** if the protocol reference changes
120
128
  - Keep data realistic and professional — this data shows in the UI during demos
121
129
  - Maintain approximately the same data volume as the original template
122
130
  - If the template uses image asset names, update them to be descriptive but don't worry about actual image files
@@ -466,6 +466,65 @@ Update `output/{app-name}/reports/summary.json` — read the file, append this s
466
466
  - Set `"filesWritten"` to the total count of files created/modified
467
467
  - Set `"duration"` to the total elapsed time
468
468
 
469
+ ## Preview Capture
470
+
471
+ During testing, save screenshots and element tree data for the web preview feature. This enables `--preview <app-name>` to generate a clickable prototype.
472
+
473
+ ### When to Capture
474
+
475
+ After inspecting each screen (in Phase 1, Step 2), save the screenshot and extract interactive element bounding boxes.
476
+
477
+ ### How to Capture
478
+
479
+ 1. **Create the preview directory** if it doesn't exist: `output/{app-name}/preview/`
480
+
481
+ 2. **For each screen you inspect**, save the screenshot:
482
+ - Use `inspect()` as normal — it returns a screenshot and element tree
483
+ - Save the screenshot image to `output/{app-name}/preview/{screen-id}.png`
484
+ - `screen-id` should be a kebab-case identifier: `home`, `explore`, `item-detail`, `settings`, `profile`, etc.
485
+ - From the element tree, extract bounding boxes of interactive elements (buttons, list items, tabs, etc.)
486
+ - Record which screen each interactive element navigates to (based on what you observed during testing)
487
+
488
+ 3. **After all screens are tested**, write `output/{app-name}/preview/screens.json`:
489
+
490
+ ```json
491
+ {
492
+ "appName": "{App Display Name}",
493
+ "platform": "{ios|android}",
494
+ "template": "{template name if known}",
495
+ "designBrand": "{brand name if known}",
496
+ "screens": [
497
+ {
498
+ "id": "{screen-id}",
499
+ "label": "{Human Readable Screen Name}",
500
+ "screenshot": "{screen-id}.png",
501
+ "hotspots": [
502
+ {
503
+ "x": 0, "y": 0, "w": 0, "h": 0,
504
+ "target": "{target-screen-id}",
505
+ "label": "{Element Label}"
506
+ }
507
+ ]
508
+ }
509
+ ],
510
+ "initialScreen": "{first-screen-id}"
511
+ }
512
+ ```
513
+
514
+ ### Hotspot Rules
515
+
516
+ - `x`, `y`, `w`, `h` are bounding box coordinates in screenshot pixel space
517
+ - `target` is the `id` of the screen that element navigates to (must match a screen in the `screens` array)
518
+ - Only include hotspots for elements that navigate to another screen in the app (tabs, list items, back buttons)
519
+ - Omit hotspots for elements that don't navigate (toggles, text fields, action sheets)
520
+ - If you don't know the target screen for an element, omit that hotspot
521
+
522
+ ### Important
523
+
524
+ - This capture is **in addition to** normal testing — do NOT skip any testing steps
525
+ - The preview directory and files are only used for the web preview feature
526
+ - If preview capture fails for any reason, log a warning but do NOT fail the test
527
+
469
528
  ## Important Rules
470
529
 
471
530
  - ONLY use ai-tester MCP tools for device interaction — NOT shell commands like `xcrun simctl`
package/dist/cli.d.ts CHANGED
@@ -7,18 +7,27 @@ export interface CliFlags {
7
7
  list?: boolean;
8
8
  run?: string;
9
9
  engine?: Engine;
10
+ noPreview?: boolean;
10
11
  }
11
12
  export interface CliParseResult {
12
13
  input: UserInput;
13
14
  flags: CliFlags;
14
15
  }
15
- /** Result when a management command (--list, --run, --test) is detected */
16
+ /** Result when a management command (--list, --run, --test, --preview, --screenshot) is detected */
16
17
  export interface ManagementCommand {
17
- command: "list" | "run" | "test";
18
+ command: "list" | "run" | "test" | "preview" | "screenshot";
18
19
  appName?: string;
19
20
  engine?: Engine;
20
21
  model?: Model;
21
22
  }
23
+ /** Result from interactive mode: either a build input or a management command */
24
+ export type InteractiveResult = {
25
+ kind: "build";
26
+ input: UserInput;
27
+ } | {
28
+ kind: "management";
29
+ command: ManagementCommand;
30
+ };
22
31
  /**
23
32
  * Check if the user passed a management command (--list, --run).
24
33
  * These don't require --description / --platform and skip the build flow entirely.
@@ -29,11 +38,16 @@ export declare function parseManagementCommand(): ManagementCommand | null;
29
38
  * Returns UserInput + CliFlags if all required args are present, null otherwise.
30
39
  */
31
40
  export declare function parseCliArgs(): CliParseResult | null;
41
+ /**
42
+ * Show an interactive picker for apps in output/.
43
+ * Scans output/ directories, reads summary.json, and presents a select menu.
44
+ */
45
+ export declare function pickApp(): Promise<string>;
32
46
  /**
33
47
  * Collect user input interactively via the terminal.
34
- * Returns the app description, target platform, and model choice.
48
+ * Returns either a build input or a management command.
35
49
  */
36
- export declare function collectUserInput(): Promise<UserInput>;
50
+ export declare function collectUserInput(): Promise<InteractiveResult>;
37
51
  /** Display a summary of what will be built and ask for confirmation */
38
52
  export declare function confirmInput(input: UserInput): Promise<boolean>;
39
53
  //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA2B,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGrF,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAE9B,mDAAmD;AACnD,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,QAAQ,CAAC;CACjB;AAED,2EAA2E;AAC3E,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,iBAAiB,GAAG,IAAI,CAuDjE;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,cAAc,GAAG,IAAI,CAuFpD;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,SAAS,CAAC,CA2I3D;AAmHD,uEAAuE;AACvE,wBAAsB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAmDrE"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA2B,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAIrF,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAE9B,mDAAmD;AACnD,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,QAAQ,CAAC;CACjB;AAED,oGAAoG;AACpG,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,iFAAiF;AACjF,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAEvD;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,iBAAiB,GAAG,IAAI,CAyEjE;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,cAAc,GAAG,IAAI,CA2FpD;AAED;;;GAGG;AACH,wBAAsB,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CA4D/C;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAqLnE;AAmHD,uEAAuE;AACvE,wBAAsB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAmDrE"}