@imksh/create 1.0.25 → 1.0.26

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 (267) hide show
  1. package/package.json +1 -1
  2. package/src/commands/create.js +2 -1
  3. package/src/index.js +1 -1
  4. package/src/utils/askTemplate.js +1 -0
  5. package/templates/mern-react-native/mobile/_gitignore +43 -0
  6. package/templates/mern-react-native/mobile/package.json +2 -1
  7. package/templates/mern-react-native/mobile/src/app/(auth)/edit-profile.tsx +11 -15
  8. package/templates/mern-react-native/mobile/src/app/(tabs)/dashboard.tsx +2 -2
  9. package/templates/mern-react-native/mobile/src/app/(tabs)/search.tsx +2 -2
  10. package/templates/mern-react-native/mobile/src/config/sidebar.config.ts +0 -60
  11. package/templates/mern-react-native/mobile/src/config/tabNavigation.ts +6 -36
  12. package/templates/mern-react-native/mobile/src/services/notification.service.ts +22 -0
  13. package/templates/mern-react-native/mobile/src/store/useNotificationStore.ts +158 -33
  14. package/templates/next/next.config.mjs +1 -0
  15. package/templates/next/package.json +10 -9
  16. package/templates/next/postcss.config.js +5 -0
  17. package/templates/next/src/app/layout.js +1 -0
  18. package/templates/next/src/app/page.js +1 -1
  19. package/templates/next/src/components/layout/ProtectedRoute.jsx +3 -3
  20. package/templates/next/src/index.css +1 -0
  21. package/templates/next/src/store/useUiStore.js +13 -7
  22. package/templates/next-ts/.env.example +0 -0
  23. package/templates/next-ts/AGENTS.md +37 -0
  24. package/templates/next-ts/CLAUDE.md +1 -0
  25. package/templates/next-ts/_gitignore +0 -24
  26. package/templates/next-ts/next-env.d.ts +3 -1
  27. package/templates/next-ts/next.config.mjs +1 -0
  28. package/templates/next-ts/package.json +13 -12
  29. package/templates/next-ts/postcss.config.js +5 -0
  30. package/templates/next-ts/public/logo.png +0 -0
  31. package/templates/next-ts/src/app/error.tsx +41 -0
  32. package/templates/next-ts/src/app/layout.tsx +2 -1
  33. package/templates/next-ts/src/app/not-found.tsx +5 -0
  34. package/templates/next-ts/src/app/page.tsx +1 -1
  35. package/templates/next-ts/src/components/layout/ProtectedRoute.tsx +3 -3
  36. package/templates/next-ts/src/components/ui/Button.tsx +63 -0
  37. package/templates/next-ts/src/components/ui/Input.tsx +79 -0
  38. package/templates/next-ts/src/index.css +1 -0
  39. package/templates/next-ts/src/store/useUiStore.ts +13 -7
  40. package/templates/next-ts/tsconfig.json +19 -5
  41. package/templates/production-fullstack/client/index.html +14 -0
  42. package/templates/production-fullstack/client/package.json +47 -0
  43. package/templates/production-fullstack/client/public/_redirects +1 -0
  44. package/templates/production-fullstack/client/public/favicon.ico +0 -0
  45. package/templates/production-fullstack/client/public/favicon.svg +1 -0
  46. package/templates/production-fullstack/client/public/logo.png +0 -0
  47. package/templates/production-fullstack/client/public/manifest.json +24 -0
  48. package/templates/production-fullstack/client/public/sw.js +56 -0
  49. package/templates/production-fullstack/client/src/App.tsx +68 -0
  50. package/templates/production-fullstack/client/src/assets/animations/loading.json +1 -0
  51. package/templates/production-fullstack/client/src/assets/data/navigation.ts +29 -0
  52. package/templates/production-fullstack/client/src/assets/images/logo.png +0 -0
  53. package/templates/production-fullstack/client/src/components/layout/ProtectedRoute.tsx +23 -0
  54. package/templates/production-fullstack/client/src/components/layout/PublicLayout.tsx +13 -0
  55. package/templates/production-fullstack/client/src/components/layout/SidebarLayout.tsx +37 -0
  56. package/templates/production-fullstack/client/src/components/shared/Breadcrumbs.tsx +27 -0
  57. package/templates/production-fullstack/client/src/components/shared/LottieIcon.tsx +36 -0
  58. package/templates/production-fullstack/client/src/components/shared/NotFound.tsx +78 -0
  59. package/templates/production-fullstack/client/src/components/shared/PwaInstallPrompt.tsx +72 -0
  60. package/templates/production-fullstack/client/src/components/shared/SEO.tsx +67 -0
  61. package/templates/production-fullstack/client/src/components/shared/Scroll.tsx +25 -0
  62. package/templates/production-fullstack/client/src/components/shared/Unauthorized.tsx +76 -0
  63. package/templates/production-fullstack/client/src/components/shared/skeletons/common/CardSkeleton.tsx +23 -0
  64. package/templates/production-fullstack/client/src/components/shared/skeletons/common/DashboardSkeleton.tsx +19 -0
  65. package/templates/production-fullstack/client/src/components/shared/skeletons/common/ListSkeleton.tsx +24 -0
  66. package/templates/production-fullstack/client/src/components/shared/skeletons/common/PageSkeleton.tsx +26 -0
  67. package/templates/production-fullstack/client/src/components/shared/skeletons/common/ProfileSkeleton.tsx +23 -0
  68. package/templates/production-fullstack/client/src/components/shared/skeletons/common/Skeleton.tsx +18 -0
  69. package/templates/production-fullstack/client/src/components/shared/skeletons/common/TableSkeleton.tsx +33 -0
  70. package/templates/production-fullstack/client/src/components/ui/ConfirmModal.tsx +152 -0
  71. package/templates/production-fullstack/client/src/components/ui/Header.tsx +230 -0
  72. package/templates/production-fullstack/client/src/components/ui/Loading.tsx +19 -0
  73. package/templates/production-fullstack/client/src/components/ui/Modal.tsx +106 -0
  74. package/templates/production-fullstack/client/src/components/ui/SidebarHeader.tsx +34 -0
  75. package/templates/production-fullstack/client/src/components/ui/Table.tsx +118 -0
  76. package/templates/production-fullstack/client/src/components/ui/ToggleSwitch.tsx +38 -0
  77. package/templates/production-fullstack/client/src/components/ui/sidebar.tsx +152 -0
  78. package/templates/production-fullstack/client/src/config/index.ts +44 -0
  79. package/templates/production-fullstack/client/src/constants/navigation.ts +14 -0
  80. package/templates/production-fullstack/client/src/features/auth/api/authService.ts +19 -0
  81. package/templates/production-fullstack/client/src/features/auth/pages/Login.tsx +233 -0
  82. package/templates/production-fullstack/client/src/features/auth/store/useAuthStore.ts +143 -0
  83. package/templates/production-fullstack/client/src/features/core/pages/Home.tsx +150 -0
  84. package/templates/production-fullstack/client/src/features/core/pages/Profile.tsx +9 -0
  85. package/templates/production-fullstack/client/src/hooks/useLenis.ts +28 -0
  86. package/templates/production-fullstack/client/src/hooks/usePwaInstall.ts +45 -0
  87. package/templates/production-fullstack/client/src/hooks/useWindowSize.ts +25 -0
  88. package/templates/production-fullstack/client/src/index.css +158 -0
  89. package/templates/production-fullstack/client/src/lib/axios.ts +22 -0
  90. package/templates/production-fullstack/client/src/lib/dayjs.ts +12 -0
  91. package/templates/production-fullstack/client/src/lib/query-client.ts +11 -0
  92. package/templates/production-fullstack/client/src/lib/socket.ts +6 -0
  93. package/templates/production-fullstack/client/src/main.tsx +28 -0
  94. package/templates/production-fullstack/client/src/store/useUiStore.ts +74 -0
  95. package/templates/production-fullstack/client/src/utils/formatDate.ts +19 -0
  96. package/templates/production-fullstack/client/src/utils/getInitials.ts +10 -0
  97. package/templates/production-fullstack/client/src/vite-env.d.ts +1 -0
  98. package/templates/production-fullstack/client/tsconfig.json +25 -0
  99. package/templates/production-fullstack/client/tsconfig.node.json +10 -0
  100. package/templates/production-fullstack/client/vite.config.ts +8 -0
  101. package/templates/production-fullstack/mobile/LICENSE +21 -0
  102. package/templates/production-fullstack/mobile/app.json +84 -0
  103. package/templates/production-fullstack/mobile/assets/animations/celebrate.json +1 -0
  104. package/templates/production-fullstack/mobile/assets/animations/infinity.json +1 -0
  105. package/templates/production-fullstack/mobile/assets/animations/loading.json +1 -0
  106. package/templates/production-fullstack/mobile/assets/fonts/Inter_Bold.ttf +0 -0
  107. package/templates/production-fullstack/mobile/assets/fonts/Inter_ExtraBold.ttf +0 -0
  108. package/templates/production-fullstack/mobile/assets/fonts/Inter_Medium.ttf +0 -0
  109. package/templates/production-fullstack/mobile/assets/fonts/Inter_Regular.ttf +0 -0
  110. package/templates/production-fullstack/mobile/assets/fonts/Inter_SemiBold.ttf +0 -0
  111. package/templates/production-fullstack/mobile/assets/images/logo/logo.png +0 -0
  112. package/templates/production-fullstack/mobile/assets/images/logo/logo.svg +1 -0
  113. package/templates/production-fullstack/mobile/assets/images/logo/logoWithBg.png +0 -0
  114. package/templates/production-fullstack/mobile/babel.config.js +13 -0
  115. package/templates/production-fullstack/mobile/drizzle.config.ts +8 -0
  116. package/templates/production-fullstack/mobile/eas.json +24 -0
  117. package/templates/production-fullstack/mobile/eslint.config.js +10 -0
  118. package/templates/production-fullstack/mobile/metro.config.js +6 -0
  119. package/templates/production-fullstack/mobile/nativewind-env.d.ts +3 -0
  120. package/templates/production-fullstack/mobile/package.json +89 -0
  121. package/templates/production-fullstack/mobile/src/app/(auth)/_layout.tsx +12 -0
  122. package/templates/production-fullstack/mobile/src/app/(auth)/change-password.tsx +112 -0
  123. package/templates/production-fullstack/mobile/src/app/(auth)/edit-profile.tsx +160 -0
  124. package/templates/production-fullstack/mobile/src/app/(auth)/forgot-password.tsx +191 -0
  125. package/templates/production-fullstack/mobile/src/app/(auth)/login.tsx +253 -0
  126. package/templates/production-fullstack/mobile/src/app/_layout.tsx +102 -0
  127. package/templates/production-fullstack/mobile/src/app/global.css +82 -0
  128. package/templates/production-fullstack/mobile/src/components/common/AnimatedHeader.tsx +328 -0
  129. package/templates/production-fullstack/mobile/src/components/common/ConfirmationToast.tsx +67 -0
  130. package/templates/production-fullstack/mobile/src/components/common/Loading.tsx +26 -0
  131. package/templates/production-fullstack/mobile/src/components/common/LocationLoader.tsx +591 -0
  132. package/templates/production-fullstack/mobile/src/components/common/ScreenHeader.tsx +68 -0
  133. package/templates/production-fullstack/mobile/src/components/common/TabHeader.tsx +58 -0
  134. package/templates/production-fullstack/mobile/src/components/common/Typography.tsx +113 -0
  135. package/templates/production-fullstack/mobile/src/components/common/Welcome.tsx +55 -0
  136. package/templates/production-fullstack/mobile/src/components/ui/BottomModal.tsx +159 -0
  137. package/templates/production-fullstack/mobile/src/components/ui/ClassicTabBar.tsx +129 -0
  138. package/templates/production-fullstack/mobile/src/components/ui/CustomTabBar.tsx +238 -0
  139. package/templates/production-fullstack/mobile/src/components/ui/Sidebar.tsx +258 -0
  140. package/templates/production-fullstack/mobile/src/components/ui/buttons/Button.tsx +180 -0
  141. package/templates/production-fullstack/mobile/src/components/ui/buttons/ButtonGroup.tsx +32 -0
  142. package/templates/production-fullstack/mobile/src/components/ui/buttons/FloatingActionButton.tsx +72 -0
  143. package/templates/production-fullstack/mobile/src/components/ui/buttons/IconButton.tsx +84 -0
  144. package/templates/production-fullstack/mobile/src/components/ui/data-display/Accordion.tsx +82 -0
  145. package/templates/production-fullstack/mobile/src/components/ui/data-display/Avatar.tsx +47 -0
  146. package/templates/production-fullstack/mobile/src/components/ui/data-display/Badge.tsx +104 -0
  147. package/templates/production-fullstack/mobile/src/components/ui/data-display/Card.tsx +36 -0
  148. package/templates/production-fullstack/mobile/src/components/ui/data-display/Image.tsx +43 -0
  149. package/templates/production-fullstack/mobile/src/components/ui/data-display/ImageViewer.tsx +33 -0
  150. package/templates/production-fullstack/mobile/src/components/ui/data-display/SwipeableRow.tsx +94 -0
  151. package/templates/production-fullstack/mobile/src/components/ui/feedback/CircularProgress.tsx +38 -0
  152. package/templates/production-fullstack/mobile/src/components/ui/feedback/GestureWrapper.tsx +114 -0
  153. package/templates/production-fullstack/mobile/src/components/ui/feedback/ProgressBar.tsx +51 -0
  154. package/templates/production-fullstack/mobile/src/components/ui/feedback/Skeleton.tsx +84 -0
  155. package/templates/production-fullstack/mobile/src/components/ui/feedback/Spinner.tsx +50 -0
  156. package/templates/production-fullstack/mobile/src/components/ui/inputs/Checkbox.tsx +54 -0
  157. package/templates/production-fullstack/mobile/src/components/ui/inputs/DatePicker.tsx +186 -0
  158. package/templates/production-fullstack/mobile/src/components/ui/inputs/ImagePickerModal.tsx +129 -0
  159. package/templates/production-fullstack/mobile/src/components/ui/inputs/Input.tsx +158 -0
  160. package/templates/production-fullstack/mobile/src/components/ui/inputs/LocationPicker.tsx +211 -0
  161. package/templates/production-fullstack/mobile/src/components/ui/inputs/OTPInput.tsx +83 -0
  162. package/templates/production-fullstack/mobile/src/components/ui/inputs/PasswordInput.tsx +16 -0
  163. package/templates/production-fullstack/mobile/src/components/ui/inputs/Radio.tsx +54 -0
  164. package/templates/production-fullstack/mobile/src/components/ui/inputs/SearchBar.tsx +53 -0
  165. package/templates/production-fullstack/mobile/src/components/ui/inputs/Slider.tsx +49 -0
  166. package/templates/production-fullstack/mobile/src/components/ui/inputs/Switch.tsx +75 -0
  167. package/templates/production-fullstack/mobile/src/components/ui/inputs/TextArea.tsx +15 -0
  168. package/templates/production-fullstack/mobile/src/components/ui/inputs/WebLocationPicker.tsx +321 -0
  169. package/templates/production-fullstack/mobile/src/components/ui/layout/Container.tsx +23 -0
  170. package/templates/production-fullstack/mobile/src/components/ui/layout/Divider.tsx +20 -0
  171. package/templates/production-fullstack/mobile/src/components/ui/layout/Grid.tsx +62 -0
  172. package/templates/production-fullstack/mobile/src/components/ui/layout/KeyboardAvoidingViewWrapper.tsx +16 -0
  173. package/templates/production-fullstack/mobile/src/components/ui/layout/ScrollContainer.tsx +21 -0
  174. package/templates/production-fullstack/mobile/src/components/ui/layout/Section.tsx +51 -0
  175. package/templates/production-fullstack/mobile/src/components/ui/layout/Spacer.tsx +6 -0
  176. package/templates/production-fullstack/mobile/src/components/ui/layout/Stack.tsx +34 -0
  177. package/templates/production-fullstack/mobile/src/components/ui/navigation/Pagination.tsx +61 -0
  178. package/templates/production-fullstack/mobile/src/components/ui/navigation/ProgressStepper.tsx +66 -0
  179. package/templates/production-fullstack/mobile/src/components/ui/navigation/Tabs.tsx +173 -0
  180. package/templates/production-fullstack/mobile/src/config/sidebar.config.ts +72 -0
  181. package/templates/production-fullstack/mobile/src/config/tabNavigation.ts +64 -0
  182. package/templates/production-fullstack/mobile/src/constants/Colors.ts +71 -0
  183. package/templates/production-fullstack/mobile/src/db/index.ts +9 -0
  184. package/templates/production-fullstack/mobile/src/db/schema.ts +14 -0
  185. package/templates/production-fullstack/mobile/src/features/auth/api/auth.service.ts +35 -0
  186. package/templates/production-fullstack/mobile/src/features/auth/store/useAuthStore.ts +273 -0
  187. package/templates/production-fullstack/mobile/src/features/auth/types/auth.type.ts +14 -0
  188. package/templates/production-fullstack/mobile/src/hooks/useDebounce.ts +17 -0
  189. package/templates/production-fullstack/mobile/src/lib/axios.ts +27 -0
  190. package/templates/production-fullstack/mobile/src/lib/query-client.ts +11 -0
  191. package/templates/production-fullstack/mobile/src/lib/socket.ts +36 -0
  192. package/templates/production-fullstack/mobile/src/lib/storage.ts +55 -0
  193. package/templates/production-fullstack/mobile/src/services/permission.service.ts +214 -0
  194. package/templates/production-fullstack/mobile/src/store/localStore.ts +7 -0
  195. package/templates/production-fullstack/mobile/src/store/useNotificationStore.ts +53 -0
  196. package/templates/production-fullstack/mobile/src/types/common.type.ts +6 -0
  197. package/templates/production-fullstack/mobile/src/types/images.d.ts +24 -0
  198. package/templates/production-fullstack/mobile/src/utils/toast.ts +26 -0
  199. package/templates/production-fullstack/mobile/tailwind.config.js +71 -0
  200. package/templates/production-fullstack/mobile/tsconfig.json +23 -0
  201. package/templates/production-fullstack/server/.env.example +63 -0
  202. package/templates/production-fullstack/server/README.md +75 -0
  203. package/templates/production-fullstack/server/eslint.config.js +13 -0
  204. package/templates/production-fullstack/server/package.json +58 -0
  205. package/templates/production-fullstack/server/prisma/schema/core/attachment.prisma +14 -0
  206. package/templates/production-fullstack/server/prisma/schema/core/notification.prisma +18 -0
  207. package/templates/production-fullstack/server/prisma/schema/core/permission.prisma +26 -0
  208. package/templates/production-fullstack/server/prisma/schema/core/role.prisma +25 -0
  209. package/templates/production-fullstack/server/prisma/schema/core/user.prisma +56 -0
  210. package/templates/production-fullstack/server/prisma/schema/enums/common.prisma +13 -0
  211. package/templates/production-fullstack/server/prisma/schema/enums/notification.prisma +6 -0
  212. package/templates/production-fullstack/server/prisma/schema/enums/user.prisma +11 -0
  213. package/templates/production-fullstack/server/prisma/schema/schema.prisma +7 -0
  214. package/templates/production-fullstack/server/prisma.config.ts +14 -0
  215. package/templates/production-fullstack/server/src/app.ts +36 -0
  216. package/templates/production-fullstack/server/src/common/middlewares/auth.middleware.ts +45 -0
  217. package/templates/production-fullstack/server/src/common/middlewares/errorHandler.ts +16 -0
  218. package/templates/production-fullstack/server/src/common/middlewares/multer.ts +20 -0
  219. package/templates/production-fullstack/server/src/common/middlewares/rateLimiter.ts +53 -0
  220. package/templates/production-fullstack/server/src/common/services/email.service.ts +28 -0
  221. package/templates/production-fullstack/server/src/common/services/push.service.ts +65 -0
  222. package/templates/production-fullstack/server/src/common/services/storage.service.ts +9 -0
  223. package/templates/production-fullstack/server/src/common/types/express.d.ts +10 -0
  224. package/templates/production-fullstack/server/src/common/utils/cloudinaryUpload.ts +44 -0
  225. package/templates/production-fullstack/server/src/common/utils/emailOtp.ts +30 -0
  226. package/templates/production-fullstack/server/src/common/utils/genOtpToken.ts +22 -0
  227. package/templates/production-fullstack/server/src/common/utils/generateVapidKeys.ts +12 -0
  228. package/templates/production-fullstack/server/src/common/utils/jwt.ts +27 -0
  229. package/templates/production-fullstack/server/src/common/utils/pushHelper.ts +22 -0
  230. package/templates/production-fullstack/server/src/config/env.ts +2 -0
  231. package/templates/production-fullstack/server/src/config/logger.ts +58 -0
  232. package/templates/production-fullstack/server/src/config/prisma.ts +26 -0
  233. package/templates/production-fullstack/server/src/features/attachments/upload.controller.ts +22 -0
  234. package/templates/production-fullstack/server/src/features/attachments/upload.routes.ts +11 -0
  235. package/templates/production-fullstack/server/src/features/auth/auth.controller.ts +124 -0
  236. package/templates/production-fullstack/server/src/features/auth/auth.routes.ts +22 -0
  237. package/templates/production-fullstack/server/src/features/auth/auth.service.ts +155 -0
  238. package/templates/production-fullstack/server/src/features/notifications/push.controller.ts +55 -0
  239. package/templates/production-fullstack/server/src/features/notifications/push.routes.ts +11 -0
  240. package/templates/production-fullstack/server/src/index.ts +17 -0
  241. package/templates/production-fullstack/server/src/routes/index.ts +12 -0
  242. package/templates/production-fullstack/server/src/sockets/auth.ts +0 -0
  243. package/templates/production-fullstack/server/src/sockets/connection.ts +31 -0
  244. package/templates/production-fullstack/server/src/sockets/emitters/assignment.emitter.ts +0 -0
  245. package/templates/production-fullstack/server/src/sockets/emitters/attendance.emitter.ts +0 -0
  246. package/templates/production-fullstack/server/src/sockets/emitters/exam.emitter.ts +0 -0
  247. package/templates/production-fullstack/server/src/sockets/emitters/notification.emitter.ts +17 -0
  248. package/templates/production-fullstack/server/src/sockets/events.ts +27 -0
  249. package/templates/production-fullstack/server/src/sockets/handlers/attendance.handler.ts +0 -0
  250. package/templates/production-fullstack/server/src/sockets/handlers/chat.handler.ts +0 -0
  251. package/templates/production-fullstack/server/src/sockets/handlers/index.ts +15 -0
  252. package/templates/production-fullstack/server/src/sockets/handlers/lms.handler.ts +0 -0
  253. package/templates/production-fullstack/server/src/sockets/handlers/notification.handler.ts +39 -0
  254. package/templates/production-fullstack/server/src/sockets/index.ts +39 -0
  255. package/templates/production-fullstack/server/src/sockets/middleware.ts +54 -0
  256. package/templates/production-fullstack/server/src/sockets/rooms.ts +11 -0
  257. package/templates/production-fullstack/server/src/sockets/types.ts +32 -0
  258. package/templates/production-fullstack/server/tsconfig.json +14 -0
  259. package/templates/react-native/package.json +2 -1
  260. package/templates/react-native/src/app/(auth)/edit-profile.tsx +11 -15
  261. package/templates/react-native/src/app/(tabs)/dashboard.tsx +2 -2
  262. package/templates/react-native/src/app/(tabs)/search.tsx +2 -2
  263. package/templates/react-native/src/config/sidebar.config.ts +0 -60
  264. package/templates/react-native/src/config/tabNavigation.ts +6 -36
  265. package/templates/react-native/src/services/notification.service.ts +22 -0
  266. package/templates/react-native/src/store/useNotificationStore.ts +158 -33
  267. /package/templates/{react-native → production-fullstack/mobile}/expo-env.d.ts +0 -0
