create-du-app 0.1.3 → 0.1.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 (455) hide show
  1. package/README.md +15 -9
  2. package/package.json +6 -5
  3. package/src/generate.js +15 -2
  4. package/src/index.js +15 -9
  5. package/src/prompts.js +1 -1
  6. package/templates/mobile/expo/.env.example +5 -0
  7. package/templates/mobile/expo/.eslintrc.js +7 -0
  8. package/templates/mobile/expo/.prettierrc.js +7 -0
  9. package/templates/mobile/expo/.svgrrc.js +9 -0
  10. package/templates/mobile/expo/README.md +70 -7
  11. package/templates/mobile/expo/_gitignore +20 -0
  12. package/templates/mobile/expo/_package.json +60 -1
  13. package/templates/mobile/expo/app.json +26 -0
  14. package/templates/mobile/expo/babel.config.js +21 -0
  15. package/templates/mobile/expo/index.js +7 -0
  16. package/templates/mobile/expo/metro.config.js +31 -0
  17. package/templates/mobile/expo/src/app/App.tsx +24 -0
  18. package/templates/mobile/expo/src/app/app-provider.tsx +40 -0
  19. package/templates/mobile/expo/src/app/config/translation.ts +30 -0
  20. package/templates/mobile/expo/src/app/index.ts +1 -0
  21. package/templates/mobile/expo/src/app/navigation/app-route-type.ts +27 -0
  22. package/templates/mobile/expo/src/app/navigation/bottom-tabs.tsx +34 -0
  23. package/templates/mobile/expo/src/app/navigation/index.tsx +14 -0
  24. package/templates/mobile/expo/src/app/stores/auth.store.ts +33 -0
  25. package/templates/mobile/expo/src/app/stores/common.store.ts +19 -0
  26. package/templates/mobile/expo/src/app/stores/index.ts +3 -0
  27. package/templates/mobile/expo/src/app/stores/loading.store.ts +22 -0
  28. package/templates/mobile/expo/src/assets/Images/empty-list.png +0 -0
  29. package/templates/mobile/expo/src/assets/Images/index.ts +5 -0
  30. package/templates/mobile/expo/src/assets/Images/screen-bg-gradian.png +0 -0
  31. package/templates/mobile/expo/src/assets/i18n/en.json +28 -0
  32. package/templates/mobile/expo/src/assets/i18n/fr.json +28 -0
  33. package/templates/mobile/expo/src/assets/lotties/index.ts +3 -0
  34. package/templates/mobile/expo/src/assets/lotties/loading.json +1 -0
  35. package/templates/mobile/expo/src/assets/svgs/arrow-left.svg +3 -0
  36. package/templates/mobile/expo/src/assets/svgs/arrow-right.svg +3 -0
  37. package/templates/mobile/expo/src/assets/svgs/calendar.svg +12 -0
  38. package/templates/mobile/expo/src/assets/svgs/check.svg +3 -0
  39. package/templates/mobile/expo/src/assets/svgs/close.svg +3 -0
  40. package/templates/mobile/expo/src/assets/svgs/eye-hide.svg +3 -0
  41. package/templates/mobile/expo/src/assets/svgs/eye.svg +4 -0
  42. package/templates/mobile/expo/src/assets/svgs/index.ts +29 -0
  43. package/templates/mobile/expo/src/assets/svgs/minus.svg +3 -0
  44. package/templates/mobile/expo/src/assets/svgs/plus.svg +3 -0
  45. package/templates/mobile/expo/src/assets/svgs/search.svg +3 -0
  46. package/templates/mobile/expo/src/assets/svgs/toast-error.svg +5 -0
  47. package/templates/mobile/expo/src/assets/svgs/toast-success.svg +4 -0
  48. package/templates/mobile/expo/src/core/api/endpoints.ts +8 -0
  49. package/templates/mobile/expo/src/core/api/example.api.ts +53 -0
  50. package/templates/mobile/expo/src/core/api/index.ts +4 -0
  51. package/templates/mobile/expo/src/core/components/common/index.ts +1 -0
  52. package/templates/mobile/expo/src/core/components/common/list-empty/index.ts +2 -0
  53. package/templates/mobile/expo/src/core/components/common/list-empty/list-empty.tsx +30 -0
  54. package/templates/mobile/expo/src/core/components/common/list-empty/list-empty.type.ts +5 -0
  55. package/templates/mobile/expo/src/core/components/forms/date-time-picker.modal.tsx +116 -0
  56. package/templates/mobile/expo/src/core/components/forms/hf-date-time.tsx +293 -0
  57. package/templates/mobile/expo/src/core/components/forms/hf-password-input.tsx +153 -0
  58. package/templates/mobile/expo/src/core/components/forms/hf-text-input.tsx +59 -0
  59. package/templates/mobile/expo/src/core/components/forms/hf-time-picker.tsx +116 -0
  60. package/templates/mobile/expo/src/core/components/forms/index.ts +4 -0
  61. package/templates/mobile/expo/src/core/components/index.ts +5 -0
  62. package/templates/mobile/expo/src/core/components/loading/index.ts +1 -0
  63. package/templates/mobile/expo/src/core/components/loading/loading-app/index.ts +1 -0
  64. package/templates/mobile/expo/src/core/components/loading/loading-app/loading-app.tsx +50 -0
  65. package/templates/mobile/expo/src/core/components/offline/index.ts +1 -0
  66. package/templates/mobile/expo/src/core/components/offline/offline-banner.tsx +186 -0
  67. package/templates/mobile/expo/src/core/components/screen/index.ts +1 -0
  68. package/templates/mobile/expo/src/core/components/screen/screen-container/index.ts +1 -0
  69. package/templates/mobile/expo/src/core/components/screen/screen-container/screen-container.tsx +248 -0
  70. package/templates/mobile/expo/src/core/components/splash/index.ts +1 -0
  71. package/templates/mobile/expo/src/core/components/splash/splash-overlay/index.ts +1 -0
  72. package/templates/mobile/expo/src/core/components/splash/splash-overlay/splash-overlay.tsx +93 -0
  73. package/templates/mobile/expo/src/core/components/ui/animated-list-item/animated-list-item.tsx +48 -0
  74. package/templates/mobile/expo/src/core/components/ui/animated-list-item/animated-list-item.type.ts +10 -0
  75. package/templates/mobile/expo/src/core/components/ui/animated-list-item/index.ts +2 -0
  76. package/templates/mobile/expo/src/core/components/ui/app-image/app-image.tsx +101 -0
  77. package/templates/mobile/expo/src/core/components/ui/app-image/app-image.type.ts +19 -0
  78. package/templates/mobile/expo/src/core/components/ui/app-image/index.ts +2 -0
  79. package/templates/mobile/expo/src/core/components/ui/asset-placeholder/asset-placeholder.tsx +76 -0
  80. package/templates/mobile/expo/src/core/components/ui/asset-placeholder/index.ts +1 -0
  81. package/templates/mobile/expo/src/core/components/ui/avatar-image/avatar-image.tsx +90 -0
  82. package/templates/mobile/expo/src/core/components/ui/avatar-image/index.ts +1 -0
  83. package/templates/mobile/expo/src/core/components/ui/bottom-sheet/bottom-sheet.tsx +145 -0
  84. package/templates/mobile/expo/src/core/components/ui/bottom-sheet/bottom-sheet.type.ts +10 -0
  85. package/templates/mobile/expo/src/core/components/ui/bottom-sheet/index.ts +2 -0
  86. package/templates/mobile/expo/src/core/components/ui/button/button.style.ts +146 -0
  87. package/templates/mobile/expo/src/core/components/ui/button/button.tsx +97 -0
  88. package/templates/mobile/expo/src/core/components/ui/button/button.type.ts +47 -0
  89. package/templates/mobile/expo/src/core/components/ui/button/index.ts +4 -0
  90. package/templates/mobile/expo/src/core/components/ui/checkbox/checkbox.tsx +127 -0
  91. package/templates/mobile/expo/src/core/components/ui/checkbox/checkbox.type.ts +24 -0
  92. package/templates/mobile/expo/src/core/components/ui/checkbox/index.ts +2 -0
  93. package/templates/mobile/expo/src/core/components/ui/collapsible-section/collapsible-section.tsx +141 -0
  94. package/templates/mobile/expo/src/core/components/ui/collapsible-section/collapsible-section.type.ts +10 -0
  95. package/templates/mobile/expo/src/core/components/ui/collapsible-section/index.ts +2 -0
  96. package/templates/mobile/expo/src/core/components/ui/components.registry.json +313 -0
  97. package/templates/mobile/expo/src/core/components/ui/field/field-frame.tsx +62 -0
  98. package/templates/mobile/expo/src/core/components/ui/field/field.shared.ts +31 -0
  99. package/templates/mobile/expo/src/core/components/ui/header/header.tsx +196 -0
  100. package/templates/mobile/expo/src/core/components/ui/header/header.type.ts +30 -0
  101. package/templates/mobile/expo/src/core/components/ui/header/index.ts +2 -0
  102. package/templates/mobile/expo/src/core/components/ui/icon-button/icon-button.style.ts +23 -0
  103. package/templates/mobile/expo/src/core/components/ui/icon-button/icon-button.tsx +66 -0
  104. package/templates/mobile/expo/src/core/components/ui/icon-button/icon-button.type.ts +25 -0
  105. package/templates/mobile/expo/src/core/components/ui/icon-button/index.ts +2 -0
  106. package/templates/mobile/expo/src/core/components/ui/image-slider/image-slider.tsx +107 -0
  107. package/templates/mobile/expo/src/core/components/ui/image-slider/image-slider.type.ts +10 -0
  108. package/templates/mobile/expo/src/core/components/ui/image-slider/index.ts +2 -0
  109. package/templates/mobile/expo/src/core/components/ui/index.ts +25 -0
  110. package/templates/mobile/expo/src/core/components/ui/label/index.ts +2 -0
  111. package/templates/mobile/expo/src/core/components/ui/label/label.tsx +36 -0
  112. package/templates/mobile/expo/src/core/components/ui/label/label.type.ts +12 -0
  113. package/templates/mobile/expo/src/core/components/ui/modal/index.ts +2 -0
  114. package/templates/mobile/expo/src/core/components/ui/modal/modal.tsx +62 -0
  115. package/templates/mobile/expo/src/core/components/ui/modal/modal.type.ts +11 -0
  116. package/templates/mobile/expo/src/core/components/ui/otp-input/index.ts +2 -0
  117. package/templates/mobile/expo/src/core/components/ui/otp-input/otp-input.tsx +129 -0
  118. package/templates/mobile/expo/src/core/components/ui/otp-input/otp-input.type.ts +20 -0
  119. package/templates/mobile/expo/src/core/components/ui/page-dots/index.ts +1 -0
  120. package/templates/mobile/expo/src/core/components/ui/page-dots/page-dots.tsx +60 -0
  121. package/templates/mobile/expo/src/core/components/ui/radio/index.ts +2 -0
  122. package/templates/mobile/expo/src/core/components/ui/radio/radio.tsx +121 -0
  123. package/templates/mobile/expo/src/core/components/ui/radio/radio.type.ts +20 -0
  124. package/templates/mobile/expo/src/core/components/ui/screen/index.ts +1 -0
  125. package/templates/mobile/expo/src/core/components/ui/screen/screen-gradient.tsx +33 -0
  126. package/templates/mobile/expo/src/core/components/ui/search-box/index.ts +2 -0
  127. package/templates/mobile/expo/src/core/components/ui/search-box/search-box.tsx +162 -0
  128. package/templates/mobile/expo/src/core/components/ui/search-box/search-box.type.ts +26 -0
  129. package/templates/mobile/expo/src/core/components/ui/segmented-control/index.ts +2 -0
  130. package/templates/mobile/expo/src/core/components/ui/segmented-control/segmented-control.tsx +86 -0
  131. package/templates/mobile/expo/src/core/components/ui/segmented-control/segmented-control.type.ts +22 -0
  132. package/templates/mobile/expo/src/core/components/ui/skeleton/index.ts +2 -0
  133. package/templates/mobile/expo/src/core/components/ui/skeleton/skeleton.tsx +106 -0
  134. package/templates/mobile/expo/src/core/components/ui/skeleton/skeleton.type.ts +8 -0
  135. package/templates/mobile/expo/src/core/components/ui/success-state/index.ts +1 -0
  136. package/templates/mobile/expo/src/core/components/ui/success-state/success-state.tsx +68 -0
  137. package/templates/mobile/expo/src/core/components/ui/tabs/index.ts +2 -0
  138. package/templates/mobile/expo/src/core/components/ui/tabs/tabs.tsx +273 -0
  139. package/templates/mobile/expo/src/core/components/ui/tabs/tabs.type.ts +21 -0
  140. package/templates/mobile/expo/src/core/components/ui/tag-input/index.ts +2 -0
  141. package/templates/mobile/expo/src/core/components/ui/tag-input/tag-input.tsx +146 -0
  142. package/templates/mobile/expo/src/core/components/ui/tag-input/tag-input.type.ts +22 -0
  143. package/templates/mobile/expo/src/core/components/ui/text-area/index.ts +2 -0
  144. package/templates/mobile/expo/src/core/components/ui/text-area/text-area.tsx +90 -0
  145. package/templates/mobile/expo/src/core/components/ui/text-area/text-area.type.ts +20 -0
  146. package/templates/mobile/expo/src/core/components/ui/text-field/index.ts +2 -0
  147. package/templates/mobile/expo/src/core/components/ui/text-field/text-field.tsx +116 -0
  148. package/templates/mobile/expo/src/core/components/ui/text-field/text-field.type.ts +21 -0
  149. package/templates/mobile/expo/src/core/components/ui/toggle/index.ts +2 -0
  150. package/templates/mobile/expo/src/core/components/ui/toggle/toggle.tsx +110 -0
  151. package/templates/mobile/expo/src/core/components/ui/toggle/toggle.type.ts +19 -0
  152. package/templates/mobile/expo/src/core/constants/external-urls.constant.ts +5 -0
  153. package/templates/mobile/expo/src/core/constants/hard-data.constant.ts +0 -0
  154. package/templates/mobile/expo/src/core/constants/index.ts +2 -0
  155. package/templates/mobile/expo/src/core/constants/type.constant.ts +3 -0
  156. package/templates/mobile/expo/src/core/context/index.ts +1 -0
  157. package/templates/mobile/expo/src/core/context/shared-transition-context.tsx +35 -0
  158. package/templates/mobile/expo/src/core/hook/index.ts +8 -0
  159. package/templates/mobile/expo/src/core/hook/useActiveRouteName.ts +63 -0
  160. package/templates/mobile/expo/src/core/hook/useAppNavigation.tsx +7 -0
  161. package/templates/mobile/expo/src/core/hook/useBottomInset.tsx +26 -0
  162. package/templates/mobile/expo/src/core/hook/useDebounce.tsx +16 -0
  163. package/templates/mobile/expo/src/core/hook/useEndReached.tsx +46 -0
  164. package/templates/mobile/expo/src/core/hook/useManualRefetch.ts +56 -0
  165. package/templates/mobile/expo/src/core/hook/useNetworkStatus.ts +68 -0
  166. package/templates/mobile/expo/src/core/hook/useTimeout.tsx +30 -0
  167. package/templates/mobile/expo/src/core/index.ts +7 -0
  168. package/templates/mobile/expo/src/core/services/api.service.ts +230 -0
  169. package/templates/mobile/expo/src/core/services/device-id.service.ts +37 -0
  170. package/templates/mobile/expo/src/core/services/index.ts +3 -0
  171. package/templates/mobile/expo/src/core/services/session-end.bridge.ts +26 -0
  172. package/templates/mobile/expo/src/core/theme/dark.theme.ts +10 -0
  173. package/templates/mobile/expo/src/core/theme/index.ts +5 -0
  174. package/templates/mobile/expo/src/core/theme/light.theme.ts +44 -0
  175. package/templates/mobile/expo/src/core/theme/theme-context.tsx +82 -0
  176. package/templates/mobile/expo/src/core/theme/theme.types.ts +26 -0
  177. package/templates/mobile/expo/src/core/theme/use-themed-styles.ts +25 -0
  178. package/templates/mobile/expo/src/core/utils/color.util.tsx +198 -0
  179. package/templates/mobile/expo/src/core/utils/date.util.ts +97 -0
  180. package/templates/mobile/expo/src/core/utils/device-locale.util.ts +24 -0
  181. package/templates/mobile/expo/src/core/utils/emitter/index.ts +161 -0
  182. package/templates/mobile/expo/src/core/utils/emitter/type.ts +40 -0
  183. package/templates/mobile/expo/src/core/utils/enum.util.tsx +15 -0
  184. package/templates/mobile/expo/src/core/utils/font.util.tsx +42 -0
  185. package/templates/mobile/expo/src/core/utils/func.util.ts +48 -0
  186. package/templates/mobile/expo/src/core/utils/greeting.util.ts +20 -0
  187. package/templates/mobile/expo/src/core/utils/image-format.util.ts +117 -0
  188. package/templates/mobile/expo/src/core/utils/image-picker.util.ts +63 -0
  189. package/templates/mobile/expo/src/core/utils/index.ts +18 -0
  190. package/templates/mobile/expo/src/core/utils/linking.util.ts +16 -0
  191. package/templates/mobile/expo/src/core/utils/navigation.util.tsx +100 -0
  192. package/templates/mobile/expo/src/core/utils/number-format.ts +28 -0
  193. package/templates/mobile/expo/src/core/utils/query-client.util.ts +35 -0
  194. package/templates/mobile/expo/src/core/utils/query-persister.util.ts +31 -0
  195. package/templates/mobile/expo/src/core/utils/schema.util.tsx +2713 -0
  196. package/templates/mobile/expo/src/core/utils/size.util.tsx +74 -0
  197. package/templates/mobile/expo/src/core/utils/storage.util.tsx +53 -0
  198. package/templates/mobile/expo/src/core/utils/toast.util.tsx +151 -0
  199. package/templates/mobile/expo/src/core/utils/translator.util.tsx +23 -0
  200. package/templates/mobile/expo/src/core/utils/typography.util.tsx +69 -0
  201. package/templates/mobile/expo/src/core/utils/validate.util.tsx +13 -0
  202. package/templates/mobile/expo/src/declarations.d.ts +54 -0
  203. package/templates/mobile/expo/src/modules/home/home.screen.tsx +110 -0
  204. package/templates/mobile/expo/src/modules/profile/profile.screen.tsx +29 -0
  205. package/templates/mobile/expo/src/scripts/link-fonts.js +60 -0
  206. package/templates/mobile/expo/src/scripts/sync-images.js +56 -0
  207. package/templates/mobile/expo/src/scripts/sync-svgs.js +50 -0
  208. package/templates/mobile/expo/src/types/models.d.ts +24 -0
  209. package/templates/mobile/expo/tsconfig.json +19 -0
  210. package/templates/mobile/rn/.bundle/config +2 -0
  211. package/templates/mobile/rn/.env.example +5 -0
  212. package/templates/mobile/rn/.eslintrc.js +7 -0
  213. package/templates/mobile/rn/.prettierrc.js +7 -0
  214. package/templates/mobile/rn/.svgrrc.js +9 -0
  215. package/templates/mobile/rn/.watchmanconfig +1 -0
  216. package/templates/mobile/rn/Gemfile +17 -0
  217. package/templates/mobile/rn/README.md +72 -7
  218. package/templates/mobile/rn/_gitignore +24 -0
  219. package/templates/mobile/rn/_package.json +69 -1
  220. package/templates/mobile/rn/android/app/build.gradle +126 -0
  221. package/templates/mobile/rn/android/app/debug.keystore +0 -0
  222. package/templates/mobile/rn/android/app/proguard-rules.pro +10 -0
  223. package/templates/mobile/rn/android/app/src/main/AndroidManifest.xml +27 -0
  224. package/templates/mobile/rn/android/app/src/main/java/com/dumobile/MainActivity.kt +22 -0
  225. package/templates/mobile/rn/android/app/src/main/java/com/dumobile/MainApplication.kt +27 -0
  226. package/templates/mobile/rn/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
  227. package/templates/mobile/rn/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  228. package/templates/mobile/rn/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  229. package/templates/mobile/rn/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  230. package/templates/mobile/rn/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  231. package/templates/mobile/rn/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  232. package/templates/mobile/rn/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  233. package/templates/mobile/rn/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  234. package/templates/mobile/rn/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  235. package/templates/mobile/rn/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  236. package/templates/mobile/rn/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  237. package/templates/mobile/rn/android/app/src/main/res/values/strings.xml +3 -0
  238. package/templates/mobile/rn/android/app/src/main/res/values/styles.xml +9 -0
  239. package/templates/mobile/rn/android/build.gradle +21 -0
  240. package/templates/mobile/rn/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  241. package/templates/mobile/rn/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  242. package/templates/mobile/rn/android/gradle.properties +44 -0
  243. package/templates/mobile/rn/android/gradlew +248 -0
  244. package/templates/mobile/rn/android/gradlew.bat +98 -0
  245. package/templates/mobile/rn/android/settings.gradle +21 -0
  246. package/templates/mobile/rn/app.json +4 -0
  247. package/templates/mobile/rn/babel.config.js +18 -0
  248. package/templates/mobile/rn/index.js +10 -0
  249. package/templates/mobile/rn/ios/.xcode.env +11 -0
  250. package/templates/mobile/rn/ios/DuMobile/AppDelegate.swift +48 -0
  251. package/templates/mobile/rn/ios/DuMobile/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  252. package/templates/mobile/rn/ios/DuMobile/Images.xcassets/Contents.json +6 -0
  253. package/templates/mobile/rn/ios/DuMobile/Info.plist +59 -0
  254. package/templates/mobile/rn/ios/DuMobile/LaunchScreen.storyboard +47 -0
  255. package/templates/mobile/rn/ios/DuMobile/PrivacyInfo.xcprivacy +37 -0
  256. package/templates/mobile/rn/ios/DuMobile.xcodeproj/project.pbxproj +475 -0
  257. package/templates/mobile/rn/ios/DuMobile.xcodeproj/xcshareddata/xcschemes/DuMobile.xcscheme +88 -0
  258. package/templates/mobile/rn/ios/Podfile +34 -0
  259. package/templates/mobile/rn/metro.config.js +33 -0
  260. package/templates/mobile/rn/src/app/App.tsx +24 -0
  261. package/templates/mobile/rn/src/app/app-provider.tsx +41 -0
  262. package/templates/mobile/rn/src/app/config/translation.ts +29 -0
  263. package/templates/mobile/rn/src/app/index.ts +1 -0
  264. package/templates/mobile/rn/src/app/navigation/app-route-type.ts +27 -0
  265. package/templates/mobile/rn/src/app/navigation/bottom-tabs.tsx +34 -0
  266. package/templates/mobile/rn/src/app/navigation/index.tsx +14 -0
  267. package/templates/mobile/rn/src/app/stores/auth.store.ts +33 -0
  268. package/templates/mobile/rn/src/app/stores/common.store.ts +19 -0
  269. package/templates/mobile/rn/src/app/stores/index.ts +3 -0
  270. package/templates/mobile/rn/src/app/stores/loading.store.ts +22 -0
  271. package/templates/mobile/rn/src/assets/Images/empty-list.png +0 -0
  272. package/templates/mobile/rn/src/assets/Images/index.ts +5 -0
  273. package/templates/mobile/rn/src/assets/Images/screen-bg-gradian.png +0 -0
  274. package/templates/mobile/rn/src/assets/i18n/en.json +22 -0
  275. package/templates/mobile/rn/src/assets/i18n/fr.json +22 -0
  276. package/templates/mobile/rn/src/assets/lotties/index.ts +3 -0
  277. package/templates/mobile/rn/src/assets/lotties/loading.json +1 -0
  278. package/templates/mobile/rn/src/assets/svgs/arrow-left.svg +3 -0
  279. package/templates/mobile/rn/src/assets/svgs/arrow-right.svg +3 -0
  280. package/templates/mobile/rn/src/assets/svgs/calendar.svg +12 -0
  281. package/templates/mobile/rn/src/assets/svgs/check.svg +3 -0
  282. package/templates/mobile/rn/src/assets/svgs/close.svg +3 -0
  283. package/templates/mobile/rn/src/assets/svgs/eye-hide.svg +3 -0
  284. package/templates/mobile/rn/src/assets/svgs/eye.svg +4 -0
  285. package/templates/mobile/rn/src/assets/svgs/index.ts +29 -0
  286. package/templates/mobile/rn/src/assets/svgs/minus.svg +3 -0
  287. package/templates/mobile/rn/src/assets/svgs/plus.svg +3 -0
  288. package/templates/mobile/rn/src/assets/svgs/search.svg +3 -0
  289. package/templates/mobile/rn/src/assets/svgs/toast-error.svg +5 -0
  290. package/templates/mobile/rn/src/assets/svgs/toast-success.svg +4 -0
  291. package/templates/mobile/rn/src/core/api/endpoints.ts +8 -0
  292. package/templates/mobile/rn/src/core/api/example.api.ts +53 -0
  293. package/templates/mobile/rn/src/core/api/index.ts +4 -0
  294. package/templates/mobile/rn/src/core/components/common/index.ts +1 -0
  295. package/templates/mobile/rn/src/core/components/common/list-empty/index.ts +2 -0
  296. package/templates/mobile/rn/src/core/components/common/list-empty/list-empty.tsx +30 -0
  297. package/templates/mobile/rn/src/core/components/common/list-empty/list-empty.type.ts +5 -0
  298. package/templates/mobile/rn/src/core/components/forms/hf-date-time.tsx +301 -0
  299. package/templates/mobile/rn/src/core/components/forms/hf-password-input.tsx +153 -0
  300. package/templates/mobile/rn/src/core/components/forms/hf-text-input.tsx +59 -0
  301. package/templates/mobile/rn/src/core/components/forms/hf-time-picker.tsx +117 -0
  302. package/templates/mobile/rn/src/core/components/forms/index.ts +4 -0
  303. package/templates/mobile/rn/src/core/components/index.ts +5 -0
  304. package/templates/mobile/rn/src/core/components/loading/index.ts +1 -0
  305. package/templates/mobile/rn/src/core/components/loading/loading-app/index.ts +1 -0
  306. package/templates/mobile/rn/src/core/components/loading/loading-app/loading-app.tsx +50 -0
  307. package/templates/mobile/rn/src/core/components/offline/index.ts +1 -0
  308. package/templates/mobile/rn/src/core/components/offline/offline-banner.tsx +186 -0
  309. package/templates/mobile/rn/src/core/components/screen/index.ts +1 -0
  310. package/templates/mobile/rn/src/core/components/screen/screen-container/index.ts +1 -0
  311. package/templates/mobile/rn/src/core/components/screen/screen-container/screen-container.tsx +252 -0
  312. package/templates/mobile/rn/src/core/components/splash/index.ts +1 -0
  313. package/templates/mobile/rn/src/core/components/splash/splash-overlay/index.ts +1 -0
  314. package/templates/mobile/rn/src/core/components/splash/splash-overlay/splash-overlay.tsx +93 -0
  315. package/templates/mobile/rn/src/core/components/ui/animated-list-item/animated-list-item.tsx +48 -0
  316. package/templates/mobile/rn/src/core/components/ui/animated-list-item/animated-list-item.type.ts +10 -0
  317. package/templates/mobile/rn/src/core/components/ui/animated-list-item/index.ts +2 -0
  318. package/templates/mobile/rn/src/core/components/ui/app-image/app-image.tsx +104 -0
  319. package/templates/mobile/rn/src/core/components/ui/app-image/app-image.type.ts +19 -0
  320. package/templates/mobile/rn/src/core/components/ui/app-image/index.ts +2 -0
  321. package/templates/mobile/rn/src/core/components/ui/asset-placeholder/asset-placeholder.tsx +76 -0
  322. package/templates/mobile/rn/src/core/components/ui/asset-placeholder/index.ts +1 -0
  323. package/templates/mobile/rn/src/core/components/ui/avatar-image/avatar-image.tsx +90 -0
  324. package/templates/mobile/rn/src/core/components/ui/avatar-image/index.ts +1 -0
  325. package/templates/mobile/rn/src/core/components/ui/bottom-sheet/bottom-sheet.tsx +145 -0
  326. package/templates/mobile/rn/src/core/components/ui/bottom-sheet/bottom-sheet.type.ts +10 -0
  327. package/templates/mobile/rn/src/core/components/ui/bottom-sheet/index.ts +2 -0
  328. package/templates/mobile/rn/src/core/components/ui/button/button.style.ts +146 -0
  329. package/templates/mobile/rn/src/core/components/ui/button/button.tsx +97 -0
  330. package/templates/mobile/rn/src/core/components/ui/button/button.type.ts +47 -0
  331. package/templates/mobile/rn/src/core/components/ui/button/index.ts +4 -0
  332. package/templates/mobile/rn/src/core/components/ui/checkbox/checkbox.tsx +127 -0
  333. package/templates/mobile/rn/src/core/components/ui/checkbox/checkbox.type.ts +24 -0
  334. package/templates/mobile/rn/src/core/components/ui/checkbox/index.ts +2 -0
  335. package/templates/mobile/rn/src/core/components/ui/collapsible-section/collapsible-section.tsx +141 -0
  336. package/templates/mobile/rn/src/core/components/ui/collapsible-section/collapsible-section.type.ts +10 -0
  337. package/templates/mobile/rn/src/core/components/ui/collapsible-section/index.ts +2 -0
  338. package/templates/mobile/rn/src/core/components/ui/components.registry.json +313 -0
  339. package/templates/mobile/rn/src/core/components/ui/field/field-frame.tsx +62 -0
  340. package/templates/mobile/rn/src/core/components/ui/field/field.shared.ts +31 -0
  341. package/templates/mobile/rn/src/core/components/ui/header/header.tsx +196 -0
  342. package/templates/mobile/rn/src/core/components/ui/header/header.type.ts +30 -0
  343. package/templates/mobile/rn/src/core/components/ui/header/index.ts +2 -0
  344. package/templates/mobile/rn/src/core/components/ui/icon-button/icon-button.style.ts +23 -0
  345. package/templates/mobile/rn/src/core/components/ui/icon-button/icon-button.tsx +66 -0
  346. package/templates/mobile/rn/src/core/components/ui/icon-button/icon-button.type.ts +25 -0
  347. package/templates/mobile/rn/src/core/components/ui/icon-button/index.ts +2 -0
  348. package/templates/mobile/rn/src/core/components/ui/image-slider/image-slider.tsx +107 -0
  349. package/templates/mobile/rn/src/core/components/ui/image-slider/image-slider.type.ts +10 -0
  350. package/templates/mobile/rn/src/core/components/ui/image-slider/index.ts +2 -0
  351. package/templates/mobile/rn/src/core/components/ui/index.ts +25 -0
  352. package/templates/mobile/rn/src/core/components/ui/label/index.ts +2 -0
  353. package/templates/mobile/rn/src/core/components/ui/label/label.tsx +36 -0
  354. package/templates/mobile/rn/src/core/components/ui/label/label.type.ts +12 -0
  355. package/templates/mobile/rn/src/core/components/ui/modal/index.ts +2 -0
  356. package/templates/mobile/rn/src/core/components/ui/modal/modal.tsx +62 -0
  357. package/templates/mobile/rn/src/core/components/ui/modal/modal.type.ts +11 -0
  358. package/templates/mobile/rn/src/core/components/ui/otp-input/index.ts +2 -0
  359. package/templates/mobile/rn/src/core/components/ui/otp-input/otp-input.tsx +129 -0
  360. package/templates/mobile/rn/src/core/components/ui/otp-input/otp-input.type.ts +20 -0
  361. package/templates/mobile/rn/src/core/components/ui/page-dots/index.ts +1 -0
  362. package/templates/mobile/rn/src/core/components/ui/page-dots/page-dots.tsx +60 -0
  363. package/templates/mobile/rn/src/core/components/ui/radio/index.ts +2 -0
  364. package/templates/mobile/rn/src/core/components/ui/radio/radio.tsx +121 -0
  365. package/templates/mobile/rn/src/core/components/ui/radio/radio.type.ts +20 -0
  366. package/templates/mobile/rn/src/core/components/ui/screen/index.ts +1 -0
  367. package/templates/mobile/rn/src/core/components/ui/screen/screen-gradient.tsx +33 -0
  368. package/templates/mobile/rn/src/core/components/ui/search-box/index.ts +2 -0
  369. package/templates/mobile/rn/src/core/components/ui/search-box/search-box.tsx +162 -0
  370. package/templates/mobile/rn/src/core/components/ui/search-box/search-box.type.ts +26 -0
  371. package/templates/mobile/rn/src/core/components/ui/segmented-control/index.ts +2 -0
  372. package/templates/mobile/rn/src/core/components/ui/segmented-control/segmented-control.tsx +86 -0
  373. package/templates/mobile/rn/src/core/components/ui/segmented-control/segmented-control.type.ts +22 -0
  374. package/templates/mobile/rn/src/core/components/ui/skeleton/index.ts +2 -0
  375. package/templates/mobile/rn/src/core/components/ui/skeleton/skeleton.tsx +106 -0
  376. package/templates/mobile/rn/src/core/components/ui/skeleton/skeleton.type.ts +8 -0
  377. package/templates/mobile/rn/src/core/components/ui/success-state/index.ts +1 -0
  378. package/templates/mobile/rn/src/core/components/ui/success-state/success-state.tsx +68 -0
  379. package/templates/mobile/rn/src/core/components/ui/tabs/index.ts +2 -0
  380. package/templates/mobile/rn/src/core/components/ui/tabs/tabs.tsx +273 -0
  381. package/templates/mobile/rn/src/core/components/ui/tabs/tabs.type.ts +21 -0
  382. package/templates/mobile/rn/src/core/components/ui/tag-input/index.ts +2 -0
  383. package/templates/mobile/rn/src/core/components/ui/tag-input/tag-input.tsx +146 -0
  384. package/templates/mobile/rn/src/core/components/ui/tag-input/tag-input.type.ts +22 -0
  385. package/templates/mobile/rn/src/core/components/ui/text-area/index.ts +2 -0
  386. package/templates/mobile/rn/src/core/components/ui/text-area/text-area.tsx +90 -0
  387. package/templates/mobile/rn/src/core/components/ui/text-area/text-area.type.ts +20 -0
  388. package/templates/mobile/rn/src/core/components/ui/text-field/index.ts +2 -0
  389. package/templates/mobile/rn/src/core/components/ui/text-field/text-field.tsx +116 -0
  390. package/templates/mobile/rn/src/core/components/ui/text-field/text-field.type.ts +21 -0
  391. package/templates/mobile/rn/src/core/components/ui/toggle/index.ts +2 -0
  392. package/templates/mobile/rn/src/core/components/ui/toggle/toggle.tsx +110 -0
  393. package/templates/mobile/rn/src/core/components/ui/toggle/toggle.type.ts +19 -0
  394. package/templates/mobile/rn/src/core/constants/external-urls.constant.ts +5 -0
  395. package/templates/mobile/rn/src/core/constants/hard-data.constant.ts +0 -0
  396. package/templates/mobile/rn/src/core/constants/index.ts +2 -0
  397. package/templates/mobile/rn/src/core/constants/type.constant.ts +3 -0
  398. package/templates/mobile/rn/src/core/context/index.ts +1 -0
  399. package/templates/mobile/rn/src/core/context/shared-transition-context.tsx +35 -0
  400. package/templates/mobile/rn/src/core/hook/index.ts +8 -0
  401. package/templates/mobile/rn/src/core/hook/useActiveRouteName.ts +63 -0
  402. package/templates/mobile/rn/src/core/hook/useAppNavigation.tsx +7 -0
  403. package/templates/mobile/rn/src/core/hook/useBottomInset.tsx +26 -0
  404. package/templates/mobile/rn/src/core/hook/useDebounce.tsx +16 -0
  405. package/templates/mobile/rn/src/core/hook/useEndReached.tsx +46 -0
  406. package/templates/mobile/rn/src/core/hook/useManualRefetch.ts +56 -0
  407. package/templates/mobile/rn/src/core/hook/useNetworkStatus.ts +68 -0
  408. package/templates/mobile/rn/src/core/hook/useTimeout.tsx +30 -0
  409. package/templates/mobile/rn/src/core/index.ts +7 -0
  410. package/templates/mobile/rn/src/core/services/api.service.ts +230 -0
  411. package/templates/mobile/rn/src/core/services/device-id.service.ts +23 -0
  412. package/templates/mobile/rn/src/core/services/index.ts +3 -0
  413. package/templates/mobile/rn/src/core/services/session-end.bridge.ts +26 -0
  414. package/templates/mobile/rn/src/core/theme/dark.theme.ts +10 -0
  415. package/templates/mobile/rn/src/core/theme/index.ts +5 -0
  416. package/templates/mobile/rn/src/core/theme/light.theme.ts +44 -0
  417. package/templates/mobile/rn/src/core/theme/theme-context.tsx +82 -0
  418. package/templates/mobile/rn/src/core/theme/theme.types.ts +26 -0
  419. package/templates/mobile/rn/src/core/theme/use-themed-styles.ts +25 -0
  420. package/templates/mobile/rn/src/core/utils/color.util.tsx +198 -0
  421. package/templates/mobile/rn/src/core/utils/date.util.ts +97 -0
  422. package/templates/mobile/rn/src/core/utils/device-locale.util.ts +22 -0
  423. package/templates/mobile/rn/src/core/utils/emitter/index.ts +161 -0
  424. package/templates/mobile/rn/src/core/utils/emitter/type.ts +40 -0
  425. package/templates/mobile/rn/src/core/utils/enum.util.tsx +15 -0
  426. package/templates/mobile/rn/src/core/utils/font.util.tsx +42 -0
  427. package/templates/mobile/rn/src/core/utils/func.util.ts +48 -0
  428. package/templates/mobile/rn/src/core/utils/greeting.util.ts +20 -0
  429. package/templates/mobile/rn/src/core/utils/image-format.util.ts +117 -0
  430. package/templates/mobile/rn/src/core/utils/image-picker.util.ts +84 -0
  431. package/templates/mobile/rn/src/core/utils/index.ts +18 -0
  432. package/templates/mobile/rn/src/core/utils/linking.util.ts +16 -0
  433. package/templates/mobile/rn/src/core/utils/navigation.util.tsx +100 -0
  434. package/templates/mobile/rn/src/core/utils/number-format.ts +28 -0
  435. package/templates/mobile/rn/src/core/utils/query-client.util.ts +35 -0
  436. package/templates/mobile/rn/src/core/utils/query-persister.util.ts +36 -0
  437. package/templates/mobile/rn/src/core/utils/schema.util.tsx +2713 -0
  438. package/templates/mobile/rn/src/core/utils/size.util.tsx +74 -0
  439. package/templates/mobile/rn/src/core/utils/storage.util.tsx +53 -0
  440. package/templates/mobile/rn/src/core/utils/toast.util.tsx +151 -0
  441. package/templates/mobile/rn/src/core/utils/translator.util.tsx +23 -0
  442. package/templates/mobile/rn/src/core/utils/typography.util.tsx +69 -0
  443. package/templates/mobile/rn/src/core/utils/validate.util.tsx +13 -0
  444. package/templates/mobile/rn/src/declarations.d.ts +54 -0
  445. package/templates/mobile/rn/src/modules/home/home.screen.tsx +67 -0
  446. package/templates/mobile/rn/src/modules/profile/profile.screen.tsx +29 -0
  447. package/templates/mobile/rn/src/scripts/link-fonts.js +60 -0
  448. package/templates/mobile/rn/src/scripts/sync-images.js +56 -0
  449. package/templates/mobile/rn/src/scripts/sync-svgs.js +50 -0
  450. package/templates/mobile/rn/src/types/models.d.ts +24 -0
  451. package/templates/mobile/rn/tsconfig.json +21 -0
  452. package/templates/shared/src/api-endpoints.ts +8 -0
  453. package/templates/shared/src/enums.ts +34 -0
  454. package/templates/shared/src/external-urls.ts +5 -0
  455. package/templates/shared/src/index.ts +6 -3
