@imksh/create 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (441) hide show
  1. package/README.md +88 -0
  2. package/bin/index.js +3 -0
  3. package/package.json +43 -0
  4. package/src/commands/create.js +90 -0
  5. package/src/index.js +41 -0
  6. package/src/utils/askTemplate.js +25 -0
  7. package/src/utils/copyTemplate.js +36 -0
  8. package/src/utils/installPackages.js +25 -0
  9. package/src/utils/logger.js +17 -0
  10. package/src/utils/runGit.js +11 -0
  11. package/templates/mern/_gitignore +2 -0
  12. package/templates/mern/client/_gitignore +24 -0
  13. package/templates/mern/client/index.html +14 -0
  14. package/templates/mern/client/package.json +39 -0
  15. package/templates/mern/client/public/_redirects +1 -0
  16. package/templates/mern/client/public/favicon.ico +0 -0
  17. package/templates/mern/client/public/favicon.svg +1 -0
  18. package/templates/mern/client/public/logo.png +0 -0
  19. package/templates/mern/client/public/manifest.json +24 -0
  20. package/templates/mern/client/public/sw.js +56 -0
  21. package/templates/mern/client/src/App.jsx +68 -0
  22. package/templates/mern/client/src/assets/animations/loading.json +1 -0
  23. package/templates/mern/client/src/assets/data/navigation.js +29 -0
  24. package/templates/mern/client/src/assets/images/logo.png +0 -0
  25. package/templates/mern/client/src/components/common/Breadcrumbs.jsx +27 -0
  26. package/templates/mern/client/src/components/common/Loading.jsx +19 -0
  27. package/templates/mern/client/src/components/common/LottieIcon.jsx +36 -0
  28. package/templates/mern/client/src/components/common/NotFound.jsx +78 -0
  29. package/templates/mern/client/src/components/common/PwaInstallPrompt.jsx +72 -0
  30. package/templates/mern/client/src/components/common/SEO.jsx +67 -0
  31. package/templates/mern/client/src/components/common/Scroll.jsx +25 -0
  32. package/templates/mern/client/src/components/common/Table.jsx +110 -0
  33. package/templates/mern/client/src/components/common/ToggleSwitch.jsx +38 -0
  34. package/templates/mern/client/src/components/common/Unauthorized.jsx +76 -0
  35. package/templates/mern/client/src/components/layout/ProtectedRoute.jsx +17 -0
  36. package/templates/mern/client/src/components/layout/PublicLayout.jsx +13 -0
  37. package/templates/mern/client/src/components/layout/SidebarLayout.jsx +37 -0
  38. package/templates/mern/client/src/components/modals/ConfirmModal.jsx +135 -0
  39. package/templates/mern/client/src/components/modals/Modal.jsx +94 -0
  40. package/templates/mern/client/src/components/skeletons/common/CardSkeleton.jsx +23 -0
  41. package/templates/mern/client/src/components/skeletons/common/DashboardSkeleton.jsx +19 -0
  42. package/templates/mern/client/src/components/skeletons/common/ListSkeleton.jsx +24 -0
  43. package/templates/mern/client/src/components/skeletons/common/PageSkeleton.jsx +26 -0
  44. package/templates/mern/client/src/components/skeletons/common/ProfileSkeleton.jsx +23 -0
  45. package/templates/mern/client/src/components/skeletons/common/Skeleton.jsx +18 -0
  46. package/templates/mern/client/src/components/skeletons/common/TableSkeleton.jsx +33 -0
  47. package/templates/mern/client/src/components/ui/Header.jsx +230 -0
  48. package/templates/mern/client/src/components/ui/SidebarHeader.jsx +27 -0
  49. package/templates/mern/client/src/components/ui/sidebar.jsx +152 -0
  50. package/templates/mern/client/src/config/api.js +22 -0
  51. package/templates/mern/client/src/config/appConfig.js +44 -0
  52. package/templates/mern/client/src/config/navigation.js +14 -0
  53. package/templates/mern/client/src/hooks/useLenis.js +28 -0
  54. package/templates/mern/client/src/hooks/usePwaInstall.js +45 -0
  55. package/templates/mern/client/src/hooks/useWindowSize.js +25 -0
  56. package/templates/mern/client/src/index.css +158 -0
  57. package/templates/mern/client/src/main.jsx +24 -0
  58. package/templates/mern/client/src/pages/Home.jsx +154 -0
  59. package/templates/mern/client/src/pages/Login.jsx +196 -0
  60. package/templates/mern/client/src/pages/Profile.jsx +9 -0
  61. package/templates/mern/client/src/services/authService.js +16 -0
  62. package/templates/mern/client/src/store/useAuthStore.js +98 -0
  63. package/templates/mern/client/src/store/useUiStore.js +54 -0
  64. package/templates/mern/client/src/utils/getInitials.js +10 -0
  65. package/templates/mern/client/vite.config.js +8 -0
  66. package/templates/mern/package.json +18 -0
  67. package/templates/mern/server/.env.example +62 -0
  68. package/templates/mern/server/README.md +65 -0
  69. package/templates/mern/server/_gitignore +24 -0
  70. package/templates/mern/server/package.json +32 -0
  71. package/templates/mern/server/src/app.js +42 -0
  72. package/templates/mern/server/src/config/cloudinary.js +9 -0
  73. package/templates/mern/server/src/config/db.js +14 -0
  74. package/templates/mern/server/src/config/dotenv.js +2 -0
  75. package/templates/mern/server/src/config/email.js +30 -0
  76. package/templates/mern/server/src/config/socket.js +54 -0
  77. package/templates/mern/server/src/config/webPush.js +9 -0
  78. package/templates/mern/server/src/controllers/auth.controller.js +153 -0
  79. package/templates/mern/server/src/controllers/upload.controller.js +26 -0
  80. package/templates/mern/server/src/index.js +24 -0
  81. package/templates/mern/server/src/middleware/auth.middleware.js +43 -0
  82. package/templates/mern/server/src/middleware/errorHandler.js +22 -0
  83. package/templates/mern/server/src/middleware/multer.js +21 -0
  84. package/templates/mern/server/src/middleware/rateLimiter.js +57 -0
  85. package/templates/mern/server/src/models/otp.model.js +21 -0
  86. package/templates/mern/server/src/models/pushSubscription.model.js +32 -0
  87. package/templates/mern/server/src/models/user.model.js +43 -0
  88. package/templates/mern/server/src/routes/auth.route.js +22 -0
  89. package/templates/mern/server/src/routes/index.js +10 -0
  90. package/templates/mern/server/src/routes/upload.route.js +12 -0
  91. package/templates/mern/server/src/services/auth.service.js +162 -0
  92. package/templates/mern/server/src/services/auth.service.ts +0 -0
  93. package/templates/mern/server/src/utils/authToken.js +26 -0
  94. package/templates/mern/server/src/utils/cloudinary.js +27 -0
  95. package/templates/mern/server/src/utils/cloudinaryUpload.js +87 -0
  96. package/templates/mern/server/src/utils/emailOtp.js +190 -0
  97. package/templates/mern/server/src/utils/genOtpToken.js +20 -0
  98. package/templates/mern/server/src/utils/generateVapidKeys.js +12 -0
  99. package/templates/mern/server/src/utils/jwt.js +25 -0
  100. package/templates/mern/server/src/utils/logger.js +25 -0
  101. package/templates/mern-ts/_gitignore +2 -0
  102. package/templates/mern-ts/client/_gitignore +24 -0
  103. package/templates/mern-ts/client/index.html +14 -0
  104. package/templates/mern-ts/client/package.json +45 -0
  105. package/templates/mern-ts/client/public/_redirects +1 -0
  106. package/templates/mern-ts/client/public/favicon.ico +0 -0
  107. package/templates/mern-ts/client/public/favicon.svg +1 -0
  108. package/templates/mern-ts/client/public/logo.png +0 -0
  109. package/templates/mern-ts/client/public/manifest.json +24 -0
  110. package/templates/mern-ts/client/public/sw.js +56 -0
  111. package/templates/mern-ts/client/src/App.tsx +68 -0
  112. package/templates/mern-ts/client/src/assets/animations/loading.json +1 -0
  113. package/templates/mern-ts/client/src/assets/data/navigation.ts +29 -0
  114. package/templates/mern-ts/client/src/assets/images/logo.png +0 -0
  115. package/templates/mern-ts/client/src/components/common/Breadcrumbs.tsx +27 -0
  116. package/templates/mern-ts/client/src/components/common/Loading.tsx +19 -0
  117. package/templates/mern-ts/client/src/components/common/LottieIcon.tsx +36 -0
  118. package/templates/mern-ts/client/src/components/common/NotFound.tsx +78 -0
  119. package/templates/mern-ts/client/src/components/common/PwaInstallPrompt.tsx +72 -0
  120. package/templates/mern-ts/client/src/components/common/SEO.tsx +67 -0
  121. package/templates/mern-ts/client/src/components/common/Scroll.tsx +25 -0
  122. package/templates/mern-ts/client/src/components/common/Table.tsx +118 -0
  123. package/templates/mern-ts/client/src/components/common/ToggleSwitch.tsx +38 -0
  124. package/templates/mern-ts/client/src/components/common/Unauthorized.tsx +76 -0
  125. package/templates/mern-ts/client/src/components/layout/ProtectedRoute.tsx +23 -0
  126. package/templates/mern-ts/client/src/components/layout/PublicLayout.tsx +13 -0
  127. package/templates/mern-ts/client/src/components/layout/SidebarLayout.tsx +37 -0
  128. package/templates/mern-ts/client/src/components/modals/ConfirmModal.tsx +135 -0
  129. package/templates/mern-ts/client/src/components/modals/Modal.tsx +94 -0
  130. package/templates/mern-ts/client/src/components/skeletons/common/CardSkeleton.tsx +23 -0
  131. package/templates/mern-ts/client/src/components/skeletons/common/DashboardSkeleton.tsx +19 -0
  132. package/templates/mern-ts/client/src/components/skeletons/common/ListSkeleton.tsx +24 -0
  133. package/templates/mern-ts/client/src/components/skeletons/common/PageSkeleton.tsx +26 -0
  134. package/templates/mern-ts/client/src/components/skeletons/common/ProfileSkeleton.tsx +23 -0
  135. package/templates/mern-ts/client/src/components/skeletons/common/Skeleton.tsx +18 -0
  136. package/templates/mern-ts/client/src/components/skeletons/common/TableSkeleton.tsx +33 -0
  137. package/templates/mern-ts/client/src/components/ui/Header.tsx +230 -0
  138. package/templates/mern-ts/client/src/components/ui/SidebarHeader.tsx +27 -0
  139. package/templates/mern-ts/client/src/components/ui/sidebar.tsx +152 -0
  140. package/templates/mern-ts/client/src/config/api.ts +22 -0
  141. package/templates/mern-ts/client/src/config/appConfig.ts +44 -0
  142. package/templates/mern-ts/client/src/config/navigation.ts +14 -0
  143. package/templates/mern-ts/client/src/hooks/useLenis.ts +28 -0
  144. package/templates/mern-ts/client/src/hooks/usePwaInstall.ts +45 -0
  145. package/templates/mern-ts/client/src/hooks/useWindowSize.ts +25 -0
  146. package/templates/mern-ts/client/src/index.css +158 -0
  147. package/templates/mern-ts/client/src/main.tsx +24 -0
  148. package/templates/mern-ts/client/src/pages/Home.tsx +154 -0
  149. package/templates/mern-ts/client/src/pages/Login.tsx +196 -0
  150. package/templates/mern-ts/client/src/pages/Profile.tsx +9 -0
  151. package/templates/mern-ts/client/src/services/authService.ts +16 -0
  152. package/templates/mern-ts/client/src/store/useAuthStore.ts +98 -0
  153. package/templates/mern-ts/client/src/store/useUiStore.ts +54 -0
  154. package/templates/mern-ts/client/src/utils/getInitials.ts +10 -0
  155. package/templates/mern-ts/client/tsconfig.json +25 -0
  156. package/templates/mern-ts/client/tsconfig.node.json +10 -0
  157. package/templates/mern-ts/client/vite.config.ts +8 -0
  158. package/templates/mern-ts/package.json +19 -0
  159. package/templates/mern-ts/server/.env.example +62 -0
  160. package/templates/mern-ts/server/README.md +69 -0
  161. package/templates/mern-ts/server/_gitignore +24 -0
  162. package/templates/mern-ts/server/package.json +47 -0
  163. package/templates/mern-ts/server/src/app.ts +36 -0
  164. package/templates/mern-ts/server/src/config/cloudinary.ts +9 -0
  165. package/templates/mern-ts/server/src/config/db.ts +15 -0
  166. package/templates/mern-ts/server/src/config/dotenv.ts +2 -0
  167. package/templates/mern-ts/server/src/config/email.ts +28 -0
  168. package/templates/mern-ts/server/src/config/socket.ts +54 -0
  169. package/templates/mern-ts/server/src/config/webPush.ts +9 -0
  170. package/templates/mern-ts/server/src/controllers/auth.controller.ts +126 -0
  171. package/templates/mern-ts/server/src/controllers/upload.controller.ts +22 -0
  172. package/templates/mern-ts/server/src/index.ts +17 -0
  173. package/templates/mern-ts/server/src/middleware/auth.middleware.ts +38 -0
  174. package/templates/mern-ts/server/src/middleware/errorHandler.ts +16 -0
  175. package/templates/mern-ts/server/src/middleware/multer.ts +20 -0
  176. package/templates/mern-ts/server/src/middleware/rateLimiter.ts +53 -0
  177. package/templates/mern-ts/server/src/models/otp.model.ts +21 -0
  178. package/templates/mern-ts/server/src/models/pushSubscription.model.ts +32 -0
  179. package/templates/mern-ts/server/src/models/user.model.ts +43 -0
  180. package/templates/mern-ts/server/src/routes/auth.route.ts +22 -0
  181. package/templates/mern-ts/server/src/routes/index.ts +10 -0
  182. package/templates/mern-ts/server/src/routes/upload.route.ts +11 -0
  183. package/templates/mern-ts/server/src/services/auth.service.ts +115 -0
  184. package/templates/mern-ts/server/src/types/express.d.ts +10 -0
  185. package/templates/mern-ts/server/src/utils/cloudinaryUpload.ts +44 -0
  186. package/templates/mern-ts/server/src/utils/emailOtp.ts +30 -0
  187. package/templates/mern-ts/server/src/utils/genOtpToken.ts +22 -0
  188. package/templates/mern-ts/server/src/utils/generateVapidKeys.ts +12 -0
  189. package/templates/mern-ts/server/src/utils/jwt.ts +27 -0
  190. package/templates/mern-ts/server/src/utils/logger.ts +27 -0
  191. package/templates/mern-ts/server/tsconfig.json +14 -0
  192. package/templates/next/_gitignore +24 -0
  193. package/templates/next/package.json +20 -0
  194. package/templates/next/src/app/layout.js +7 -0
  195. package/templates/next/src/app/page.js +218 -0
  196. package/templates/next-ts/_gitignore +24 -0
  197. package/templates/next-ts/package.json +24 -0
  198. package/templates/next-ts/src/app/layout.tsx +9 -0
  199. package/templates/next-ts/src/app/page.tsx +218 -0
  200. package/templates/next-ts/tsconfig.json +27 -0
  201. package/templates/node/.env.example +62 -0
  202. package/templates/node/README.md +65 -0
  203. package/templates/node/_gitignore +24 -0
  204. package/templates/node/package.json +32 -0
  205. package/templates/node/src/app.js +42 -0
  206. package/templates/node/src/config/cloudinary.js +9 -0
  207. package/templates/node/src/config/db.js +14 -0
  208. package/templates/node/src/config/dotenv.js +2 -0
  209. package/templates/node/src/config/email.js +30 -0
  210. package/templates/node/src/config/socket.js +54 -0
  211. package/templates/node/src/config/webPush.js +9 -0
  212. package/templates/node/src/controllers/auth.controller.js +153 -0
  213. package/templates/node/src/controllers/upload.controller.js +26 -0
  214. package/templates/node/src/index.js +24 -0
  215. package/templates/node/src/middleware/auth.middleware.js +43 -0
  216. package/templates/node/src/middleware/errorHandler.js +22 -0
  217. package/templates/node/src/middleware/multer.js +21 -0
  218. package/templates/node/src/middleware/rateLimiter.js +57 -0
  219. package/templates/node/src/models/otp.model.js +21 -0
  220. package/templates/node/src/models/pushSubscription.model.js +32 -0
  221. package/templates/node/src/models/user.model.js +43 -0
  222. package/templates/node/src/routes/auth.route.js +22 -0
  223. package/templates/node/src/routes/index.js +10 -0
  224. package/templates/node/src/routes/upload.route.js +12 -0
  225. package/templates/node/src/services/auth.service.js +162 -0
  226. package/templates/node/src/services/auth.service.ts +0 -0
  227. package/templates/node/src/utils/authToken.js +26 -0
  228. package/templates/node/src/utils/cloudinary.js +27 -0
  229. package/templates/node/src/utils/cloudinaryUpload.js +87 -0
  230. package/templates/node/src/utils/emailOtp.js +190 -0
  231. package/templates/node/src/utils/genOtpToken.js +20 -0
  232. package/templates/node/src/utils/generateVapidKeys.js +12 -0
  233. package/templates/node/src/utils/jwt.js +25 -0
  234. package/templates/node/src/utils/logger.js +25 -0
  235. package/templates/node-prisma/.env.example +63 -0
  236. package/templates/node-prisma/README.md +69 -0
  237. package/templates/node-prisma/_gitignore +24 -0
  238. package/templates/node-prisma/package.json +35 -0
  239. package/templates/node-prisma/prisma/schema.prisma +41 -0
  240. package/templates/node-prisma/src/app.js +42 -0
  241. package/templates/node-prisma/src/config/cloudinary.js +9 -0
  242. package/templates/node-prisma/src/config/db.js +16 -0
  243. package/templates/node-prisma/src/config/dotenv.js +2 -0
  244. package/templates/node-prisma/src/config/email.js +30 -0
  245. package/templates/node-prisma/src/config/socket.js +54 -0
  246. package/templates/node-prisma/src/config/webPush.js +9 -0
  247. package/templates/node-prisma/src/controllers/auth.controller.js +146 -0
  248. package/templates/node-prisma/src/controllers/upload.controller.js +26 -0
  249. package/templates/node-prisma/src/index.js +24 -0
  250. package/templates/node-prisma/src/middleware/auth.middleware.js +44 -0
  251. package/templates/node-prisma/src/middleware/errorHandler.js +22 -0
  252. package/templates/node-prisma/src/middleware/multer.js +21 -0
  253. package/templates/node-prisma/src/middleware/rateLimiter.js +57 -0
  254. package/templates/node-prisma/src/routes/auth.route.js +22 -0
  255. package/templates/node-prisma/src/routes/index.js +10 -0
  256. package/templates/node-prisma/src/routes/upload.route.js +12 -0
  257. package/templates/node-prisma/src/services/auth.service.js +163 -0
  258. package/templates/node-prisma/src/services/auth.service.ts +0 -0
  259. package/templates/node-prisma/src/utils/authToken.js +26 -0
  260. package/templates/node-prisma/src/utils/cloudinary.js +27 -0
  261. package/templates/node-prisma/src/utils/cloudinaryUpload.js +87 -0
  262. package/templates/node-prisma/src/utils/emailOtp.js +190 -0
  263. package/templates/node-prisma/src/utils/genOtpToken.js +20 -0
  264. package/templates/node-prisma/src/utils/generateVapidKeys.js +12 -0
  265. package/templates/node-prisma/src/utils/jwt.js +25 -0
  266. package/templates/node-prisma/src/utils/logger.js +25 -0
  267. package/templates/node-prisma-ts/.env.example +63 -0
  268. package/templates/node-prisma-ts/README.md +73 -0
  269. package/templates/node-prisma-ts/_gitignore +24 -0
  270. package/templates/node-prisma-ts/package.json +48 -0
  271. package/templates/node-prisma-ts/prisma/schema.prisma +41 -0
  272. package/templates/node-prisma-ts/src/app.ts +36 -0
  273. package/templates/node-prisma-ts/src/config/cloudinary.ts +9 -0
  274. package/templates/node-prisma-ts/src/config/db.ts +16 -0
  275. package/templates/node-prisma-ts/src/config/dotenv.ts +2 -0
  276. package/templates/node-prisma-ts/src/config/email.ts +28 -0
  277. package/templates/node-prisma-ts/src/config/socket.ts +54 -0
  278. package/templates/node-prisma-ts/src/config/webPush.ts +9 -0
  279. package/templates/node-prisma-ts/src/controllers/auth.controller.ts +124 -0
  280. package/templates/node-prisma-ts/src/controllers/upload.controller.ts +22 -0
  281. package/templates/node-prisma-ts/src/index.ts +17 -0
  282. package/templates/node-prisma-ts/src/middleware/auth.middleware.ts +45 -0
  283. package/templates/node-prisma-ts/src/middleware/errorHandler.ts +16 -0
  284. package/templates/node-prisma-ts/src/middleware/multer.ts +20 -0
  285. package/templates/node-prisma-ts/src/middleware/rateLimiter.ts +53 -0
  286. package/templates/node-prisma-ts/src/routes/auth.route.ts +22 -0
  287. package/templates/node-prisma-ts/src/routes/index.ts +10 -0
  288. package/templates/node-prisma-ts/src/routes/upload.route.ts +11 -0
  289. package/templates/node-prisma-ts/src/services/auth.service.ts +163 -0
  290. package/templates/node-prisma-ts/src/types/express.d.ts +10 -0
  291. package/templates/node-prisma-ts/src/utils/cloudinaryUpload.ts +44 -0
  292. package/templates/node-prisma-ts/src/utils/emailOtp.ts +30 -0
  293. package/templates/node-prisma-ts/src/utils/genOtpToken.ts +22 -0
  294. package/templates/node-prisma-ts/src/utils/generateVapidKeys.ts +12 -0
  295. package/templates/node-prisma-ts/src/utils/jwt.ts +27 -0
  296. package/templates/node-prisma-ts/src/utils/logger.ts +27 -0
  297. package/templates/node-prisma-ts/tsconfig.json +14 -0
  298. package/templates/node-ts/.env.example +62 -0
  299. package/templates/node-ts/README.md +69 -0
  300. package/templates/node-ts/_gitignore +24 -0
  301. package/templates/node-ts/package.json +47 -0
  302. package/templates/node-ts/src/app.ts +36 -0
  303. package/templates/node-ts/src/config/cloudinary.ts +9 -0
  304. package/templates/node-ts/src/config/db.ts +15 -0
  305. package/templates/node-ts/src/config/dotenv.ts +2 -0
  306. package/templates/node-ts/src/config/email.ts +28 -0
  307. package/templates/node-ts/src/config/socket.ts +54 -0
  308. package/templates/node-ts/src/config/webPush.ts +9 -0
  309. package/templates/node-ts/src/controllers/auth.controller.ts +126 -0
  310. package/templates/node-ts/src/controllers/upload.controller.ts +22 -0
  311. package/templates/node-ts/src/index.ts +17 -0
  312. package/templates/node-ts/src/middleware/auth.middleware.ts +38 -0
  313. package/templates/node-ts/src/middleware/errorHandler.ts +16 -0
  314. package/templates/node-ts/src/middleware/multer.ts +20 -0
  315. package/templates/node-ts/src/middleware/rateLimiter.ts +53 -0
  316. package/templates/node-ts/src/models/otp.model.ts +21 -0
  317. package/templates/node-ts/src/models/pushSubscription.model.ts +32 -0
  318. package/templates/node-ts/src/models/user.model.ts +43 -0
  319. package/templates/node-ts/src/routes/auth.route.ts +22 -0
  320. package/templates/node-ts/src/routes/index.ts +10 -0
  321. package/templates/node-ts/src/routes/upload.route.ts +11 -0
  322. package/templates/node-ts/src/services/auth.service.ts +115 -0
  323. package/templates/node-ts/src/types/express.d.ts +10 -0
  324. package/templates/node-ts/src/utils/cloudinaryUpload.ts +44 -0
  325. package/templates/node-ts/src/utils/emailOtp.ts +30 -0
  326. package/templates/node-ts/src/utils/genOtpToken.ts +22 -0
  327. package/templates/node-ts/src/utils/generateVapidKeys.ts +12 -0
  328. package/templates/node-ts/src/utils/jwt.ts +27 -0
  329. package/templates/node-ts/src/utils/logger.ts +27 -0
  330. package/templates/node-ts/tsconfig.json +18 -0
  331. package/templates/react/.env.example +1 -0
  332. package/templates/react/_gitignore +24 -0
  333. package/templates/react/index.html +14 -0
  334. package/templates/react/package.json +39 -0
  335. package/templates/react/public/_redirects +1 -0
  336. package/templates/react/public/favicon.ico +0 -0
  337. package/templates/react/public/favicon.svg +1 -0
  338. package/templates/react/public/logo.png +0 -0
  339. package/templates/react/public/manifest.json +24 -0
  340. package/templates/react/public/sw.js +56 -0
  341. package/templates/react/src/App.jsx +68 -0
  342. package/templates/react/src/assets/animations/loading.json +1 -0
  343. package/templates/react/src/assets/data/navigation.js +29 -0
  344. package/templates/react/src/assets/images/logo.png +0 -0
  345. package/templates/react/src/components/common/Breadcrumbs.jsx +27 -0
  346. package/templates/react/src/components/common/Loading.jsx +19 -0
  347. package/templates/react/src/components/common/LottieIcon.jsx +36 -0
  348. package/templates/react/src/components/common/NotFound.jsx +78 -0
  349. package/templates/react/src/components/common/PwaInstallPrompt.jsx +72 -0
  350. package/templates/react/src/components/common/SEO.jsx +67 -0
  351. package/templates/react/src/components/common/Scroll.jsx +25 -0
  352. package/templates/react/src/components/common/Table.jsx +110 -0
  353. package/templates/react/src/components/common/ToggleSwitch.jsx +38 -0
  354. package/templates/react/src/components/common/Unauthorized.jsx +76 -0
  355. package/templates/react/src/components/layout/ProtectedRoute.jsx +17 -0
  356. package/templates/react/src/components/layout/PublicLayout.jsx +13 -0
  357. package/templates/react/src/components/layout/SidebarLayout.jsx +37 -0
  358. package/templates/react/src/components/modals/ConfirmModal.jsx +135 -0
  359. package/templates/react/src/components/modals/Modal.jsx +94 -0
  360. package/templates/react/src/components/skeletons/common/CardSkeleton.jsx +23 -0
  361. package/templates/react/src/components/skeletons/common/DashboardSkeleton.jsx +19 -0
  362. package/templates/react/src/components/skeletons/common/ListSkeleton.jsx +24 -0
  363. package/templates/react/src/components/skeletons/common/PageSkeleton.jsx +26 -0
  364. package/templates/react/src/components/skeletons/common/ProfileSkeleton.jsx +23 -0
  365. package/templates/react/src/components/skeletons/common/Skeleton.jsx +18 -0
  366. package/templates/react/src/components/skeletons/common/TableSkeleton.jsx +33 -0
  367. package/templates/react/src/components/ui/Header.jsx +230 -0
  368. package/templates/react/src/components/ui/SidebarHeader.jsx +27 -0
  369. package/templates/react/src/components/ui/sidebar.jsx +152 -0
  370. package/templates/react/src/config/api.js +22 -0
  371. package/templates/react/src/config/appConfig.js +44 -0
  372. package/templates/react/src/config/navigation.js +14 -0
  373. package/templates/react/src/hooks/useLenis.js +28 -0
  374. package/templates/react/src/hooks/usePwaInstall.js +45 -0
  375. package/templates/react/src/hooks/useWindowSize.js +25 -0
  376. package/templates/react/src/index.css +158 -0
  377. package/templates/react/src/main.jsx +24 -0
  378. package/templates/react/src/pages/Home.jsx +154 -0
  379. package/templates/react/src/pages/Login.jsx +196 -0
  380. package/templates/react/src/pages/Profile.jsx +9 -0
  381. package/templates/react/src/services/authService.js +16 -0
  382. package/templates/react/src/store/useAuthStore.js +98 -0
  383. package/templates/react/src/store/useUiStore.js +54 -0
  384. package/templates/react/src/utils/getInitials.js +10 -0
  385. package/templates/react/vite.config.js +8 -0
  386. package/templates/react-ts/_gitignore +24 -0
  387. package/templates/react-ts/index.html +14 -0
  388. package/templates/react-ts/package.json +45 -0
  389. package/templates/react-ts/public/_redirects +1 -0
  390. package/templates/react-ts/public/favicon.ico +0 -0
  391. package/templates/react-ts/public/favicon.svg +1 -0
  392. package/templates/react-ts/public/logo.png +0 -0
  393. package/templates/react-ts/public/manifest.json +24 -0
  394. package/templates/react-ts/public/sw.js +56 -0
  395. package/templates/react-ts/src/App.tsx +68 -0
  396. package/templates/react-ts/src/assets/animations/loading.json +1 -0
  397. package/templates/react-ts/src/assets/data/navigation.ts +29 -0
  398. package/templates/react-ts/src/assets/images/logo.png +0 -0
  399. package/templates/react-ts/src/components/common/Breadcrumbs.tsx +27 -0
  400. package/templates/react-ts/src/components/common/Loading.tsx +19 -0
  401. package/templates/react-ts/src/components/common/LottieIcon.tsx +36 -0
  402. package/templates/react-ts/src/components/common/NotFound.tsx +78 -0
  403. package/templates/react-ts/src/components/common/PwaInstallPrompt.tsx +72 -0
  404. package/templates/react-ts/src/components/common/SEO.tsx +67 -0
  405. package/templates/react-ts/src/components/common/Scroll.tsx +25 -0
  406. package/templates/react-ts/src/components/common/Table.tsx +118 -0
  407. package/templates/react-ts/src/components/common/ToggleSwitch.tsx +38 -0
  408. package/templates/react-ts/src/components/common/Unauthorized.tsx +76 -0
  409. package/templates/react-ts/src/components/layout/ProtectedRoute.tsx +23 -0
  410. package/templates/react-ts/src/components/layout/PublicLayout.tsx +13 -0
  411. package/templates/react-ts/src/components/layout/SidebarLayout.tsx +37 -0
  412. package/templates/react-ts/src/components/modals/ConfirmModal.tsx +135 -0
  413. package/templates/react-ts/src/components/modals/Modal.tsx +94 -0
  414. package/templates/react-ts/src/components/skeletons/common/CardSkeleton.tsx +23 -0
  415. package/templates/react-ts/src/components/skeletons/common/DashboardSkeleton.tsx +19 -0
  416. package/templates/react-ts/src/components/skeletons/common/ListSkeleton.tsx +24 -0
  417. package/templates/react-ts/src/components/skeletons/common/PageSkeleton.tsx +26 -0
  418. package/templates/react-ts/src/components/skeletons/common/ProfileSkeleton.tsx +23 -0
  419. package/templates/react-ts/src/components/skeletons/common/Skeleton.tsx +18 -0
  420. package/templates/react-ts/src/components/skeletons/common/TableSkeleton.tsx +33 -0
  421. package/templates/react-ts/src/components/ui/Header.tsx +230 -0
  422. package/templates/react-ts/src/components/ui/SidebarHeader.tsx +27 -0
  423. package/templates/react-ts/src/components/ui/sidebar.tsx +152 -0
  424. package/templates/react-ts/src/config/api.ts +22 -0
  425. package/templates/react-ts/src/config/appConfig.ts +44 -0
  426. package/templates/react-ts/src/config/navigation.ts +14 -0
  427. package/templates/react-ts/src/hooks/useLenis.ts +28 -0
  428. package/templates/react-ts/src/hooks/usePwaInstall.ts +45 -0
  429. package/templates/react-ts/src/hooks/useWindowSize.ts +25 -0
  430. package/templates/react-ts/src/index.css +158 -0
  431. package/templates/react-ts/src/main.tsx +24 -0
  432. package/templates/react-ts/src/pages/Home.tsx +154 -0
  433. package/templates/react-ts/src/pages/Login.tsx +196 -0
  434. package/templates/react-ts/src/pages/Profile.tsx +9 -0
  435. package/templates/react-ts/src/services/authService.ts +16 -0
  436. package/templates/react-ts/src/store/useAuthStore.ts +98 -0
  437. package/templates/react-ts/src/store/useUiStore.ts +54 -0
  438. package/templates/react-ts/src/utils/getInitials.ts +10 -0
  439. package/templates/react-ts/tsconfig.json +25 -0
  440. package/templates/react-ts/tsconfig.node.json +10 -0
  441. package/templates/react-ts/vite.config.ts +8 -0