@@ -17,12 +17,15 @@ export const useUiStore = create((set, get) => ({
17
17
  set((state) => ({ isMobileMenuOpened: !state.isMobileMenuOpened }));
18
18
  },
19
19
 
20
- theme: localStorage.getItem("theme") || "light",
20
+ theme: typeof window !== "undefined" ? localStorage.getItem("theme") || "light" : "light",
21
21
 
22
22
  setTheme: (theme) => {
23
- document.documentElement.setAttribute("data-theme", theme);
24
-
25
- localStorage.setItem("theme", theme);
23
+ if (typeof document !== "undefined") {
24
+ document.documentElement.setAttribute("data-theme", theme);
25
+ }
26
+ if (typeof window !== "undefined") {
27
+ localStorage.setItem("theme", theme);
28
+ }
26
29
 
27
30
  set({ theme });
28
31
  },
@@ -30,9 +33,12 @@ export const useUiStore = create((set, get) => ({
30
33
  toggleTheme: () => {
31
34
  const nextTheme = get().theme === "light" ? "dark" : "light";
32
35
 
33
- document.documentElement.setAttribute("data-theme", nextTheme);
34
-
35
- localStorage.setItem("theme", nextTheme);
36
+ if (typeof document !== "undefined") {
37
+ document.documentElement.setAttribute("data-theme", nextTheme);
38
+ }
39
+ if (typeof window !== "undefined") {
40
+ localStorage.setItem("theme", nextTheme);
41
+ }
36
42
 
37
43
  set({ theme: nextTheme });
38
44
  },
File without changes
@@ -0,0 +1,37 @@
1
+ <!-- BEGIN:nextjs-agent-rules -->
2
+
3
+ # This is NOT the Next.js you know
4
+
5
+ This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices.
6
+
7
+ This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean.
8
+
9
+ <!-- END:nextjs-agent-rules -->
10
+
11
+ # React Starter Template Rules
12
+
13
+ When working on this template, adhere to the following tech stack and architectural conventions:
14
+
15
+ ## 1. Next.js 16 (App Router)
16
+ - Always use the **App Router** (`src/app/`). Do NOT create a `pages/` directory.
17
+ - Differentiate clearly between Server Components (default) and Client Components (add `"use client";` at the top). Use Client Components only when interactivity or browser APIs are required.
18
+ - Do not create custom `_document.tsx` or `_app.tsx`. Use `layout.tsx`.
19
+
20
+ ## 2. Tailwind CSS v4
21
+ - We use **Tailwind CSS v4**. Do not create or look for a `tailwind.config.js` or `tailwind.config.ts`.
22
+ - All styling configuration, theme variables, and custom CSS should be handled in `src/index.css` using the new `@theme` syntax.
23
+ - Do not use `@apply` if it can be solved with utility classes.
24
+
25
+ ## 3. FlyonUI
26
+ - **FlyonUI v2** is pre-configured and available.
27
+ - Prioritize using FlyonUI component classes (e.g., `btn`, `input`, `modal`, `card`) instead of building custom variants from scratch.
28
+ - The plugin is initialized in `src/index.css` via `@plugin "flyonui";`.
29
+
30
+ ## 4. Zustand (State Management)
31
+ - Place all global stores in `src/store/`.
32
+ - **CRITICAL**: Be very careful with Server-Side Rendering (SSR) hydration mismatches when using Zustand. Do not initialize store values directly with browser APIs (e.g., `localStorage`). Always wrap browser API access in `typeof window !== "undefined"` checks or use a standard hydration mechanism.
33
+
34
+ ## 5. Components Architecture
35
+ - Reusable, generic UI components (buttons, inputs) go in `src/components/ui/`.
36
+ - Domain-specific or common page components go in `src/components/common/`.
37
+ - Modals, layouts, and skeletons have their respective folders in `src/components/`.
@@ -0,0 +1 @@
1
+ @AGENTS.md
@@ -1,24 +0,0 @@
1
- # Logs
2
- logs
3
- *.log
4
- npm-debug.log*
5
- yarn-debug.log*
6
- yarn-error.log*
7
- pnpm-debug.log*
8
- lerna-debug.log*
9
-
10
- node_modules
11
- dist
12
- dist-ssr
13
- *.local
14
-
15
- # Editor directories and files
16
- .vscode/*
17
- !.vscode/extensions.json
18
- .idea
19
- .DS_Store
20
- *.suo
21
- *.ntvs*
22
- *.njsproj
23
- *.sln
24
- *.sw?
@@ -1,5 +1,7 @@
1
1
  /// <reference types="next" />
2
2
  /// <reference types="next/image-types/global" />
3
+ import "./.next/dev/types/routes.d.ts";
4
+ import "./.next/dev/types/root-params.d.ts";
3
5
 
4
6
  // NOTE: This file should not be edited
5
- // see https://nextjs.org/docs/basic-features/typescript for more information.
7
+ // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -17,6 +17,7 @@ const nextConfig = {
17
17
  },
18
18
  ];
19
19
  },
20
+ turbopack: {},
20
21
  };
21
22
 
22
23
  export default withPWA(nextConfig);
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "next-ts-template",
2
+ "name": "client",
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
5
  "scripts": {
@@ -9,28 +9,29 @@
9
9
  "lint": "next lint"
10
10
  },
11
11
  "dependencies": {
12
- "react": "^18",
13
- "react-dom": "^18",
14
- "next": "14.0.3",
15
12
  "@ducanh2912/next-pwa": "latest",
13
+ "@tailwindcss/postcss": "^4.3.3",
16
14
  "axios": "^1.6.0",
17
15
  "flyonui": "^2.4.1",
18
16
  "framer-motion": "^11.0.0",
19
17
  "lenis": "^1.1.3",
20
18
  "lottie-react": "^2.4.0",
21
- "lucide-react": "^0.292.0",
19
+ "lucide-react": "^0.470.0",
20
+ "next": "^16.3.0",
21
+ "postcss": "^8.5.26",
22
+ "react": "^19.2.8",
23
+ "react-dom": "^19.2.8",
22
24
  "react-hot-toast": "^2.4.1",
23
25
  "react-icons": "^4.11.0",
24
- "tailwindcss": "^4.3.2",
25
- "@tailwindcss/postcss": "^4.3.2",
26
+ "tailwindcss": "^4.3.3",
26
27
  "zustand": "^4.5.2"
27
28
  },
28
29
  "devDependencies": {
29
- "typescript": "^5",
30
30
  "@types/node": "^20",
31
- "@types/react": "^18",
32
- "@types/react-dom": "^18",
33
- "eslint": "^8",
34
- "eslint-config-next": "14.0.3"
31
+ "@types/react": "^19.2.18",
32
+ "@types/react-dom": "^19.2.4",
33
+ "eslint": "^10.8.1",
34
+ "eslint-config-next": "^16.3.0",
35
+ "typescript": "^5"
35
36
  }
36
37
  }
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ };
@@ -0,0 +1,41 @@
1
+ "use client";
2
+
3
+ import React, { useEffect } from "react";
4
+ import { FiAlertTriangle } from "react-icons/fi";
5
+ import Link from "next/link";
6
+
7
+ export default function Error({
8
+ error,
9
+ reset,
10
+ }: {
11
+ error: Error & { digest?: string };
12
+ reset: () => void;
13
+ }) {
14
+ useEffect(() => {
15
+ // Log the error to an error reporting service
16
+ console.error(error);
17
+ }, [error]);
18
+
19
+ return (
20
+ <div className="min-h-screen flex flex-col items-center justify-center bg-base-100 text-base-content p-6 text-center">
21
+ <div className="bg-error/10 text-error p-6 rounded-full mb-6">
22
+ <FiAlertTriangle className="w-12 h-12" />
23
+ </div>
24
+ <h1 className="text-3xl font-bold mb-3">Something went wrong!</h1>
25
+ <p className="text-slate-500 mb-8 max-w-md">
26
+ An unexpected error occurred. We have been notified and are looking into it.
27
+ </p>
28
+ <div className="flex gap-4">
29
+ <button
30
+ onClick={() => reset()}
31
+ className="btn btn-primary rounded-xl"
32
+ >
33
+ Try again
34
+ </button>
35
+ <Link href="/" className="btn btn-outline rounded-xl">
36
+ Go Home
37
+ </Link>
38
+ </div>
39
+ </div>
40
+ );
41
+ }
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import { Toaster } from "react-hot-toast";
3
3
  import Scroll from "../components/common/Scroll";
4
4
  import SEO from "../components/common/SEO";
5
- import "../index.css"; // Assuming index.css contains Tailwind
5
+ import "../index.css";
6
6
  import appConfig from "../config/appConfig";
7
7
 
8
8
  export const metadata = {
@@ -32,6 +32,7 @@ export default function RootLayout({
32
32
  <div className="min-h-screen bg-base-100 text-base-content font-sans">
33
33
  <Toaster position="top-right" />
34
34
  <Scroll />
35
+
35
36
  {children}
36
37
  </div>
37
38
  </body>
@@ -0,0 +1,5 @@
1
+ import NotFoundComponent from "../components/common/NotFound";
2
+
3
+ export default function NotFound() {
4
+ return <NotFoundComponent />;
5
+ }
@@ -2,7 +2,7 @@
2
2
  import React from "react";
3
3
  import Link from "next/link";
4
4
  import { motion } from "framer-motion";
5
- import { FiZap, FiLayers, FiCpu, FiShield, FiArrowRight } from "react-icons/fi";
5
+ import { FiZap, FiLayers, FiCpu, FiShield } from "react-icons/fi";
6
6
  import appConfig from "../config/appConfig";
7
7
  import toast from "react-hot-toast";
8
8
  import { useState } from "react";
@@ -14,16 +14,16 @@ const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ children, role }) => {
14
14
  const router = useRouter();
15
15
 
16
16
  useEffect(() => {
17
- if (!loading) {
17
+ if (!isCheckingAuth) {
18
18
  if (!user) {
19
19
  router.replace("/login");
20
20
  } else if (role && user.role !== role) {
21
21
  router.replace("/");
22
22
  }
23
23
  }
24
- }, [user, loading, role, router]);
24
+ }, [user, isCheckingAuth, role, router]);
25
25
 
26
- if (loading || !user || (role && user.role !== role)) return <Loading />;
26
+ if (isCheckingAuth || !user || (role && user.role !== role)) return <Loading />;
27
27
 
28
28
  return <>{children}</>;
29
29
  };
@@ -0,0 +1,63 @@
1
+ import React, { ButtonHTMLAttributes } from "react";
2
+ import { FiLoader } from "react-icons/fi";
3
+
4
+ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
5
+ variant?: "primary" | "secondary" | "accent" | "info" | "success" | "warning" | "error" | "ghost" | "outline";
6
+ size?: "xs" | "sm" | "md" | "lg";
7
+ isLoading?: boolean;
8
+ fullWidth?: boolean;
9
+ }
10
+
11
+ export const Button: React.FC<ButtonProps> = ({
12
+ children,
13
+ variant = "primary",
14
+ size = "md",
15
+ isLoading = false,
16
+ fullWidth = false,
17
+ className = "",
18
+ disabled,
19
+ ...props
20
+ }) => {
21
+ // FlyonUI standard button classes
22
+ const baseClasses = "btn transition-all duration-200";
23
+
24
+ const variantClasses = {
25
+ primary: "btn-primary",
26
+ secondary: "btn-secondary",
27
+ accent: "btn-accent",
28
+ info: "btn-info",
29
+ success: "btn-success",
30
+ warning: "btn-warning",
31
+ error: "btn-error",
32
+ ghost: "btn-ghost",
33
+ outline: "btn-outline",
34
+ };
35
+
36
+ const sizeClasses = {
37
+ xs: "btn-xs",
38
+ sm: "btn-sm",
39
+ md: "",
40
+ lg: "btn-lg",
41
+ };
42
+
43
+ const classes = [
44
+ baseClasses,
45
+ variantClasses[variant],
46
+ sizeClasses[size],
47
+ fullWidth ? "w-full" : "",
48
+ className,
49
+ ].filter(Boolean).join(" ");
50
+
51
+ return (
52
+ <button
53
+ className={classes}
54
+ disabled={isLoading || disabled}
55
+ {...props}
56
+ >
57
+ {isLoading ? <FiLoader className="animate-spin mr-2" /> : null}
58
+ {children}
59
+ </button>
60
+ );
61
+ };
62
+
63
+ export default Button;
@@ -0,0 +1,79 @@
1
+ import React, { InputHTMLAttributes, ReactNode } from "react";
2
+
3
+ export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
4
+ label?: string;
5
+ error?: string;
6
+ helperText?: string;
7
+ leftIcon?: ReactNode;
8
+ rightIcon?: ReactNode;
9
+ fullWidth?: boolean;
10
+ }
11
+
12
+ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
13
+ (
14
+ {
15
+ label,
16
+ error,
17
+ helperText,
18
+ leftIcon,
19
+ rightIcon,
20
+ fullWidth = true,
21
+ className = "",
22
+ id,
23
+ ...props
24
+ },
25
+ ref
26
+ ) => {
27
+ const inputId = id || (label ? label.toLowerCase().replace(/\s+/g, "-") : undefined);
28
+
29
+ const inputClasses = [
30
+ "input input-bordered",
31
+ error ? "input-error" : "",
32
+ leftIcon ? "pl-10" : "",
33
+ rightIcon ? "pr-10" : "",
34
+ fullWidth ? "w-full" : "",
35
+ className,
36
+ ]
37
+ .filter(Boolean)
38
+ .join(" ");
39
+
40
+ return (
41
+ <div className={`form-control ${fullWidth ? "w-full" : ""}`}>
42
+ {label && (
43
+ <label htmlFor={inputId} className="label">
44
+ <span className="label-text font-medium">{label}</span>
45
+ </label>
46
+ )}
47
+ <div className="relative flex items-center">
48
+ {leftIcon && (
49
+ <div className="absolute left-3 text-base-content/50 pointer-events-none">
50
+ {leftIcon}
51
+ </div>
52
+ )}
53
+ <input
54
+ id={inputId}
55
+ ref={ref}
56
+ className={inputClasses}
57
+ {...props}
58
+ />
59
+ {rightIcon && (
60
+ <div className="absolute right-3 text-base-content/50 pointer-events-none">
61
+ {rightIcon}
62
+ </div>
63
+ )}
64
+ </div>
65
+ {(error || helperText) && (
66
+ <label className="label">
67
+ <span className={`label-text-alt ${error ? "text-error" : "text-base-content/70"}`}>
68
+ {error || helperText}
69
+ </span>
70
+ </label>
71
+ )}
72
+ </div>
73
+ );
74
+ }
75
+ );
76
+
77
+ Input.displayName = "Input";
78
+
79
+ export default Input;
@@ -1,5 +1,6 @@
1
1
  @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800;900&display=swap');
2
2
  @import "tailwindcss";
3
+ @source "./";
3
4
  @plugin "flyonui";
4
5
 
5
6
 
@@ -37,12 +37,15 @@ export const useUiStore = create<UiState>((set, get) => ({
37
37
  set((state) => ({ isMobileMenuOpened: !state.isMobileMenuOpened }));
38
38
  },
39
39
 
40
- theme: localStorage.getItem("theme") || "light",
40
+ theme: typeof window !== "undefined" ? localStorage.getItem("theme") || "light" : "light",
41
41
 
42
42
  setTheme: (theme) => {
43
- document.documentElement.setAttribute("data-theme", theme);
44
-
45
- localStorage.setItem("theme", theme);
43
+ if (typeof document !== "undefined") {
44
+ document.documentElement.setAttribute("data-theme", theme);
45
+ }
46
+ if (typeof window !== "undefined") {
47
+ localStorage.setItem("theme", theme);
48
+ }
46
49
 
47
50
  set({ theme });
48
51
  },
@@ -50,9 +53,12 @@ export const useUiStore = create<UiState>((set, get) => ({
50
53
  toggleTheme: () => {
51
54
  const nextTheme = get().theme === "light" ? "dark" : "light";
52
55
 
53
- document.documentElement.setAttribute("data-theme", nextTheme);
54
-
55
- localStorage.setItem("theme", nextTheme);
56
+ if (typeof document !== "undefined") {
57
+ document.documentElement.setAttribute("data-theme", nextTheme);
58
+ }
59
+ if (typeof window !== "undefined") {
60
+ localStorage.setItem("theme", nextTheme);
61
+ }
56
62
 
57
63
  set({ theme: nextTheme });
58
64
  },
@@ -1,7 +1,11 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "es5",
4
- "lib": ["dom", "dom.iterable", "esnext"],
4
+ "lib": [
5
+ "dom",
6
+ "dom.iterable",
7
+ "esnext"
8
+ ],
5
9
  "allowJs": true,
6
10
  "skipLibCheck": true,
7
11
  "strict": true,
@@ -11,7 +15,7 @@
11
15
  "moduleResolution": "bundler",
12
16
  "resolveJsonModule": true,
13
17
  "isolatedModules": true,
14
- "jsx": "preserve",
18
+ "jsx": "react-jsx",
15
19
  "incremental": true,
16
20
  "plugins": [
17
21
  {
@@ -19,9 +23,19 @@
19
23
  }
20
24
  ],
21
25
  "paths": {
22
- "@/*": ["./src/*"]
26
+ "@/*": [
27
+ "./src/*"
28
+ ]
23
29
  }
24
30
  },
25
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
26
- "exclude": ["node_modules"]
31
+ "include": [
32
+ "next-env.d.ts",
33
+ "**/*.ts",
34
+ "**/*.tsx",
35
+ ".next/types/**/*.ts",
36
+ ".next/dev/types/**/*.ts"
37
+ ],
38
+ "exclude": [
39
+ "node_modules"
40
+ ]
27
41
  }
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" href="/favicon.svg" type="image/svg+xml" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <link rel="manifest" href="/manifest.json" />
8
+ <title>React App</title>
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ <script type="module" src="/src/main.tsx"></script>
13
+ </body>
14
+ </html>
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "client",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "tsc && vite build",
9
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10
+ "preview": "vite preview"
11
+ },
12
+ "dependencies": {
13
+ "@hookform/resolvers": "^5.7.1",
14
+ "@tailwindcss/vite": "^4.3.2",
15
+ "@tanstack/react-query": "^5.101.4",
16
+ "axios": "^1.6.0",
17
+ "dayjs": "^1.11.21",
18
+ "flyonui": "^2.4.1",
19
+ "framer-motion": "^11.0.0",
20
+ "lenis": "^1.1.3",
21
+ "lottie-react": "^2.4.0",
22
+ "lucide-react": "^0.292.0",
23
+ "react": "^18.2.0",
24
+ "react-dom": "^18.2.0",
25
+ "react-hook-form": "^7.84.0",
26
+ "react-hot-toast": "^2.4.1",
27
+ "react-icons": "^4.11.0",
28
+ "react-router-dom": "^6.18.0",
29
+ "socket.io-client": "^4.8.3",
30
+ "tailwindcss": "^4.3.2",
31
+ "zod": "^4.4.3",
32
+ "zustand": "^4.5.2"
33
+ },
34
+ "devDependencies": {
35
+ "@types/react": "^18.2.37",
36
+ "@types/react-dom": "^18.2.15",
37
+ "@typescript-eslint/eslint-plugin": "^6.10.0",
38
+ "@typescript-eslint/parser": "^6.10.0",
39
+ "@vitejs/plugin-react": "^4.2.0",
40
+ "eslint": "^8.53.0",
41
+ "eslint-plugin-react": "^7.33.2",
42
+ "eslint-plugin-react-hooks": "^4.6.0",
43
+ "eslint-plugin-react-refresh": "^0.4.4",
44
+ "typescript": "^5.2.2",
45
+ "vite": "^5.0.0"
46
+ }
47
+ }
@@ -0,0 +1 @@
1
+ /* /index.html 200