package/README.md CHANGED
@@ -19,10 +19,13 @@ You'll be asked:
19
19
  2. **Select the groups** → press **`Space`** to tick Mobile / Frontend / Backend, then **`Enter`**
20
20
  3. **Pick one technology** per group → **↑ / ↓** then **`Enter`**
21
21
 
22
- Then:
22
+ Then bootstrap it — one command installs deps, builds `@repo/shared`, and
23
+ verifies every app can import it:
23
24
 
24
25
  ```bash
25
- cd my-shop && pnpm install
26
+ cd my-shop
27
+ pnpm bootstrap
28
+ pnpm dev
26
29
  ```
27
30
 
28
31
  Done. 🎉
@@ -44,16 +47,13 @@ npx create-du-app --name my-shop --mobile expo --fe nextjs --be nestjs
44
47
 
45
48
  ## Install globally (optional)
46
49
 
47
- Scaffold often? Install once and use the shorter `create-app` command:
50
+ Scaffold often? Install once so you don't re-download it each time:
48
51
 
49
52
  ```bash
50
53
  npm install -g create-du-app # or: pnpm add -g create-du-app
51
- create-app # same as npx create-du-app
54
+ create-du-app # same as npx create-du-app
52
55
  ```
53
56
 
54
- > The **package** is `create-du-app`; the installed **command** is `create-app`
55
- > (same pattern as `create-next-app`).
56
-
57
57
  ## Available stacks