@@ -0,0 +1,10 @@
1
+ import express from "express";
2
+ import authRoutes from "./auth.route.js";
3
+ import uploadRoutes from "./upload.route.js";
4
+
5
+ const router = express.Router();
6
+
7
+ router.use("/auth", authRoutes);
8
+ router.use("/upload", uploadRoutes);
9
+
10
+ export default router;
@@ -0,0 +1,11 @@
1
+ import express from "express";
2
+ import { upload } from "../middleware/multer.js";
3
+ import { uploadFile } from "../controllers/upload.controller.js";
4
+ import { protect } from "../middleware/auth.middleware.js";
5
+ import { uploadLimiter } from "../middleware/rateLimiter.js";
6
+
7
+ const router = express.Router();
8
+
9
+ router.post("/", protect, uploadLimiter, upload.single("file"), uploadFile);
10
+
11
+ export default router;
@@ -0,0 +1,163 @@
1
+ import bcrypt from "bcrypt";
2
+ import { prisma } from "../config/db.js";
3
+ import { sendOtpEmail } from "../utils/emailOtp.js";
4
+ import { uploadSingleToCloudinary, deleteFromCloudinary } from "../utils/cloudinaryUpload.js";
5
+ import logger from "../utils/logger.js";
6
+
7
+ export const authService = {
8
+ signup: async ({ name, email, phone, password }: any) => {
9
+ const existingUser = await prisma.user.findUnique({
10
+ where: { email },
11
+ });
12
+ if (existingUser) {
13
+ const err: any = new Error("User already exists");
14
+ err.status = 409;
15
+ throw err;
16
+ }
17
+
18
+ const salt = await bcrypt.genSalt(10);
19
+ const hashedPassword = await bcrypt.hash(password, salt);
20
+ const photoURL = `https://placehold.co/600x400?text=${name.charAt(0).toUpperCase()}`;
21
+
22
+ const newUser = await prisma.user.create({
23
+ data: {
24
+ name,
25
+ email: email.toLowerCase(),
26
+ phone,
27
+ password: hashedPassword,
28
+ avatarUrl: photoURL,
29
+ avatarPublicId: "",
30
+ },
31
+ });
32
+
33
+ return newUser;
34
+ },
35
+
36
+ login: async ({ email, password }: any) => {
37
+ const user = await prisma.user.findUnique({
38
+ where: { email },
39
+ });
40
+ if (!user) {
41
+ const err: any = new Error("User not found");
42
+ err.status = 404;
43
+ throw err;
44
+ }
45
+
46
+ const isValid = await bcrypt.compare(password, user.password);
47
+ if (!isValid) {
48
+ const err: any = new Error("Invalid Credentials");
49
+ err.status = 401;
50
+ throw err;
51
+ }
52
+
53
+ return user;
54
+ },
55
+
56
+ generateOtp: async (email: string) => {
57
+ const user = await prisma.user.findUnique({
58
+ where: { email },
59
+ });
60
+ if (!user) {
61
+ const err: any = new Error("User not found");
62
+ err.status = 404;
63
+ throw err;
64
+ }
65
+
66
+ const existingOtp = await prisma.otp.findUnique({
67
+ where: { email },
68
+ });
69
+ if (existingOtp) {
70
+ await prisma.otp.delete({
71
+ where: { email },
72
+ });
73
+ }
74
+
75
+ const otp = Math.floor(100000 + Math.random() * 900000).toString();
76
+ const hashedOtp = await bcrypt.hash(otp, 10);
77
+
78
+ await prisma.otp.create({
79
+ data: {
80
+ email,
81
+ otp: hashedOtp,
82
+ },
83
+ });
84
+
85
+ await sendOtpEmail(email, otp);
86
+ return true;
87
+ },
88
+
89
+ verifyOtp: async ({ email, otp }: any) => {
90
+ const user = await prisma.user.findUnique({
91
+ where: { email },
92
+ });
93
+ if (!user) {
94
+ const err: any = new Error("User not found");
95
+ err.status = 404;
96
+ throw err;
97
+ }
98
+
99
+ const existingOtp = await prisma.otp.findUnique({
100
+ where: { email },
101
+ });
102
+ if (!existingOtp) {
103
+ const err: any = new Error("OTP match failed");
104
+ err.status = 400;
105
+ throw err;
106
+ }
107
+
108
+ const isMatched = await bcrypt.compare(otp, existingOtp.otp);
109
+ if (!isMatched) {
110
+ const err: any = new Error("OTP match failed");
111
+ err.status = 400;
112
+ throw err;
113
+ }
114
+
115
+ return user;
116
+ },
117
+
118
+ resetPassword: async (user: any, newPassword: any) => {
119
+ const hashedPassword = await bcrypt.hash(newPassword, 10);
120
+ await prisma.user.update({
121
+ where: { id: user.id },
122
+ data: { password: hashedPassword },
123
+ });
124
+ return true;
125
+ },
126
+
127
+ updateProfile: async (userId: any, { name, phone, file }: any) => {
128
+ const user = await prisma.user.findUnique({
129
+ where: { id: userId },
130
+ });
131
+ if (!user) {
132
+ const err: any = new Error("User not found");
133
+ err.status = 404;
134
+ throw err;
135
+ }
136
+
137
+ const updateData: any = {};
138
+ if (name) updateData.name = name;
139
+ if (phone) updateData.phone = phone;
140
+
141
+ if (file) {
142
+ const uploadResult = await uploadSingleToCloudinary(file, {
143
+ folder: "codelab/avatars",
144
+ });
145
+
146
+ if (user.avatarPublicId) {
147
+ await deleteFromCloudinary(user.avatarPublicId).catch((err) =>
148
+ logger.error("Old avatar delete error", err)
149
+ );
150
+ }
151
+
152
+ updateData.avatarUrl = uploadResult.url;
153
+ updateData.avatarPublicId = uploadResult.publicId;
154
+ }
155
+
156
+ const updatedUser = await prisma.user.update({
157
+ where: { id: userId },
158
+ data: updateData,
159
+ });
160
+
161
+ return updatedUser;
162
+ },
163
+ };
@@ -0,0 +1,10 @@
1
+ import { Express } from "express";
2
+
3
+ declare global {
4
+ namespace Express {
5
+ interface Request {
6
+ user?: any;
7
+ file?: any;
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,44 @@
1
+ import cloudinary from "../config/cloudinary.js";
2
+ import logger from "./logger.js";
3
+
4
+ const uploadToCloudinary = async (file: any, options: any = {}) => {
5
+ if (!file?.buffer) {
6
+ throw new Error("Invalid file.");
7
+ }
8
+ const dataURI = `data:${file.mimetype};base64,${file.buffer.toString("base64")}`;
9
+ const result = await cloudinary.uploader.upload(dataURI, {
10
+ folder: options.folder || "uploads",
11
+ ...options,
12
+ });
13
+ return {
14
+ url: result.secure_url,
15
+ publicId: result.public_id,
16
+ };
17
+ };
18
+
19
+ export const uploadSingleToCloudinary = async (file: any, options: any = {}) => {
20
+ try {
21
+ return await uploadToCloudinary(file, options);
22
+ } catch (error) {
23
+ logger.error("Cloudinary Upload Error", error);
24
+ throw new Error("Failed to upload image.");
25
+ }
26
+ };
27
+
28
+ export const uploadMultipleToCloudinary = async (files: any[] = [], options: any = {}) => {
29
+ try {
30
+ return await Promise.all(files.map((file) => uploadToCloudinary(file, options)));
31
+ } catch (error) {
32
+ logger.error("Cloudinary Upload Error", error);
33
+ throw new Error("Failed to upload images.");
34
+ }
35
+ };
36
+
37
+ export const deleteFromCloudinary = async (publicId: string) => {
38
+ try {
39
+ return await cloudinary.uploader.destroy(publicId);
40
+ } catch (error) {
41
+ logger.error("Cloudinary Delete Error", error);
42
+ throw new Error("Failed to delete image.");
43
+ }
44
+ };
@@ -0,0 +1,30 @@
1
+ import sendEmail from "../config/email.js";
2
+
3
+ const APP_NAME = process.env.APP_NAME || "My App";
4
+ const APP_URL = process.env.APP_URL || "";
5
+ const APP_PRIMARY_COLOR = process.env.APP_PRIMARY_COLOR || "#2563eb";
6
+
7
+ export const emailOtp = (otp: string, expiry = 10) => ({
8
+ subject: `${APP_NAME} - Verification Code`,
9
+ html: `
10
+ <!DOCTYPE html>
11
+ <html lang="en">
12
+ <head>
13
+ <meta charset="UTF-8" />
14
+ <title>${APP_NAME}</title>
15
+ </head>
16
+ <body style="margin:0;padding:40px;background:#f3f4f6;font-family:Arial,sans-serif;">
17
+ <div style="background:#fff;border-radius:12px;padding:30px;max-width:500px;margin:auto;">
18
+ <h2>Verification Code</h2>
19
+ <p>Your code is valid for ${expiry} minutes:</p>
20
+ <div style="font-size:32px;font-weight:bold;color:${APP_PRIMARY_COLOR};text-align:center;margin:20px 0;">${otp}</div>
21
+ </div>
22
+ </body>
23
+ </html>
24
+ `,
25
+ });
26
+
27
+ export const sendOtpEmail = async (to: string, otp: string, expiry = 10) => {
28
+ const template = emailOtp(otp, expiry);
29
+ await sendEmail(to, template.subject, template.html);
30
+ };
@@ -0,0 +1,22 @@
1
+ import jwt from "jsonwebtoken";
2
+ import { Response } from "express";
3
+
4
+ const genOtpToken = (user: any, res?: Response) => {
5
+ const JWT_SECRET = process.env.JWT_SECRET || "fallbacksecret";
6
+ const token = jwt.sign({ id: user._id || user.id }, JWT_SECRET, {
7
+ expiresIn: "10m",
8
+ });
9
+
10
+ if (res) {
11
+ res.cookie("token", token, {
12
+ httpOnly: true,
13
+ secure: process.env.NODE_ENV === "production",
14
+ sameSite: "strict",
15
+ maxAge: 10 * 60 * 1000, // 10 minutes
16
+ });
17
+ }
18
+
19
+ return token;
20
+ };
21
+
22
+ export default genOtpToken;
@@ -0,0 +1,12 @@
1
+ import webpush from "web-push";
2
+ import logger from "./logger.js";
3
+
4
+ const generateVapidKeys = () => {
5
+ const vapidKeys = webpush.generateVAPIDKeys();
6
+ logger.info("Generated VAPID Keys:");
7
+ logger.info(`Public Key: ${vapidKeys.publicKey}`);
8
+ logger.info(`Private Key: ${vapidKeys.privateKey}`);
9
+ return vapidKeys;
10
+ };
11
+
12
+ export default generateVapidKeys;
@@ -0,0 +1,27 @@
1
+ import jwt from "jsonwebtoken";
2
+ import { Response } from "express";
3
+
4
+ export const generateToken = (user: any, res?: Response) => {
5
+ const payload = { id: user._id || user.id };
6
+ const JWT_SECRET = process.env.JWT_SECRET || "fallbacksecret";
7
+ const token = jwt.sign(payload, JWT_SECRET, { expiresIn: "30d" });
8
+
9
+ if (res) {
10
+ res.cookie("token", token, {
11
+ httpOnly: true,
12
+ secure: process.env.NODE_ENV === "production",
13
+ sameSite: "strict",
14
+ maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
15
+ });
16
+ }
17
+ return token;
18
+ };
19
+
20
+ export const verifyToken = (token: string) => {
21
+ try {
22
+ const JWT_SECRET = process.env.JWT_SECRET || "fallbacksecret";
23
+ return jwt.verify(token, JWT_SECRET);
24
+ } catch (error) {
25
+ return null;
26
+ }
27
+ };
@@ -0,0 +1,27 @@
1
+ const colors = {
2
+ reset: "\x1b[0m",
3
+ info: "\x1b[36m", // Cyan
4
+ success: "\x1b[32m", // Green
5
+ warn: "\x1b[33m", // Yellow
6
+ error: "\x1b[31m", // Red
7
+ timestamp: "\x1b[90m", // Gray
8
+ };
9
+
10
+ type LogLevel = "info" | "success" | "warn" | "error";
11
+
12
+ const formatMessage = (level: LogLevel, message: string) => {
13
+ const timestamp = new Date().toISOString();
14
+ return `${colors.timestamp}[${timestamp}]${colors.reset} ${colors[level] || colors.reset}[${level.toUpperCase()}]${colors.reset} ${message}`;
15
+ };
16
+
17
+ export const logger = {
18
+ info: (msg: string) => console.log(formatMessage("info", msg)),
19
+ success: (msg: string) => console.log(formatMessage("success", msg)),
20
+ warn: (msg: string) => console.warn(formatMessage("warn", msg)),
21
+ error: (msg: string, err?: any) => {
22
+ console.error(formatMessage("error", msg));
23
+ if (err) console.error(err);
24
+ },
25
+ };
26
+
27
+ export default logger;
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "esModuleInterop": true,
7
+ "forceConsistentCasingInFileNames": true,
8
+ "strict": true,
9
+ "skipLibCheck": true,
10
+ "outDir": "./dist",
11
+ "rootDir": "./src"
12
+ },
13
+ "include": ["src/**/*"]
14
+ }
@@ -0,0 +1,62 @@
1
+ # ==========================
2
+ # Application
3
+ # ==========================
4
+ NODE_ENV=development
5
+ PORT=5001
6
+
7
+ APP_NAME=My App
8
+ APP_URL=http://localhost:5173
9
+ APP_EMAIL=noreply@example.com
10
+ APP_PRIMARY_COLOR=#2563eb
11
+
12
+ # ==========================
13
+ # Database
14
+ # ==========================
15
+ MONGO_URI=
16
+
17
+ # ==========================
18
+ # JWT
19
+ # ==========================
20
+ JWT_SECRET=
21
+ JWT_EXPIRES_IN=7d
22
+
23
+ # ==========================
24
+ # Cloudinary
25
+ # ==========================
26
+ CLOUDINARY_CLOUD_NAME=
27
+ CLOUDINARY_API_KEY=
28
+ CLOUDINARY_API_SECRET=
29
+
30
+ # ==========================
31
+ # Email (SMTP)
32
+ # ==========================
33
+ SMTP_HOST=smtp.gmail.com
34
+ SMTP_PORT=587
35
+ SMTP_SECURE=false
36
+ SMTP_USER=
37
+ SMTP_PASS=
38
+ SMTP_FROM="My App <noreply@example.com>"
39
+
40
+ # ==========================
41
+ # CORS
42
+ # ==========================
43
+ CLIENT_URL=http://localhost:5173
44
+
45
+ # ==========================
46
+ # Cookie
47
+ # ==========================
48
+ COOKIE_NAME=token
49
+ COOKIE_EXPIRES_IN=7d
50
+
51
+ # ==========================
52
+ # Rate Limiting
53
+ # ==========================
54
+ RATE_LIMIT_WINDOW=15
55
+ RATE_LIMIT_MAX=100
56
+
57
+ # ==========================
58
+ # Rate Limiting
59
+ # ==========================
60
+ VAPID_PRIVATE_KEY=
61
+ VAPID_PUBLIC_KEY=
62
+ VAPID_SUBJECT=mailto:noreply@example.com
@@ -0,0 +1,69 @@
1
+ # Node.js TypeScript Backend Boilerplate
2
+
3
+ A production-ready, strongly-typed Node.js & Express boilerplate project with best-practice architectures, modular routing, and TypeScript compilation.
4
+
5
+ ## Features
6
+
7
+ - ⚙️ **Modular Architecture:** Express application setup decoupled into `app.ts` (middleware + router wiring) and `index.ts` (server initialization & db connection).
8
+ - 📝 **Colorized Logging:** Zero-dependency custom logger with timestamped success, warning, info, and error layouts.
9
+ - 🛡️ **Security Out-of-the-Box:** Pre-configured with Helmet headers, CORS policies, and global rate limiters (`apiLimiter`, `authLimiter`, `uploadLimiter`).
10
+ - 🔑 **Authentication & JWT:** Custom middlewares for route protection, sign-ups, and log-ins with HTTP-only cookie-based tokens.
11
+ - 📧 **SMTP Mailer & OTP:** Standard mailer transport using Gmail NodeMailer wrapper, integrated with an OTP generator and email template.
12
+ - 🖼️ **File Uploads:** Cloudinary integration utilizing Multer memory buffers for secure, single or multi-file uploads.
13
+ - 🔌 **Socket.io Setup:** Pre-installed Socket.io hooks mapping connected user sessions to active sockets.
14
+ - ✉️ **Web Push:** Push notifications integration powered by VAPID key generators and web-push subscriptions.
15
+ - 📦 **TSX Engine:** Fast runtime TS loader supporting ESM resolutions natively with instant reloads.
16
+
17
+ ## Getting Started
18
+
19
+ ### 1. Configure Environment Variables
20
+
21
+ Create a `.env` file in the root directory (based on `.env.example`):
22
+
23
+ ```env
24
+ PORT=5002
25
+ JWT_SECRET=your_super_secret_jwt_key
26
+ MONGO_URI=your_mongodb_connection_uri
27
+
28
+ # Cloudinary
29
+ CLOUDINARY_CLOUD_NAME=your_cloud_name
30
+ CLOUDINARY_API_KEY=your_api_key
31
+ CLOUDINARY_API_SECRET=your_api_secret
32
+
33
+ # SMTP Settings
34
+ GMAIL_USER=your_email@gmail.com
35
+ GMAIL_PASSCODE=your_app_password
36
+
37
+ # Web Push
38
+ VAPID_SUBJECT=mailto:your_email@example.com
39
+ VAPID_PUBLIC_KEY=your_vapid_public_key
40
+ VAPID_PRIVATE_KEY=your_vapid_private_key
41
+ ```
42
+
43
+ ### 2. Install & Start Development
44
+
45
+ ```bash
46
+ # Install dependencies
47
+ npm install
48
+
49
+ # Start development server with reload (via tsx)
50
+ npm run dev
51
+
52
+ # Build the project to JS
53
+ npm run build
54
+
55
+ # Start production compiled server
56
+ npm start
57
+ ```
58
+
59
+ ## API Endpoints
60
+
61
+ ### Auth Routes (`/api/auth`)
62
+ - `POST /signup` - Registers a new user session
63
+ - `POST /login` - Log in user and write token cookie
64
+ - `POST /logout` - Clear token session cookies
65
+ - `GET /me` - Returns logged-in user profile (requires auth)
66
+ - `PUT /me` - Edit profile info and upload avatars (requires auth)
67
+
68
+ ### Upload Routes (`/api/upload`)
69
+ - `POST /` - Securely uploads image/file to Cloudinary (requires auth)
@@ -0,0 +1,24 @@
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?
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "/Users/karan/workspace/Projects/boilerplate/test-app-node-ts",
3
+ "version": "1.0.0",
4
+ "main": "src/index.ts",
5
+ "type": "module",
6
+ "scripts": {
7
+ "start": "tsx src/index.ts",
8
+ "dev": "tsx watch src/index.ts",
9
+ "build": "tsc",
10
+ "generate:vapid": "node ./src/utils/generateVapidKeys.js"
11
+ },
12
+ "dependencies": {
13
+ "bcrypt": "^5.1.1",
14
+ "cloudinary": "^2.0.0",
15
+ "compression": "^1.7.4",
16
+ "cookie-parser": "^1.4.6",
17
+ "cors": "^2.8.5",
18
+ "dotenv": "^16.3.1",
19
+ "express": "^4.18.2",
20
+ "express-rate-limit": "^7.1.4",
21
+ "helmet": "^7.1.0",
22
+ "jsonwebtoken": "^9.0.2",
23
+ "mongoose": "^8.0.0",
24
+ "morgan": "^1.10.0",
25
+ "multer": "^1.4.5-lts.1",
26
+ "nodemailer": "^6.9.7",
27
+ "socket.io": "^4.7.2",
28
+ "web-push": "^3.6.6"
29
+ },
30
+ "devDependencies": {
31
+ "@types/bcrypt": "^5.0.2",
32
+ "@types/compression": "^1.7.5",
33
+ "@types/cookie-parser": "^1.4.6",
34
+ "@types/cors": "^2.8.17",
35
+ "@types/express": "^4.17.21",
36
+ "@types/jsonwebtoken": "^9.0.5",
37
+ "@types/morgan": "^1.9.9",
38
+ "@types/multer": "^1.4.11",
39
+ "@types/node": "^20.9.0",
40
+ "@types/nodemailer": "^6.4.14",
41
+ "@types/web-push": "^3.6.3",
42
+ "nodemon": "^3.0.1",
43
+ "ts-node": "^10.9.1",
44
+ "tsx": "^4.23.1",
45
+ "typescript": "^5.2.2"
46
+ }
47
+ }
@@ -0,0 +1,36 @@
1
+ import express, { Request, Response, NextFunction } from "express";
2
+ import helmet from "helmet";
3
+ import cors from "cors";
4
+ import compression from "compression";
5
+ import cookieParser from "cookie-parser";
6
+ import morgan from "morgan";
7
+ import apiRoutes from "./routes/index.js";
8
+ import { notFound, errorHandler } from "./middleware/errorHandler.js";
9
+ import { apiLimiter } from "./middleware/rateLimiter.js";
10
+
11
+ const app = express();
12
+
13
+ app.use(helmet());
14
+ app.use(
15
+ cors({
16
+ origin: process.env.CLIENT_URL || "http://localhost:5173",
17
+ credentials: true,
18
+ })
19
+ );
20
+ app.use(compression());
21
+ app.use(express.json());
22
+ app.use(express.urlencoded({ extended: true }));
23
+ app.use(cookieParser());
24
+ app.use(morgan("dev"));
25
+
26
+ app.use(apiLimiter);
27
+ app.use("/api", apiRoutes);
28
+
29
+ app.get("/api/health", (req: Request, res: Response) => {
30
+ res.status(200).json({ success: true, message: "API is running" });
31
+ });
32
+
33
+ app.use(notFound);
34
+ app.use(errorHandler);
35
+
36
+ export default app;
@@ -0,0 +1,9 @@
1
+ import { v2 as cloudinary } from "cloudinary";
2
+
3
+ cloudinary.config({
4
+ cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
5
+ api_key: process.env.CLOUDINARY_API_KEY,
6
+ api_secret: process.env.CLOUDINARY_API_SECRET,
7
+ });
8
+
9
+ export default cloudinary;
@@ -0,0 +1,15 @@
1
+ import mongoose from "mongoose";
2
+ import logger from "../utils/logger.js";
3
+
4
+ const connectDB = async () => {
5
+ try {
6
+ const MONGO_URI = process.env.MONGO_URI || "mongodb://localhost:27017/test";
7
+ const conn = await mongoose.connect(MONGO_URI);
8
+ logger.success(`MongoDB connected: ${conn.connection.host}`);
9
+ } catch (error: any) {
10
+ logger.error(`MongoDB connection error: ${error.message}`, error);
11
+ process.exit(1);
12
+ }
13
+ };
14
+
15
+ export default connectDB;
@@ -0,0 +1,2 @@
1
+ import dotenv from "dotenv";
2
+ dotenv.config();
@@ -0,0 +1,28 @@
1
+ import nodemailer from "nodemailer";
2
+ import logger from "../utils/logger.js";
3
+
4
+ const sendEmail = async (to: string, subject: string, message: string) => {
5
+ try {
6
+ const transporter = nodemailer.createTransport({
7
+ service: "gmail",
8
+ auth: {
9
+ user: process.env.GMAIL_USER,
10
+ pass: process.env.GMAIL_PASSCODE,
11
+ },
12
+ });
13
+
14
+ const mailOptions = {
15
+ from: process.env.GMAIL_USER,
16
+ to,
17
+ subject,
18
+ html: message,
19
+ };
20
+
21
+ const res = await transporter.sendMail(mailOptions);
22
+ logger.success(`Email sent to ${to}: ${res.messageId}`);
23
+ } catch (error) {
24
+ logger.error("Failed to send email", error);
25
+ }
26
+ };
27
+
28
+ export default sendEmail;