58
58
 
59
59
  | Group | Technologies | Output folder |
@@ -62,7 +62,9 @@ create-app # same as npx create-du-app
62
62
  | Frontend | Next.js · ReactJS | `apps/web` |
63
63
  | Backend | Node.js · NestJS · PHP | `apps/backend` |
64
64
 
65
- `packages/shared` (shared types + api client) is added automatically when you pick **≥ 2** JS/TS stacks.
65
+ `packages/shared` (`@repo/shared` shared data contracts, built with tsup) is added
66
+ automatically when you pick **≥ 2** JS/TS stacks, and every JS/TS app is wired to it
67
+ as a `workspace:*` dependency.
66
68
 
67
69
  ---
68
70
 
@@ -76,6 +78,10 @@ Working on the CLI source or the templates? See the
76
78
  | `src/index.js` | Entry point. Parses flags, runs interactive or non-interactive, then generates. |
77
79
  | `src/registry.js` | **Data declaration** of groups, technologies, `templatePath`, and `lang`. Edit this to add/remove a stack. |
78
80
  | `src/prompts.js` | Interactive prompts (`@clack/prompts`). |
79
- | `src/generate.js` | Copies templates, renames `_package.json` → `package.json`, emits the root `package.json` + `pnpm-workspace.yaml`, substitutes `{{PROJECT_NAME}}`. |
81
+ | `src/generate.js` | Copies templates, renames `_package.json` → `package.json`, substitutes `{{PROJECT_NAME}}`, emits the root config (`package.json`, `pnpm-workspace.yaml`, `turbo.json`, `tsconfig.base.json`, `.gitignore`, `.npmrc`, `scripts/bootstrap.mjs`), and wires JS/TS apps to `@repo/shared`. |
82
+ | `scripts/validate-templates.mjs` | Validates every registered template (gates `prepack`/publish). Run with `pnpm validate`. |
83
+
84
+ Before publishing, `prepack` runs template validation automatically. Run the full
85
+ check (validate + generate smoke test) from the repo root with `pnpm test`.
80
86
 
81
87
  Release a new version: `pnpm release` (see [scripts/release.mjs](scripts/release.mjs)).
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "create-du-app",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "CLI generator: pick templates (Mobile/FE/BE) and scaffold a product monorepo",
5
5
  "type": "module",
6
6
  "bin": {
7
- "create-app": "src/index.js"
7
+ "create-du-app": "src/index.js"
8
8
  },
9
9
  "files": [
10
10
  "src",
@@ -12,14 +12,15 @@
12
12
  ],
13
13
  "scripts": {
14
14
  "start": "node src/index.js",
15
+ "validate": "node scripts/validate-templates.mjs",
15
16
  "release": "node scripts/release.mjs",
16
- "prepack": "node scripts/bundle-templates.mjs",
17
+ "prepack": "node scripts/validate-templates.mjs && node scripts/bundle-templates.mjs",
17
18
  "postpack": "node scripts/bundle-templates.mjs --clean"
18
19
  },
19
20
  "engines": {
20
- "node": ">=18"
21
+ "node": ">=20"
21
22
  },
22
- "packageManager": "pnpm@9.0.0",
23
+ "packageManager": "pnpm@9.12.0",
23
24
  "dependencies": {
24
25
  "@clack/prompts": "^0.7.0",
25
26
  "fs-extra": "^11.2.0"
package/src/generate.js CHANGED
@@ -81,7 +81,19 @@ async function copyTemplate(srcDir, destDir, projectName) {
81
81
  // ---------------------------------------------------------------------------
82
82
 
83
83
  // Build the project's root package.json (pnpm: NO "workspaces" field).
84
- function buildRootPackageJson(projectName, hasShared) {
84
+ function buildRootPackageJson(projectName, hasShared, createdAppDirs = []) {
85
+ // Per-app convenience scripts (life-master style): build @repo/shared first
86
+ // (if it exists), then run that app's dev server. Keyed by the app folder
87
+ // name, filtered to the app's package (e.g. `pnpm mobile` -> runs apps/mobile).
88
+ const sharedPrefix = hasShared
89
+ ? `turbo run build --filter=${SHARED_PACKAGE_NAME} && `
90
+ : '';
91
+ const appScripts = {};
92
+ for (const dir of createdAppDirs) {
93
+ const app = dir.split('/').pop(); // 'apps/mobile' -> 'mobile'
94
+ appScripts[app] = `${sharedPrefix}turbo run dev --filter=${projectName}-${app}`;
95
+ }
96
+
85
97
  return {
86
98
  name: projectName,
87
99
  version: '0.1.0',
@@ -98,6 +110,7 @@ function buildRootPackageJson(projectName, hasShared) {
98
110
  ...(hasShared
99
111
  ? { 'shared:build': `turbo run build --filter=${SHARED_PACKAGE_NAME}` }
100
112
  : {}),
113
+ ...appScripts,
101
114
  },
102
115
  devDependencies: {
103
116
  turbo: '^2.3.3',
@@ -333,7 +346,7 @@ export async function generate(plan, repoRoot, cwd = process.cwd()) {
333
346
  // 3) Generate the root config files dynamically.
334
347
  await fse.writeJson(
335
348
  path.join(projectRoot, 'package.json'),
336
- buildRootPackageJson(projectName, hasShared),
349
+ buildRootPackageJson(projectName, hasShared, createdAppDirs),
337
350
  { spaces: 2 },
338
351
  );
339
352
  logs.push('✓ package.json');
package/src/index.js CHANGED
@@ -2,8 +2,8 @@
2
2
  // index.js — entry point. Parse args + run prompts (TTY) or generate directly (flags).
3
3
  //
4
4
  // Usage:
5
- // create-app interactive (requires a real terminal)
6
- // create-app --name my-shop --be nestjs non-interactive (runs anywhere)
5
+ // create-du-app interactive (requires a real terminal)
6
+ // create-du-app --name my-shop --be nestjs non-interactive (runs anywhere)
7
7
  // node src/index.js
8
8
  //
9
9
  // Flags:
@@ -56,11 +56,11 @@ async function readVersion() {
56
56
 
57
57
  function printHelp() {
58
58
  console.log(`
59
- create-app — scaffold a product monorepo from company templates
59
+ create-du-app — scaffold a product monorepo from company templates
60
60
 
61
61
  Usage:
62
- create-app interactive (requires a real terminal)
63
- create-app --name my-shop --be nestjs non-interactive (runs anywhere)
62
+ create-du-app interactive (requires a real terminal)
63
+ create-du-app --name my-shop --be nestjs non-interactive (runs anywhere)
64
64
  node src/index.js equivalent (when not linked)
65
65
 
66
66
  Options:
@@ -73,7 +73,7 @@ Options:
73
73
  -y, --yes generate without prompting (needs --name + >=1 group)
74
74
 
75
75
  Example:
76
- create-app --name my-shop --mobile expo --fe nextjs --be nestjs
76
+ create-du-app --name my-shop --mobile expo --fe nextjs --be nestjs
77
77
 
78
78
  Add/remove templates: edit packages/cli/src/registry.js
79
79
  `);
@@ -93,7 +93,7 @@ function parseArgs(argv) {
93
93
  case '--fe': out.fe = argv[++i]; break;
94
94
  case '--be': out.be = argv[++i]; break;
95
95
  default:
96
- throw new Error(`Invalid argument: ${a}. See: create-app --help`);
96
+ throw new Error(`Invalid argument: ${a}. See: create-du-app --help`);
97
97
  }
98
98
  }
99
99
  return out;
@@ -155,7 +155,7 @@ async function main() {
155
155
  throw new Error(
156
156
  'This terminal does not support interactive mode (stdin is not a TTY).\n' +
157
157
  ' → Run it in Terminal.app/iTerm, OR use flags:\n' +
158
- ' create-app --name my-shop --mobile expo --fe nextjs --be nestjs',
158
+ ' create-du-app --name my-shop --mobile expo --fe nextjs --be nestjs',
159
159
  );
160
160
  } else {
161
161
  plan = await runPrompts();
@@ -168,7 +168,13 @@ async function main() {
168
168
  console.log('');
169
169
 
170
170
  const rel = path.relative(process.cwd(), projectRoot) || projectRoot;
171
- const msg = `Done! Next:\n\n cd ${rel} && pnpm install\n`;
171
+ // `pnpm bootstrap` is the one-command setup: it installs deps, builds
172
+ // @repo/shared, and verifies each app resolves it. Then `pnpm dev`.
173
+ const msg =
174
+ `Done! Next:\n\n` +
175
+ ` cd ${rel}\n` +
176
+ ` pnpm bootstrap # install deps + build @repo/shared + verify\n` +
177
+ ` pnpm dev # start the dev servers\n`;
172
178
  // outro() (clack) only looks good in a TTY; print plainly in non-interactive mode.
173
179
  if (process.stdout.isTTY && !hasSelectionFlags(args)) outro(msg);
174
180
  else console.log(msg);
package/src/prompts.js CHANGED
@@ -24,7 +24,7 @@ function ensureNotCancelled(value) {
24
24
  }
25
25
 
26
26
  export async function runPrompts() {
27
- intro('create-app — scaffold a product monorepo from company templates');
27
+ intro('create-du-app — scaffold a product monorepo from company templates');
28
28
 
29
29
  // 1) Project name
30
30
  const projectName = ensureNotCancelled(
@@ -0,0 +1,5 @@
1
+ # Copy to .env and fill in. Expo inlines any EXPO_PUBLIC_* var at build time.
2
+ # NEVER commit the real .env — only this example.
3
+
4
+ # Base URL of your API (include trailing slash).
5
+ EXPO_PUBLIC_BASE_URL=https://api.example.com/
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ root: true,
3
+ extends: '@react-native',
4
+ rules: {
5
+ semi: 0,
6
+ },
7
+ };
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ arrowParens: 'avoid',
3
+ bracketSameLine: true,
4
+ bracketSpacing: true,
5
+ singleQuote: true,
6
+ trailingComma: 'all',
7
+ };
@@ -0,0 +1,9 @@
1
+ module.exports = {
2
+ replaceAttrValues: {
3
+ '{currentColor}': '{props.color || "#0D1F2D"}',
4
+ '{292929}': '{props.color || "#292929"}',
5
+ '{D4D4FF}': '{props.color || "#D4D4FF"}',
6
+ '{7C7C7C}': '{props.color || "#7C7C7C"}',
7
+ '{D97706}': '{props.color || "#D97706"}',
8
+ },
9
+ }
@@ -1,11 +1,74 @@
1
- # Placeholder: Expo (mobile/expo)
1
+ # {{PROJECT_NAME}} Mobile (Expo)
2
2
 
3
- This is a **placeholder** for the **Expo** template.
3
+ An Expo + React Native starter built from the company's production core. The
4
+ reusable infrastructure (`src/core`) is ported as-is; only product-specific
5
+ features (audio/player, real-estate, IAP, maps, blur) were removed. Build your
6
+ features under `src/modules/`.
4
7
 
5
- Drop the standard Expo source here. Conventions:
8
+ ## Architecture
6
9
 
7
- - Name the template's `package.json` as **`_package.json`** (the CLI renames it on generate).
8
- - Name `.gitignore` as **`_gitignore`**, `.npmrc` as **`_npmrc`** if present.
9
- - Wherever you need the project name, write `{{PROJECT_NAME}}` — the CLI replaces it with the real name.
10
+ ```
11
+ src/
12
+ ├── app/ composition: providers, navigation, global stores (auth/loading/common), i18n
13
+ ├── core/ reusable infrastructure (see below)
14
+ ├── modules/ your features (home/profile examples included)
15
+ └── assets/ i18n, svgs (sync-generated barrel), images, lotties
16
+ ```
10
17
 
11
- `lang: js` this app counts toward the condition for creating `packages/shared`.
18
+ ### `src/core` the reusable kit
19
+ | Area | Where |
20
+ |------|-------|
21
+ | API | `services/api.service.ts` (axios + auth header + device-id + 401 session handling), `api/example.api.ts` (React Query pattern) |
22
+ | Data | `utils/query-client.util.ts`, `utils/query-persister.util.ts` (AsyncStorage offline cache) |
23
+ | Theme | `theme/` — context + `Colors` design tokens (`useTheme`, `useThemedStyles`) |
24
+ | UI kit | `components/ui/*` — button, text-field/area, checkbox, radio, toggle, modal, bottom-sheet, header, tabs, otp-input, search-box, skeleton, app-image, image-slider… |
25
+ | Forms | `components/forms/*` — react-hook-form bindings over the DS fields |
26
+ | Hooks | `hook/*` — useDebounce, useTimeout, useNetworkStatus, useEndReached, useAppNavigation… |
27
+ | Utils | `utils/*` — storage, translator (i18n), validate/schema (yup), date/number format, enum, toast, size/typography… |
28
+
29
+ ### Shared contracts
30
+ The core imports domain contracts (`ApiEndpoints`, `ExternalUrls`, enums) from
31
+ **`@repo/shared`** — generate this app alongside another JS/TS stack so that
32
+ package exists; the CLI wires `"@repo/shared": "workspace:*"` automatically.
33
+
34
+ ## Getting started
35
+
36
+ > [!TIP]
37
+ > Every native dependency in this starter ships inside **Expo Go**, so you can
38
+ > run it by scanning the QR code — **no dev build / Xcode / Android Studio
39
+ > needed**. (See [Expo Go compatibility](#expo-go-compatibility) for how.)
40
+
41
+ ```bash
42
+ pnpm bootstrap # install + build @repo/shared
43
+ pnpm --filter {{PROJECT_NAME}}-mobile typecheck # verify
44
+ pnpm --filter {{PROJECT_NAME}}-mobile start # expo start — scan QR in Expo Go
45
+ ```
46
+
47
+ Press `i` (iOS simulator) / `a` (Android emulator) in the Metro terminal, or scan
48
+ the QR with the **Expo Go** app on a physical device.
49
+
50
+ Add an icon: drop `name.svg` in `src/assets/svgs/` then `pnpm --filter {{PROJECT_NAME}}-mobile sync-svgs`.
51
+
52
+ ## Expo Go compatibility
53
+
54
+ This starter deliberately uses only libraries bundled in Expo Go, so the standard
55
+ QR-code workflow works out of the box. Where the original production app used a
56
+ bare-RN native module, the Expo equivalent is used instead:
57
+
58
+ | Need | Library used |
59
+ |------|--------------|
60
+ | Images (cache, prefetch) | `expo-image` |
61
+ | Pick / capture photos | `expo-image-picker` |
62
+ | Date / time picker | `@react-native-community/datetimepicker` |
63
+ | Gradients | `expo-linear-gradient` |
64
+ | Device locale | `expo-localization` |
65
+ | Device id | `expo-application` (+ `expo-crypto` fallback) |
66
+ | Offline query cache | `@react-native-async-storage/async-storage` |
67
+ | Env vars | `process.env.EXPO_PUBLIC_*` (set in `.env`) |
68
+ | Keyboard avoidance | React Native `KeyboardAvoidingView` |
69
+
70
+ > Need a bare-RN native module later (e.g. MMKV, a custom SDK)? Run
71
+ > `npx expo prebuild` + `expo run:ios` / `run:android` to switch to a development
72
+ > build. Until then, plain `expo start` + Expo Go is all you need.
73
+
74
+ > Before shipping: set `name`, `slug`, `scheme`, and the iOS/Android bundle ids in `app.json`.
@@ -0,0 +1,20 @@
1
+ # Native build artifacts (regenerated by `expo prebuild`)
2
+ /ios
3
+ /android
4
+ .expo/
5
+ web-build/
6
+
7
+ # Dependencies
8
+ node_modules/
9
+
10
+ # Metro
11
+ .metro-health-check*
12
+
13
+ # Env (keep .env.example)
14
+ .env
15
+ .env.*
16
+ !.env.example
17
+
18
+ # Logs / OS
19
+ *.log
20
+ .DS_Store
@@ -2,5 +2,64 @@
2
2
  "name": "{{PROJECT_NAME}}-mobile",
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
- "description": "Placeholder Expo app for {{PROJECT_NAME}}"
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "dev": "expo start",
8
+ "start": "expo start",
9
+ "android": "expo run:android",
10
+ "ios": "expo run:ios",
11
+ "prebuild": "expo prebuild",
12
+ "lint": "eslint . --ext .ts,.tsx",
13
+ "typecheck": "tsc --noEmit",
14
+ "sync-svgs": "node src/scripts/sync-svgs.js",
15
+ "sync-images": "node src/scripts/sync-images.js"
16
+ },
17
+ "dependencies": {
18
+ "@hookform/error-message": "2.0.0",
19
+ "@react-native-async-storage/async-storage": "2.2.0",
20
+ "@react-native-community/netinfo": "12.0.1",
21
+ "@react-navigation/bottom-tabs": "^7.12.0",
22
+ "@react-navigation/native": "^7.0.13",
23
+ "@react-native-community/datetimepicker": "9.1.0",
24
+ "@react-navigation/native-stack": "^7.1.14",
25
+ "@tanstack/react-query": "^5.101.0",
26
+ "@tanstack/react-query-persist-client": "^5.101.0",
27
+ "axios": "^1.7.9",
28
+ "expo": "~56.0.6",
29
+ "expo-application": "~56.0.3",
30
+ "expo-crypto": "~56.0.4",
31
+ "expo-image": "~56.0.11",
32
+ "expo-image-picker": "~56.0.18",
33
+ "expo-linear-gradient": "~56.0.4",
34
+ "expo-localization": "~56.0.6",
35
+ "i18next": "^21.5.4",
36
+ "lodash": "^4.17.21",
37
+ "lottie-react-native": "~7.3.4",
38
+ "qs": "^6.10.1",
39
+ "react": "19.2.3",
40
+ "react-hook-form": "^7.53.2",
41
+ "react-i18next": "^11.14.3",
42
+ "react-native": "0.85.3",
43
+ "react-native-gesture-handler": "~2.31.1",
44
+ "react-native-reanimated": "4.3.1",
45
+ "react-native-safe-area-context": "~5.7.0",
46
+ "react-native-screens": "4.25.2",
47
+ "react-native-svg": "15.15.4",
48
+ "react-native-toast-message": "^2.2.1",
49
+ "react-native-worklets": "0.8.3",
50
+ "yup": "^0.32.11",
51
+ "zustand": "^5.0.7"
52
+ },
53
+ "devDependencies": {
54
+ "@babel/core": "^7.25.2",
55
+ "@react-native/eslint-config": "0.85.3",
56
+ "@types/lodash": "^4.14.176",
57
+ "@types/qs": "^6.9.7",
58
+ "@types/react": "^19.1.1",
59
+ "babel-plugin-module-resolver": "^4.1.0",
60
+ "eslint": "^8.19.0",
61
+ "prettier": "2.8.8",
62
+ "react-native-svg-transformer": "^1.5.0",
63
+ "typescript": "~5.8.3"
64
+ }
6
65
  }
@@ -0,0 +1,26 @@
1
+ {
2
+ "expo": {
3
+ "name": "{{PROJECT_NAME}}",
4
+ "slug": "{{PROJECT_NAME}}",
5
+ "version": "1.0.0",
6
+ "orientation": "portrait",
7
+ "userInterfaceStyle": "automatic",
8
+ "newArchEnabled": true,
9
+ "scheme": "myapp",
10
+ "ios": {
11
+ "supportsTablet": true,
12
+ "bundleIdentifier": "com.company.myapp",
13
+ "infoPlist": {
14
+ "NSPhotoLibraryUsageDescription": "Allow $(PRODUCT_NAME) to access your photos.",
15
+ "NSCameraUsageDescription": "Allow $(PRODUCT_NAME) to use the camera."
16
+ }
17
+ },
18
+ "android": {
19
+ "package": "com.company.myapp",
20
+ "permissions": [
21
+ "android.permission.CAMERA",
22
+ "android.permission.READ_MEDIA_IMAGES"
23
+ ]
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,21 @@
1
+ module.exports = function (api) {
2
+ api.cache(true);
3
+ return {
4
+ presets: ['babel-preset-expo'],
5
+ plugins: [
6
+ [
7
+ 'module-resolver',
8
+ {
9
+ root: ['.'],
10
+ extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json', '.svg'],
11
+ alias: {
12
+ '@src': './src',
13
+ '@modules': './src/modules',
14
+ },
15
+ },
16
+ ],
17
+ // Must be last.
18
+ 'react-native-reanimated/plugin',
19
+ ],
20
+ };
21
+ };
@@ -0,0 +1,7 @@
1
+ // Must be the very first import (react-native-gesture-handler requirement).
2
+ import 'react-native-gesture-handler';
3
+ import { registerRootComponent } from 'expo';
4
+ import AppProvider from './src/app/app-provider';
5
+
6
+ // Expo registers the root component under the fixed native module name "main".
7
+ registerRootComponent(AppProvider);
@@ -0,0 +1,31 @@
1
+ const path = require('path');
2
+ const { getDefaultConfig } = require('expo/metro-config');
3
+ const { wrapWithReanimatedMetroConfig } = require('react-native-reanimated/metro-config');
4
+
5
+ // --- Monorepo paths ---
6
+ const projectRoot = __dirname;
7
+ const monorepoRoot = path.resolve(projectRoot, '../..');
8
+
9
+ /**
10
+ * Metro configuration (Expo + monorepo-aware, with SVG support)
11
+ * https://docs.expo.dev/guides/monorepos/
12
+ *
13
+ * @type {import('expo/metro-config').MetroConfig}
14
+ */
15
+ const config = getDefaultConfig(projectRoot);
16
+
17
+ // Watch the whole monorepo so edits in packages/* trigger reloads.
18
+ config.watchFolders = [monorepoRoot];
19
+
20
+ // Resolve from the app first, then the hoisted monorepo root node_modules.
21
+ config.resolver.nodeModulesPaths = [
22
+ path.resolve(projectRoot, 'node_modules'),
23
+ path.resolve(monorepoRoot, 'node_modules'),
24
+ ];
25
+
26
+ // SVG-as-component support (react-native-svg-transformer).
27
+ config.transformer.babelTransformerPath = require.resolve('react-native-svg-transformer/expo');
28
+ config.resolver.assetExts = config.resolver.assetExts.filter(ext => ext !== 'svg');
29
+ config.resolver.sourceExts = [...config.resolver.sourceExts, 'svg'];
30
+
31
+ module.exports = wrapWithReanimatedMetroConfig(config);
@@ -0,0 +1,24 @@
1
+ import React, { useEffect } from 'react';
2
+ import { StatusBar } from 'react-native';
3
+ import { useTheme } from '@src/core/theme';
4
+ import { RootNavigator } from './navigation';
5
+ import { useAuthStore } from './stores';
6
+ import { bootstrapLanguage } from './config/translation';
7
+
8
+ // Root UI component. Restores the persisted session + language, then mounts navigation.
9
+ export function App() {
10
+ const { resolved } = useTheme();
11
+ const hydrate = useAuthStore(s => s.hydrate);
12
+
13
+ useEffect(() => {
14
+ void bootstrapLanguage();
15
+ void hydrate();
16
+ }, [hydrate]);
17
+
18
+ return (
19
+ <>
20
+ <StatusBar barStyle={resolved === 'dark' ? 'light-content' : 'dark-content'} />
21
+ <RootNavigator />
22
+ </>
23
+ );
24
+ }
@@ -0,0 +1,40 @@
1
+ import React from 'react';
2
+ import { GestureHandlerRootView } from 'react-native-gesture-handler';
3
+ import { SafeAreaProvider } from 'react-native-safe-area-context';
4
+ import { I18nextProvider } from 'react-i18next';
5
+ import { onlineManager } from '@tanstack/react-query';
6
+ import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client';
7
+ import NetInfo from '@react-native-community/netinfo';
8
+ import Toast from 'react-native-toast-message';
9
+ import { queryClient, queryPersister, toastConfig } from '@src/core/utils';
10
+ import { ThemeProvider } from '@src/core/theme';
11
+ import { i18n } from './config/translation';
12
+ import { App } from './App';
13
+
14
+ // Pause/resume React Query based on connectivity (offline-first).
15
+ onlineManager.setEventListener(setOnline =>
16
+ NetInfo.addEventListener(state => setOnline(Boolean(state.isConnected))),
17
+ );
18
+
19
+ // The provider tree. Order: gesture root → persisted query cache → i18n →
20
+ // safe-area → theme → app UI. <Toast> is mounted last so it overlays all.
21
+ // Keyboard handling uses React Native's built-in KeyboardAvoidingView (in
22
+ // ScreenContainer) so the app runs in Expo Go without a custom dev build.
23
+ export default function AppProvider() {
24
+ return (
25
+ <GestureHandlerRootView style={{ flex: 1 }}>
26
+ <PersistQueryClientProvider
27
+ client={queryClient}
28
+ persistOptions={{ persister: queryPersister }}>
29
+ <I18nextProvider i18n={i18n}>
30
+ <SafeAreaProvider>
31
+ <ThemeProvider>
32
+ <App />
33
+ <Toast config={toastConfig} />
34
+ </ThemeProvider>
35
+ </SafeAreaProvider>
36
+ </I18nextProvider>
37
+ </PersistQueryClientProvider>
38
+ </GestureHandlerRootView>
39
+ );
40
+ }
@@ -0,0 +1,30 @@
1
+ import { getLocales } from 'expo-localization';
2
+ import { Translator } from '@src/core/utils';
3
+ import en from '@src/assets/i18n/en.json';
4
+ import fr from '@src/assets/i18n/fr.json';
5
+
6
+ const resources = {
7
+ en: { translation: en },
8
+ fr: { translation: fr },
9
+ };
10
+
11
+ const fallbackLng = 'en';
12
+ // expo-localization reads the OS preferred-languages list (ships in Expo Go).
13
+ const deviceLanguage = getLocales()[0]?.languageCode ?? fallbackLng;
14
+
15
+ // Initialize i18next once and expose the instance. The provider mounts it in
16
+ // app-provider.tsx; the active language can be changed via Translator.changeLanguages.
17
+ export const i18n = Translator.setup({
18
+ resources,
19
+ lng: deviceLanguage in resources ? deviceLanguage : fallbackLng,
20
+ fallbackLng,
21
+ interpolation: { escapeValue: false },
22
+ // RN's JS engine lacks full Intl.PluralRules — use i18next's v3 plural format
23
+ // so it doesn't warn and fall back at runtime.
24
+ compatibilityJSON: 'v3',
25
+ });
26
+
27
+ // Hook persisted-language restore here if you store a user preference.
28
+ export async function bootstrapLanguage(): Promise<void> {
29
+ // no-op for the starter; wire AppStorageUtil + Translator.changeLanguages here.
30
+ }
@@ -0,0 +1 @@
1
+ export * from './stores';
@@ -0,0 +1,27 @@
1
+ // Central screen registry + typed param list. Add a screen here and every
2
+ // navigation call to it (via NavigationUtil / useNavigation) is type-checked.
3
+ export enum Screen {
4
+ Home = 'Home',
5
+ Profile = 'Profile',
6
+ // Auth / feature screens the core references (e.g. session-expired reset).
7
+ // Wire real screens for these as you build the app.
8
+ SignIn = 'SignIn',
9
+ OtpVerification = 'OtpVerification',
10
+ PlayerFull = 'PlayerFull',
11
+ LibraryMain = 'LibraryMain',
12
+ }
13
+
14
+ export type NavigatorParamList = {
15
+ [Screen.Home]: undefined;
16
+ [Screen.Profile]: undefined;
17
+ [Screen.SignIn]: undefined;
18
+ [Screen.OtpVerification]: undefined;
19
+ [Screen.PlayerFull]: undefined;
20
+ [Screen.LibraryMain]: undefined;
21
+ };
22
+
23
+ declare global {
24
+ namespace ReactNavigation {
25
+ interface RootParamList extends NavigatorParamList {}
26
+ }
27
+ }