@digilogiclabs/create-saas-app 2.10.0 → 2.12.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 (416) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +153 -113
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/cli/commands/create.d.ts.map +1 -1
  5. package/dist/cli/commands/create.js +2 -6
  6. package/dist/cli/commands/create.js.map +1 -1
  7. package/dist/cli/index.js +1 -1
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/generators/template-generator.d.ts.map +1 -1
  10. package/dist/generators/template-generator.js +15 -8
  11. package/dist/generators/template-generator.js.map +1 -1
  12. package/dist/templates/shared/admin/web/src/components/admin-nav.tsx +3 -3
  13. package/dist/templates/shared/auth/supabase/web/src/lib/auth-session.ts +36 -16
  14. package/dist/templates/shared/auth/supabase/web/src/middleware.ts +6 -0
  15. package/dist/templates/shared/cookie-consent/web/components/cookie-consent.tsx +5 -5
  16. package/dist/templates/shared/design/web/src/components/ui/button.tsx +56 -0
  17. package/dist/templates/shared/email/web/src/lib/email/client.ts +1 -1
  18. package/dist/templates/shared/error-pages/web/src/app/error.tsx +13 -11
  19. package/dist/templates/shared/error-pages/web/src/app/global-error.tsx +2 -0
  20. package/dist/templates/shared/error-pages/web/src/app/not-found.tsx +6 -6
  21. package/dist/templates/shared/legal/web/src/app/(legal)/privacy/page.tsx +4 -4
  22. package/dist/templates/shared/legal/web/src/app/(legal)/terms/page.tsx +4 -4
  23. package/dist/templates/shared/loading/web/components/skeleton.tsx +4 -4
  24. package/dist/templates/shared/mock/web/.env.local +55 -0
  25. package/dist/templates/shared/mock/web/src/components/mock-auth-provider.tsx +72 -0
  26. package/dist/templates/shared/mock/web/src/components/mock-banner.tsx +29 -0
  27. package/dist/templates/shared/mock/web/src/lib/mock.ts +147 -0
  28. package/dist/templates/shared/payments/web/src/app/api/webhooks/stripe/route.ts +10 -4
  29. package/dist/templates/shared/redis/web/src/lib/redis.ts +1 -1
  30. package/dist/templates/web/ai-platform/template/src/app/api/auth/route.ts +57 -0
  31. package/dist/templates/web/ai-platform/template/src/app/login/page.tsx +112 -0
  32. package/dist/templates/web/ai-platform/template/src/app/models/page.tsx +186 -0
  33. package/dist/templates/web/ai-platform/template/src/app/playground/page.tsx +251 -0
  34. package/dist/templates/web/ai-platform/template/src/app/settings/page.tsx +190 -0
  35. package/dist/templates/web/ai-platform/template/src/app/signup/page.tsx +133 -0
  36. package/dist/templates/web/ai-platform/template/src/lib/auth-session.ts +52 -0
  37. package/dist/templates/web/base/template/eslint.config.mjs +14 -0
  38. package/dist/templates/web/base/template/src/app/auth/callback/route.ts +1 -1
  39. package/dist/templates/web/base/template/src/app/checkout/page.tsx +76 -103
  40. package/dist/templates/web/base/template/src/app/dashboard/page.tsx +145 -329
  41. package/dist/templates/web/base/template/src/app/layout.tsx +40 -38
  42. package/dist/templates/web/base/template/src/app/login/page.tsx +116 -66
  43. package/dist/templates/web/base/template/src/app/page.tsx +97 -193
  44. package/dist/templates/web/base/template/src/app/settings/page.tsx +154 -0
  45. package/dist/templates/web/base/template/src/app/signup/page.tsx +117 -66
  46. package/dist/templates/web/base/template/src/components/providers/app-providers.tsx +8 -3
  47. package/dist/templates/web/base/template/src/components/shared/header.tsx +229 -63
  48. package/dist/templates/web/iot-dashboard/template/src/app/alerts/page.tsx +157 -0
  49. package/dist/templates/web/iot-dashboard/template/src/app/api/auth/route.ts +57 -0
  50. package/dist/templates/web/iot-dashboard/template/src/app/devices/[id]/page.tsx +204 -0
  51. package/dist/templates/web/iot-dashboard/template/src/app/devices/new/page.tsx +139 -0
  52. package/dist/templates/web/iot-dashboard/template/src/app/devices/page.tsx +171 -0
  53. package/dist/templates/web/iot-dashboard/template/src/app/login/page.tsx +112 -0
  54. package/dist/templates/web/iot-dashboard/template/src/app/settings/page.tsx +186 -0
  55. package/dist/templates/web/iot-dashboard/template/src/app/signup/page.tsx +133 -0
  56. package/dist/templates/web/iot-dashboard/template/src/lib/auth-session.ts +52 -0
  57. package/dist/templates/web/marketplace/template/src/app/api/auth/route.ts +57 -0
  58. package/dist/templates/web/marketplace/template/src/app/login/page.tsx +112 -0
  59. package/dist/templates/web/marketplace/template/src/app/orders/page.tsx +160 -0
  60. package/dist/templates/web/marketplace/template/src/app/products/[id]/page.tsx +218 -0
  61. package/dist/templates/web/marketplace/template/src/app/settings/page.tsx +150 -0
  62. package/dist/templates/web/marketplace/template/src/app/signup/page.tsx +133 -0
  63. package/dist/templates/web/marketplace/template/src/lib/auth-session.ts +52 -0
  64. package/dist/templates/web/micro-saas/template/src/app/api/auth/route.ts +57 -0
  65. package/dist/templates/web/micro-saas/template/src/app/login/page.tsx +14 -3
  66. package/dist/templates/web/micro-saas/template/src/app/signup/page.tsx +15 -4
  67. package/dist/templates/web/micro-saas/template/src/lib/auth-session.ts +52 -0
  68. package/dist/templates/web/ui-auth/template/eslint.config.mjs +14 -0
  69. package/dist/templates/web/ui-auth/template/src/app/checkout/page.tsx +3 -3
  70. package/dist/templates/web/ui-auth/template/src/app/dev-setup/page.tsx +81 -91
  71. package/dist/templates/web/ui-auth/template/src/app/layout.tsx +38 -36
  72. package/dist/templates/web/ui-auth/template/src/app/login/page.tsx +22 -45
  73. package/dist/templates/web/ui-auth/template/src/app/page.tsx +106 -306
  74. package/dist/templates/web/ui-auth/template/src/app/setup/page.tsx +387 -402
  75. package/dist/templates/web/ui-auth/template/src/app/signup/page.tsx +24 -47
  76. package/dist/templates/web/ui-auth/template/src/components/providers/app-providers.tsx +8 -3
  77. package/dist/templates/web/ui-auth/template/src/components/shared/header.tsx +229 -94
  78. package/dist/templates/web/ui-auth-ai/template/src/app/layout.tsx +38 -45
  79. package/dist/templates/web/ui-auth-ai/template/src/app/login/page.tsx +86 -0
  80. package/dist/templates/web/ui-auth-ai/template/src/app/page.tsx +107 -193
  81. package/dist/templates/web/ui-auth-ai/template/src/app/signup/page.tsx +105 -0
  82. package/dist/templates/web/ui-auth-ai/template/src/components/ai/audio-generator.tsx +144 -140
  83. package/dist/templates/web/ui-auth-ai/template/src/components/ai/video-generator.tsx +156 -157
  84. package/dist/templates/web/ui-auth-ai/template/src/components/auth/login-form.tsx +7 -3
  85. package/dist/templates/web/ui-auth-ai/template/src/components/providers/app-providers.tsx +25 -0
  86. package/dist/templates/web/ui-auth-ai/template/src/components/shared/footer.tsx +36 -0
  87. package/dist/templates/web/ui-auth-ai/template/src/components/shared/header.tsx +228 -0
  88. package/dist/templates/web/ui-auth-ai/template/src/components/ui/button.tsx +5 -5
  89. package/dist/templates/web/ui-auth-ai/template/src/components/ui/input.tsx +1 -1
  90. package/dist/templates/web/ui-auth-ai/template/src/components/ui/select.tsx +1 -1
  91. package/dist/templates/web/ui-auth-ai/template/src/components/ui/textarea.tsx +1 -1
  92. package/dist/templates/web/ui-auth-ai/template/src/components/ui/theme-toggle.tsx +34 -0
  93. package/dist/templates/web/ui-auth-ai/template/src/lib/supabase.ts +6 -4
  94. package/dist/templates/web/ui-auth-ai/template/src/providers/auth-provider.tsx +7 -5
  95. package/dist/templates/web/ui-auth-payments/template/src/app/billing/page.tsx +63 -192
  96. package/dist/templates/web/ui-auth-payments/template/src/app/checkout/page.tsx +104 -296
  97. package/dist/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +27 -27
  98. package/dist/templates/web/ui-auth-payments/template/src/app/dev-setup/page.tsx +70 -81
  99. package/dist/templates/web/ui-auth-payments/template/src/app/layout.tsx +38 -36
  100. package/dist/templates/web/ui-auth-payments/template/src/app/login/loading.tsx +9 -9
  101. package/dist/templates/web/ui-auth-payments/template/src/app/login/page.tsx +4 -104
  102. package/dist/templates/web/ui-auth-payments/template/src/app/page.tsx +69 -337
  103. package/dist/templates/web/ui-auth-payments/template/src/app/setup/page.tsx +55 -68
  104. package/dist/templates/web/ui-auth-payments/template/src/app/signup/loading.tsx +13 -13
  105. package/dist/templates/web/ui-auth-payments/template/src/app/signup/page.tsx +4 -123
  106. package/dist/templates/web/ui-auth-payments/template/src/components/client/auth-status.tsx +37 -52
  107. package/dist/templates/web/ui-auth-payments/template/src/components/client/login-form.tsx +49 -103
  108. package/dist/templates/web/ui-auth-payments/template/src/components/client/newsletter-signup.tsx +4 -4
  109. package/dist/templates/web/ui-auth-payments/template/src/components/client/signup-form.tsx +60 -140
  110. package/dist/templates/web/ui-auth-payments/template/src/components/providers/app-providers.tsx +25 -28
  111. package/dist/templates/web/ui-auth-payments/template/src/components/shared/header.tsx +229 -230
  112. package/dist/templates/web/ui-auth-payments/template/src/lib/actions/auth.ts +245 -245
  113. package/dist/templates/web/ui-auth-payments/template/src/lib/actions/index.ts +339 -339
  114. package/dist/templates/web/ui-auth-payments-ai/template/src/app/ai/page.tsx +305 -309
  115. package/dist/templates/web/ui-auth-payments-ai/template/src/app/billing/page.tsx +62 -312
  116. package/dist/templates/web/ui-auth-payments-ai/template/src/app/checkout/page.tsx +109 -125
  117. package/dist/templates/web/ui-auth-payments-ai/template/src/app/dashboard/page.tsx +27 -27
  118. package/dist/templates/web/ui-auth-payments-ai/template/src/app/dev-setup/page.tsx +68 -83
  119. package/dist/templates/web/ui-auth-payments-ai/template/src/app/layout.tsx +40 -38
  120. package/dist/templates/web/ui-auth-payments-ai/template/src/app/onboarding/page.tsx +20 -20
  121. package/dist/templates/web/ui-auth-payments-ai/template/src/app/page.tsx +140 -394
  122. package/dist/templates/web/ui-auth-payments-ai/template/src/app/settings/page.tsx +28 -27
  123. package/dist/templates/web/ui-auth-payments-ai/template/src/app/setup/page.tsx +51 -66
  124. package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/auth-status.tsx +37 -52
  125. package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/login-form.tsx +50 -79
  126. package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/signup-form.tsx +58 -111
  127. package/dist/templates/web/ui-auth-payments-ai/template/src/components/providers/app-providers.tsx +8 -3
  128. package/dist/templates/web/ui-auth-payments-ai/template/src/components/shared/header.tsx +229 -252
  129. package/dist/templates/web/ui-auth-payments-ai/template/src/lib/actions/auth.ts +245 -245
  130. package/dist/templates/web/ui-auth-payments-audio/template/src/app/billing/page.tsx +63 -192
  131. package/dist/templates/web/ui-auth-payments-audio/template/src/app/checkout/page.tsx +109 -125
  132. package/dist/templates/web/ui-auth-payments-audio/template/src/app/dashboard/page.tsx +27 -27
  133. package/dist/templates/web/ui-auth-payments-audio/template/src/app/layout.tsx +40 -38
  134. package/dist/templates/web/ui-auth-payments-audio/template/src/app/page.tsx +122 -385
  135. package/dist/templates/web/ui-auth-payments-audio/template/src/app/setup/page.tsx +340 -344
  136. package/dist/templates/web/ui-auth-payments-audio/template/src/components/client/auth-status.tsx +37 -52
  137. package/dist/templates/web/ui-auth-payments-audio/template/src/components/client/login-form.tsx +49 -103
  138. package/dist/templates/web/ui-auth-payments-audio/template/src/components/client/signup-form.tsx +60 -140
  139. package/dist/templates/web/ui-auth-payments-audio/template/src/components/providers/app-providers.tsx +8 -3
  140. package/dist/templates/web/ui-auth-payments-audio/template/src/components/shared/header.tsx +229 -252
  141. package/dist/templates/web/ui-auth-payments-audio/template/src/lib/actions/auth.ts +3 -3
  142. package/dist/templates/web/ui-auth-payments-video/template/src/app/billing/page.tsx +63 -192
  143. package/dist/templates/web/ui-auth-payments-video/template/src/app/checkout/page.tsx +109 -125
  144. package/dist/templates/web/ui-auth-payments-video/template/src/app/layout.tsx +38 -36
  145. package/dist/templates/web/ui-auth-payments-video/template/src/app/login/page.tsx +9 -109
  146. package/dist/templates/web/ui-auth-payments-video/template/src/app/page.tsx +132 -392
  147. package/dist/templates/web/ui-auth-payments-video/template/src/app/setup/page.tsx +346 -350
  148. package/dist/templates/web/ui-auth-payments-video/template/src/app/signup/page.tsx +9 -128
  149. package/dist/templates/web/ui-auth-payments-video/template/src/components/client/login-form.tsx +90 -0
  150. package/dist/templates/web/ui-auth-payments-video/template/src/components/client/signup-form.tsx +105 -0
  151. package/dist/templates/web/ui-auth-payments-video/template/src/components/providers/app-providers.tsx +8 -3
  152. package/dist/templates/web/ui-auth-payments-video/template/src/components/shared/header.tsx +229 -246
  153. package/dist/templates/web/ui-only/template/eslint.config.mjs +14 -0
  154. package/dist/templates/web/ui-only/template/src/app/checkout/page.tsx +2 -2
  155. package/dist/templates/web/ui-only/template/src/app/login/page.tsx +69 -63
  156. package/dist/templates/web/ui-only/template/src/app/page.tsx +69 -91
  157. package/dist/templates/web/ui-only/template/src/app/signup/page.tsx +94 -79
  158. package/dist/templates/web/ui-only/template/src/components/providers/app-providers.tsx +1 -6
  159. package/dist/templates/web/ui-only/template/src/components/shared/header.tsx +90 -53
  160. package/dist/templates/web/ui-package-test/template/package.json +19 -23
  161. package/dist/templates/web/ui-package-test/template/postcss.config.mjs +8 -0
  162. package/dist/templates/web/ui-package-test/template/src/app/globals.css +88 -0
  163. package/dist/templates/web/ui-package-test/template/src/app/layout.tsx +27 -0
  164. package/dist/templates/web/ui-package-test/template/src/app/page.tsx +46 -106
  165. package/package.json +1 -1
  166. package/src/templates/shared/admin/web/src/components/admin-nav.tsx +3 -3
  167. package/src/templates/shared/auth/supabase/web/src/lib/auth-session.ts +36 -16
  168. package/src/templates/shared/auth/supabase/web/src/middleware.ts +6 -0
  169. package/src/templates/shared/cookie-consent/web/components/cookie-consent.tsx +5 -5
  170. package/src/templates/shared/design/web/src/components/ui/button.tsx +56 -0
  171. package/src/templates/shared/email/web/src/lib/email/client.ts +1 -1
  172. package/src/templates/shared/error-pages/web/src/app/error.tsx +13 -11
  173. package/src/templates/shared/error-pages/web/src/app/global-error.tsx +2 -0
  174. package/src/templates/shared/error-pages/web/src/app/not-found.tsx +6 -6
  175. package/src/templates/shared/legal/web/src/app/(legal)/privacy/page.tsx +4 -4
  176. package/src/templates/shared/legal/web/src/app/(legal)/terms/page.tsx +4 -4
  177. package/src/templates/shared/loading/web/components/skeleton.tsx +4 -4
  178. package/src/templates/shared/mock/web/.env.local +55 -0
  179. package/src/templates/shared/mock/web/src/components/mock-auth-provider.tsx +72 -0
  180. package/src/templates/shared/mock/web/src/components/mock-banner.tsx +29 -0
  181. package/src/templates/shared/mock/web/src/lib/mock.ts +147 -0
  182. package/src/templates/shared/payments/web/src/app/api/webhooks/stripe/route.ts +10 -4
  183. package/src/templates/shared/redis/web/src/lib/redis.ts +1 -1
  184. package/src/templates/web/ai-platform/template/src/app/api/auth/route.ts +57 -0
  185. package/src/templates/web/ai-platform/template/src/app/login/page.tsx +112 -0
  186. package/src/templates/web/ai-platform/template/src/app/models/page.tsx +186 -0
  187. package/src/templates/web/ai-platform/template/src/app/playground/page.tsx +251 -0
  188. package/src/templates/web/ai-platform/template/src/app/settings/page.tsx +190 -0
  189. package/src/templates/web/ai-platform/template/src/app/signup/page.tsx +133 -0
  190. package/src/templates/web/ai-platform/template/src/lib/auth-session.ts +52 -0
  191. package/src/templates/web/base/template/eslint.config.mjs +14 -0
  192. package/src/templates/web/base/template/src/app/auth/callback/route.ts +1 -1
  193. package/src/templates/web/base/template/src/app/checkout/page.tsx +76 -103
  194. package/src/templates/web/base/template/src/app/dashboard/page.tsx +145 -329
  195. package/src/templates/web/base/template/src/app/layout.tsx +40 -38
  196. package/src/templates/web/base/template/src/app/login/page.tsx +116 -66
  197. package/src/templates/web/base/template/src/app/page.tsx +97 -193
  198. package/src/templates/web/base/template/src/app/settings/page.tsx +154 -0
  199. package/src/templates/web/base/template/src/app/signup/page.tsx +117 -66
  200. package/src/templates/web/base/template/src/components/providers/app-providers.tsx +8 -3
  201. package/src/templates/web/base/template/src/components/shared/header.tsx +229 -63
  202. package/src/templates/web/iot-dashboard/template/src/app/alerts/page.tsx +157 -0
  203. package/src/templates/web/iot-dashboard/template/src/app/api/auth/route.ts +57 -0
  204. package/src/templates/web/iot-dashboard/template/src/app/devices/[id]/page.tsx +204 -0
  205. package/src/templates/web/iot-dashboard/template/src/app/devices/new/page.tsx +139 -0
  206. package/src/templates/web/iot-dashboard/template/src/app/devices/page.tsx +171 -0
  207. package/src/templates/web/iot-dashboard/template/src/app/login/page.tsx +112 -0
  208. package/src/templates/web/iot-dashboard/template/src/app/settings/page.tsx +186 -0
  209. package/src/templates/web/iot-dashboard/template/src/app/signup/page.tsx +133 -0
  210. package/src/templates/web/iot-dashboard/template/src/lib/auth-session.ts +52 -0
  211. package/src/templates/web/marketplace/template/src/app/api/auth/route.ts +57 -0
  212. package/src/templates/web/marketplace/template/src/app/login/page.tsx +112 -0
  213. package/src/templates/web/marketplace/template/src/app/orders/page.tsx +160 -0
  214. package/src/templates/web/marketplace/template/src/app/products/[id]/page.tsx +218 -0
  215. package/src/templates/web/marketplace/template/src/app/settings/page.tsx +150 -0
  216. package/src/templates/web/marketplace/template/src/app/signup/page.tsx +133 -0
  217. package/src/templates/web/marketplace/template/src/lib/auth-session.ts +52 -0
  218. package/src/templates/web/micro-saas/template/src/app/api/auth/route.ts +57 -0
  219. package/src/templates/web/micro-saas/template/src/app/login/page.tsx +14 -3
  220. package/src/templates/web/micro-saas/template/src/app/signup/page.tsx +15 -4
  221. package/src/templates/web/micro-saas/template/src/lib/auth-session.ts +52 -0
  222. package/src/templates/web/ui-auth/template/eslint.config.mjs +14 -0
  223. package/src/templates/web/ui-auth/template/src/app/checkout/page.tsx +3 -3
  224. package/src/templates/web/ui-auth/template/src/app/dev-setup/page.tsx +81 -91
  225. package/src/templates/web/ui-auth/template/src/app/layout.tsx +38 -36
  226. package/src/templates/web/ui-auth/template/src/app/login/page.tsx +22 -45
  227. package/src/templates/web/ui-auth/template/src/app/page.tsx +106 -306
  228. package/src/templates/web/ui-auth/template/src/app/setup/page.tsx +387 -402
  229. package/src/templates/web/ui-auth/template/src/app/signup/page.tsx +24 -47
  230. package/src/templates/web/ui-auth/template/src/components/providers/app-providers.tsx +8 -3
  231. package/src/templates/web/ui-auth/template/src/components/shared/header.tsx +229 -94
  232. package/src/templates/web/ui-auth-ai/template/src/app/layout.tsx +38 -45
  233. package/src/templates/web/ui-auth-ai/template/src/app/login/page.tsx +86 -0
  234. package/src/templates/web/ui-auth-ai/template/src/app/page.tsx +107 -193
  235. package/src/templates/web/ui-auth-ai/template/src/app/signup/page.tsx +105 -0
  236. package/src/templates/web/ui-auth-ai/template/src/components/ai/audio-generator.tsx +144 -140
  237. package/src/templates/web/ui-auth-ai/template/src/components/ai/video-generator.tsx +156 -157
  238. package/src/templates/web/ui-auth-ai/template/src/components/auth/login-form.tsx +7 -3
  239. package/src/templates/web/ui-auth-ai/template/src/components/providers/app-providers.tsx +25 -0
  240. package/src/templates/web/ui-auth-ai/template/src/components/shared/footer.tsx +36 -0
  241. package/src/templates/web/ui-auth-ai/template/src/components/shared/header.tsx +228 -0
  242. package/src/templates/web/ui-auth-ai/template/src/components/ui/button.tsx +5 -5
  243. package/src/templates/web/ui-auth-ai/template/src/components/ui/input.tsx +1 -1
  244. package/src/templates/web/ui-auth-ai/template/src/components/ui/select.tsx +1 -1
  245. package/src/templates/web/ui-auth-ai/template/src/components/ui/textarea.tsx +1 -1
  246. package/src/templates/web/ui-auth-ai/template/src/components/ui/theme-toggle.tsx +34 -0
  247. package/src/templates/web/ui-auth-ai/template/src/lib/supabase.ts +6 -4
  248. package/src/templates/web/ui-auth-ai/template/src/providers/auth-provider.tsx +7 -5
  249. package/src/templates/web/ui-auth-payments/template/src/app/billing/page.tsx +63 -192
  250. package/src/templates/web/ui-auth-payments/template/src/app/checkout/page.tsx +104 -296
  251. package/src/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +27 -27
  252. package/src/templates/web/ui-auth-payments/template/src/app/dev-setup/page.tsx +70 -81
  253. package/src/templates/web/ui-auth-payments/template/src/app/layout.tsx +38 -36
  254. package/src/templates/web/ui-auth-payments/template/src/app/login/loading.tsx +9 -9
  255. package/src/templates/web/ui-auth-payments/template/src/app/login/page.tsx +4 -104
  256. package/src/templates/web/ui-auth-payments/template/src/app/page.tsx +69 -337
  257. package/src/templates/web/ui-auth-payments/template/src/app/setup/page.tsx +55 -68
  258. package/src/templates/web/ui-auth-payments/template/src/app/signup/loading.tsx +13 -13
  259. package/src/templates/web/ui-auth-payments/template/src/app/signup/page.tsx +4 -123
  260. package/src/templates/web/ui-auth-payments/template/src/components/client/auth-status.tsx +37 -52
  261. package/src/templates/web/ui-auth-payments/template/src/components/client/login-form.tsx +49 -103
  262. package/src/templates/web/ui-auth-payments/template/src/components/client/newsletter-signup.tsx +4 -4
  263. package/src/templates/web/ui-auth-payments/template/src/components/client/signup-form.tsx +60 -140
  264. package/src/templates/web/ui-auth-payments/template/src/components/providers/app-providers.tsx +25 -28
  265. package/src/templates/web/ui-auth-payments/template/src/components/shared/header.tsx +229 -230
  266. package/src/templates/web/ui-auth-payments/template/src/lib/actions/auth.ts +245 -245
  267. package/src/templates/web/ui-auth-payments/template/src/lib/actions/index.ts +339 -339
  268. package/src/templates/web/ui-auth-payments-ai/template/src/app/ai/page.tsx +305 -309
  269. package/src/templates/web/ui-auth-payments-ai/template/src/app/billing/page.tsx +62 -312
  270. package/src/templates/web/ui-auth-payments-ai/template/src/app/checkout/page.tsx +109 -125
  271. package/src/templates/web/ui-auth-payments-ai/template/src/app/dashboard/page.tsx +27 -27
  272. package/src/templates/web/ui-auth-payments-ai/template/src/app/dev-setup/page.tsx +68 -83
  273. package/src/templates/web/ui-auth-payments-ai/template/src/app/layout.tsx +40 -38
  274. package/src/templates/web/ui-auth-payments-ai/template/src/app/onboarding/page.tsx +20 -20
  275. package/src/templates/web/ui-auth-payments-ai/template/src/app/page.tsx +140 -394
  276. package/src/templates/web/ui-auth-payments-ai/template/src/app/settings/page.tsx +28 -27
  277. package/src/templates/web/ui-auth-payments-ai/template/src/app/setup/page.tsx +51 -66
  278. package/src/templates/web/ui-auth-payments-ai/template/src/components/client/auth-status.tsx +37 -52
  279. package/src/templates/web/ui-auth-payments-ai/template/src/components/client/login-form.tsx +50 -79
  280. package/src/templates/web/ui-auth-payments-ai/template/src/components/client/signup-form.tsx +58 -111
  281. package/src/templates/web/ui-auth-payments-ai/template/src/components/providers/app-providers.tsx +8 -3
  282. package/src/templates/web/ui-auth-payments-ai/template/src/components/shared/header.tsx +229 -252
  283. package/src/templates/web/ui-auth-payments-ai/template/src/lib/actions/auth.ts +245 -245
  284. package/src/templates/web/ui-auth-payments-audio/template/src/app/billing/page.tsx +63 -192
  285. package/src/templates/web/ui-auth-payments-audio/template/src/app/checkout/page.tsx +109 -125
  286. package/src/templates/web/ui-auth-payments-audio/template/src/app/dashboard/page.tsx +27 -27
  287. package/src/templates/web/ui-auth-payments-audio/template/src/app/layout.tsx +40 -38
  288. package/src/templates/web/ui-auth-payments-audio/template/src/app/page.tsx +122 -385
  289. package/src/templates/web/ui-auth-payments-audio/template/src/app/setup/page.tsx +340 -344
  290. package/src/templates/web/ui-auth-payments-audio/template/src/components/client/auth-status.tsx +37 -52
  291. package/src/templates/web/ui-auth-payments-audio/template/src/components/client/login-form.tsx +49 -103
  292. package/src/templates/web/ui-auth-payments-audio/template/src/components/client/signup-form.tsx +60 -140
  293. package/src/templates/web/ui-auth-payments-audio/template/src/components/providers/app-providers.tsx +8 -3
  294. package/src/templates/web/ui-auth-payments-audio/template/src/components/shared/header.tsx +229 -252
  295. package/src/templates/web/ui-auth-payments-audio/template/src/lib/actions/auth.ts +3 -3
  296. package/src/templates/web/ui-auth-payments-video/template/src/app/billing/page.tsx +63 -192
  297. package/src/templates/web/ui-auth-payments-video/template/src/app/checkout/page.tsx +109 -125
  298. package/src/templates/web/ui-auth-payments-video/template/src/app/layout.tsx +38 -36
  299. package/src/templates/web/ui-auth-payments-video/template/src/app/login/page.tsx +9 -109
  300. package/src/templates/web/ui-auth-payments-video/template/src/app/page.tsx +132 -392
  301. package/src/templates/web/ui-auth-payments-video/template/src/app/setup/page.tsx +346 -350
  302. package/src/templates/web/ui-auth-payments-video/template/src/app/signup/page.tsx +9 -128
  303. package/src/templates/web/ui-auth-payments-video/template/src/components/client/login-form.tsx +90 -0
  304. package/src/templates/web/ui-auth-payments-video/template/src/components/client/signup-form.tsx +105 -0
  305. package/src/templates/web/ui-auth-payments-video/template/src/components/providers/app-providers.tsx +8 -3
  306. package/src/templates/web/ui-auth-payments-video/template/src/components/shared/header.tsx +229 -246
  307. package/src/templates/web/ui-only/template/eslint.config.mjs +14 -0
  308. package/src/templates/web/ui-only/template/src/app/checkout/page.tsx +2 -2
  309. package/src/templates/web/ui-only/template/src/app/login/page.tsx +69 -63
  310. package/src/templates/web/ui-only/template/src/app/page.tsx +69 -91
  311. package/src/templates/web/ui-only/template/src/app/signup/page.tsx +94 -79
  312. package/src/templates/web/ui-only/template/src/components/providers/app-providers.tsx +1 -6
  313. package/src/templates/web/ui-only/template/src/components/shared/header.tsx +90 -53
  314. package/src/templates/web/ui-package-test/template/package.json +19 -23
  315. package/src/templates/web/ui-package-test/template/postcss.config.mjs +8 -0
  316. package/src/templates/web/ui-package-test/template/src/app/globals.css +88 -0
  317. package/src/templates/web/ui-package-test/template/src/app/layout.tsx +27 -0
  318. package/src/templates/web/ui-package-test/template/src/app/page.tsx +46 -106
  319. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/README.md +0 -655
  320. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/app/(tabs)/ai.tsx +0 -683
  321. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/app/_layout.tsx +0 -124
  322. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/app.json +0 -74
  323. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/babel.config.js +0 -25
  324. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/docs/MOBILE-SETUP.md +0 -787
  325. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/eas.json +0 -25
  326. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/expo-env.d.ts +0 -3
  327. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +0 -346
  328. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/jest-setup.ts +0 -37
  329. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/lib/rag/config.ts +0 -180
  330. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/metro.config.js +0 -11
  331. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/package.json +0 -122
  332. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +0 -599
  333. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/tsconfig.json +0 -32
  334. package/dist/templates/web/base/template/.eslintrc.js +0 -8
  335. package/dist/templates/web/base/template/src/components/__tests__/example.test.tsx +0 -49
  336. package/dist/templates/web/base/template/src/test/setup.ts +0 -74
  337. package/dist/templates/web/base/template/vitest.config.ts +0 -17
  338. package/dist/templates/web/ui-auth/template/.eslintrc.js +0 -8
  339. package/dist/templates/web/ui-auth/template/src/components/__tests__/example.test.tsx +0 -49
  340. package/dist/templates/web/ui-auth/template/src/test/setup.ts +0 -74
  341. package/dist/templates/web/ui-auth/template/vitest.config.ts +0 -17
  342. package/dist/templates/web/ui-auth-payments/template/src/components/__tests__/example.test.tsx +0 -49
  343. package/dist/templates/web/ui-auth-payments/template/src/test/setup.ts +0 -74
  344. package/dist/templates/web/ui-auth-payments/template/vitest.config.ts +0 -17
  345. package/dist/templates/web/ui-auth-payments-ai/template/src/components/__tests__/example.test.tsx +0 -49
  346. package/dist/templates/web/ui-auth-payments-ai/template/src/test/setup.ts +0 -74
  347. package/dist/templates/web/ui-auth-payments-ai/template/vitest.config.ts +0 -17
  348. package/dist/templates/web/ui-auth-payments-ai-rag/template/README.md +0 -434
  349. package/dist/templates/web/ui-auth-payments-ai-rag/template/components/rag/KnowledgeManager.tsx +0 -642
  350. package/dist/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGAnalytics.tsx +0 -466
  351. package/dist/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGChatInterface.tsx +0 -393
  352. package/dist/templates/web/ui-auth-payments-ai-rag/template/docs/GETTING-STARTED.md +0 -457
  353. package/dist/templates/web/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +0 -478
  354. package/dist/templates/web/ui-auth-payments-ai-rag/template/lib/rag/config.ts +0 -250
  355. package/dist/templates/web/ui-auth-payments-ai-rag/template/package.json +0 -73
  356. package/dist/templates/web/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +0 -622
  357. package/dist/templates/web/ui-auth-payments-ai-rag/template/src/app/ai/page.tsx +0 -396
  358. package/dist/templates/web/ui-auth-payments-audio/template/src/components/__tests__/example.test.tsx +0 -49
  359. package/dist/templates/web/ui-auth-payments-audio/template/src/test/setup.ts +0 -74
  360. package/dist/templates/web/ui-auth-payments-audio/template/vitest.config.ts +0 -17
  361. package/dist/templates/web/ui-auth-payments-video/template/src/components/__tests__/example.test.tsx +0 -49
  362. package/dist/templates/web/ui-auth-payments-video/template/src/test/setup.ts +0 -74
  363. package/dist/templates/web/ui-auth-payments-video/template/vitest.config.ts +0 -17
  364. package/dist/templates/web/ui-only/template/.eslintrc.js +0 -8
  365. package/dist/templates/web/ui-only/template/src/components/__tests__/example.test.tsx +0 -49
  366. package/dist/templates/web/ui-only/template/src/test/setup.ts +0 -74
  367. package/dist/templates/web/ui-only/template/vitest.config.ts +0 -17
  368. package/src/templates/mobile/ui-auth-payments-ai-rag/template/README.md +0 -655
  369. package/src/templates/mobile/ui-auth-payments-ai-rag/template/app/(tabs)/ai.tsx +0 -683
  370. package/src/templates/mobile/ui-auth-payments-ai-rag/template/app/_layout.tsx +0 -124
  371. package/src/templates/mobile/ui-auth-payments-ai-rag/template/app.json +0 -74
  372. package/src/templates/mobile/ui-auth-payments-ai-rag/template/babel.config.js +0 -25
  373. package/src/templates/mobile/ui-auth-payments-ai-rag/template/docs/MOBILE-SETUP.md +0 -787
  374. package/src/templates/mobile/ui-auth-payments-ai-rag/template/eas.json +0 -25
  375. package/src/templates/mobile/ui-auth-payments-ai-rag/template/expo-env.d.ts +0 -3
  376. package/src/templates/mobile/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +0 -346
  377. package/src/templates/mobile/ui-auth-payments-ai-rag/template/jest-setup.ts +0 -37
  378. package/src/templates/mobile/ui-auth-payments-ai-rag/template/lib/rag/config.ts +0 -180
  379. package/src/templates/mobile/ui-auth-payments-ai-rag/template/metro.config.js +0 -11
  380. package/src/templates/mobile/ui-auth-payments-ai-rag/template/package.json +0 -122
  381. package/src/templates/mobile/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +0 -599
  382. package/src/templates/mobile/ui-auth-payments-ai-rag/template/tsconfig.json +0 -32
  383. package/src/templates/web/base/template/.eslintrc.js +0 -8
  384. package/src/templates/web/base/template/src/components/__tests__/example.test.tsx +0 -49
  385. package/src/templates/web/base/template/src/test/setup.ts +0 -74
  386. package/src/templates/web/base/template/vitest.config.ts +0 -17
  387. package/src/templates/web/ui-auth/template/.eslintrc.js +0 -8
  388. package/src/templates/web/ui-auth/template/src/components/__tests__/example.test.tsx +0 -49
  389. package/src/templates/web/ui-auth/template/src/test/setup.ts +0 -74
  390. package/src/templates/web/ui-auth/template/vitest.config.ts +0 -17
  391. package/src/templates/web/ui-auth-payments/template/src/components/__tests__/example.test.tsx +0 -49
  392. package/src/templates/web/ui-auth-payments/template/src/test/setup.ts +0 -74
  393. package/src/templates/web/ui-auth-payments/template/vitest.config.ts +0 -17
  394. package/src/templates/web/ui-auth-payments-ai/template/src/components/__tests__/example.test.tsx +0 -49
  395. package/src/templates/web/ui-auth-payments-ai/template/src/test/setup.ts +0 -74
  396. package/src/templates/web/ui-auth-payments-ai/template/vitest.config.ts +0 -17
  397. package/src/templates/web/ui-auth-payments-ai-rag/template/README.md +0 -434
  398. package/src/templates/web/ui-auth-payments-ai-rag/template/components/rag/KnowledgeManager.tsx +0 -642
  399. package/src/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGAnalytics.tsx +0 -466
  400. package/src/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGChatInterface.tsx +0 -393
  401. package/src/templates/web/ui-auth-payments-ai-rag/template/docs/GETTING-STARTED.md +0 -457
  402. package/src/templates/web/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +0 -478
  403. package/src/templates/web/ui-auth-payments-ai-rag/template/lib/rag/config.ts +0 -250
  404. package/src/templates/web/ui-auth-payments-ai-rag/template/package.json +0 -73
  405. package/src/templates/web/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +0 -622
  406. package/src/templates/web/ui-auth-payments-ai-rag/template/src/app/ai/page.tsx +0 -396
  407. package/src/templates/web/ui-auth-payments-audio/template/src/components/__tests__/example.test.tsx +0 -49
  408. package/src/templates/web/ui-auth-payments-audio/template/src/test/setup.ts +0 -74
  409. package/src/templates/web/ui-auth-payments-audio/template/vitest.config.ts +0 -17
  410. package/src/templates/web/ui-auth-payments-video/template/src/components/__tests__/example.test.tsx +0 -49
  411. package/src/templates/web/ui-auth-payments-video/template/src/test/setup.ts +0 -74
  412. package/src/templates/web/ui-auth-payments-video/template/vitest.config.ts +0 -17
  413. package/src/templates/web/ui-only/template/.eslintrc.js +0 -8
  414. package/src/templates/web/ui-only/template/src/components/__tests__/example.test.tsx +0 -49
  415. package/src/templates/web/ui-only/template/src/test/setup.ts +0 -74
  416. package/src/templates/web/ui-only/template/vitest.config.ts +0 -17
@@ -1,340 +1,340 @@
1
- 'use server'
2
-
3
- import { after } from 'next/server'
4
- import { revalidateTag, revalidatePath } from 'next/cache'
5
- import { getCurrentUser } from '@/lib/auth-server'
6
- import { z } from 'zod'
7
-
8
- // Common response type
9
- export type ActionResponse<T = any> = {
10
- success: boolean
11
- data?: T
12
- error?: string
13
- fieldErrors?: Record<string, string[]>
14
- }
15
-
16
- /**
17
- * Example server action for contact form
18
- */
19
- export async function submitContactForm(prevState: any, formData: FormData): Promise<ActionResponse> {
20
- try {
21
- const contactSchema = z.object({
22
- name: z.string().min(2, 'Name must be at least 2 characters'),
23
- email: z.string().email('Invalid email address'),
24
- subject: z.string().min(5, 'Subject must be at least 5 characters'),
25
- message: z.string().min(10, 'Message must be at least 10 characters'),
26
- })
27
-
28
- const rawData = {
29
- name: formData.get('name') as string,
30
- email: formData.get('email') as string,
31
- subject: formData.get('subject') as string,
32
- message: formData.get('message') as string,
33
- }
34
-
35
- const validationResult = contactSchema.safeParse(rawData)
36
-
37
- if (!validationResult.success) {
38
- return {
39
- success: false,
40
- error: 'Please check your input',
41
- fieldErrors: validationResult.error.formErrors.fieldErrors,
42
- }
43
- }
44
-
45
- const { name, email, subject, message } = validationResult.data
46
-
47
- // Process contact form submission
48
- // This could involve:
49
- // - Sending email to admin
50
- // - Saving to database
51
- // - Sending auto-reply to user
52
-
53
- // Use after() for non-blocking operations (Next.js 15.3 feature)
54
- after(async () => {
55
- // Send notification email to admin (non-blocking)
56
- console.log('Sending notification email for contact form submission')
57
-
58
- // Log analytics event (non-blocking)
59
- console.log('Logging contact form submission analytics')
60
-
61
- // Update dashboard statistics (non-blocking)
62
- console.log('Updating contact form statistics')
63
- })
64
-
65
- return {
66
- success: true,
67
- data: { message: 'Thank you for your message. We\'ll get back to you soon!' }
68
- }
69
- } catch (error) {
70
- console.error('Contact form error:', error)
71
- return {
72
- success: false,
73
- error: 'An unexpected error occurred. Please try again.',
74
- }
75
- }
76
- }
77
-
78
- /**
79
- * Example server action for newsletter signup
80
- */
81
- export async function subscribeToNewsletter(prevState: any, formData: FormData): Promise<ActionResponse> {
82
- try {
83
- const email = formData.get('email') as string
84
-
85
- const emailSchema = z.string().email('Invalid email address')
86
- const validationResult = emailSchema.safeParse(email)
87
-
88
- if (!validationResult.success) {
89
- return {
90
- success: false,
91
- error: 'Please enter a valid email address',
92
- }
93
- }
94
-
95
- // Add to newsletter list
96
- // This could involve:
97
- // - Adding to email service provider (Mailchimp, ConvertKit, etc.)
98
- // - Saving to database
99
- // - Sending welcome email
100
-
101
- after(async () => {
102
- // Send welcome email (non-blocking)
103
- console.log(`Sending welcome email to ${email}`)
104
-
105
- // Add to email marketing platform (non-blocking)
106
- console.log(`Adding ${email} to newsletter list`)
107
-
108
- // Track conversion (non-blocking)
109
- console.log('Tracking newsletter signup conversion')
110
- })
111
-
112
- return {
113
- success: true,
114
- data: { message: 'Successfully subscribed to newsletter!' }
115
- }
116
- } catch (error) {
117
- console.error('Newsletter subscription error:', error)
118
- return {
119
- success: false,
120
- error: 'An unexpected error occurred. Please try again.',
121
- }
122
- }
123
- }
124
-
125
- /**
126
- * Example authenticated server action
127
- */
128
- export async function createPost(prevState: any, formData: FormData): Promise<ActionResponse> {
129
- try {
130
- // Require authentication
131
- const user = await getCurrentUser()
132
- if (!user) {
133
- return {
134
- success: false,
135
- error: 'Authentication required',
136
- }
137
- }
138
-
139
- const postSchema = z.object({
140
- title: z.string().min(3, 'Title must be at least 3 characters'),
141
- content: z.string().min(10, 'Content must be at least 10 characters'),
142
- published: z.boolean().default(false),
143
- })
144
-
145
- const rawData = {
146
- title: formData.get('title') as string,
147
- content: formData.get('content') as string,
148
- published: formData.get('published') === 'true',
149
- }
150
-
151
- const validationResult = postSchema.safeParse(rawData)
152
-
153
- if (!validationResult.success) {
154
- return {
155
- success: false,
156
- error: 'Please check your input',
157
- fieldErrors: validationResult.error.formErrors.fieldErrors,
158
- }
159
- }
160
-
161
- const { title, content, published } = validationResult.data
162
-
163
- // Create post in database
164
- const post = {
165
- id: Math.random().toString(36).substr(2, 9),
166
- title,
167
- content,
168
- published,
169
- authorId: user.id,
170
- createdAt: new Date().toISOString(),
171
- }
172
-
173
- // Revalidate relevant paths and tags
174
- revalidateTag('posts')
175
- revalidatePath('/posts')
176
- if (published) {
177
- revalidatePath('/')
178
- }
179
-
180
- // Non-blocking operations
181
- after(async () => {
182
- // Send notifications to subscribers (non-blocking)
183
- if (published) {
184
- console.log('Notifying subscribers of new post')
185
- }
186
-
187
- // Update search index (non-blocking)
188
- console.log('Updating search index')
189
-
190
- // Track content creation analytics (non-blocking)
191
- console.log('Tracking post creation analytics')
192
- })
193
-
194
- return {
195
- success: true,
196
- data: { post, message: published ? 'Post published successfully!' : 'Post saved as draft!' }
197
- }
198
- } catch (error) {
199
- console.error('Create post error:', error)
200
- return {
201
- success: false,
202
- error: 'An unexpected error occurred. Please try again.',
203
- }
204
- }
205
- }
206
-
207
- /**
208
- * Example action for updating user preferences
209
- */
210
- export async function updatePreferences(prevState: any, formData: FormData): Promise<ActionResponse> {
211
- try {
212
- const user = await getCurrentUser()
213
- if (!user) {
214
- return {
215
- success: false,
216
- error: 'Authentication required',
217
- }
218
- }
219
-
220
- const preferencesSchema = z.object({
221
- emailNotifications: z.boolean().default(true),
222
- pushNotifications: z.boolean().default(false),
223
- marketingEmails: z.boolean().default(false),
224
- theme: z.enum(['light', 'dark', 'system']).default('system'),
225
- })
226
-
227
- const rawData = {
228
- emailNotifications: formData.get('emailNotifications') === 'true',
229
- pushNotifications: formData.get('pushNotifications') === 'true',
230
- marketingEmails: formData.get('marketingEmails') === 'true',
231
- theme: formData.get('theme') as 'light' | 'dark' | 'system' | null || 'system',
232
- }
233
-
234
- const validationResult = preferencesSchema.safeParse(rawData)
235
-
236
- if (!validationResult.success) {
237
- return {
238
- success: false,
239
- error: 'Please check your input',
240
- fieldErrors: validationResult.error.formErrors.fieldErrors,
241
- }
242
- }
243
-
244
- const preferences = validationResult.data
245
-
246
- // Update user preferences in database
247
- // This would typically involve a database update
248
-
249
- after(async () => {
250
- // Update notification service settings (non-blocking)
251
- console.log('Updating notification service settings')
252
-
253
- // Log preference changes for analytics (non-blocking)
254
- console.log('Logging preference changes')
255
- })
256
-
257
- return {
258
- success: true,
259
- data: { preferences, message: 'Preferences updated successfully!' }
260
- }
261
- } catch (error) {
262
- console.error('Update preferences error:', error)
263
- return {
264
- success: false,
265
- error: 'An unexpected error occurred. Please try again.',
266
- }
267
- }
268
- }
269
-
270
- /**
271
- * Example action with file upload
272
- */
273
- export async function uploadAvatar(prevState: any, formData: FormData): Promise<ActionResponse> {
274
- try {
275
- const user = await getCurrentUser()
276
- if (!user) {
277
- return {
278
- success: false,
279
- error: 'Authentication required',
280
- }
281
- }
282
-
283
- const file = formData.get('avatar') as File
284
-
285
- if (!file || file.size === 0) {
286
- return {
287
- success: false,
288
- error: 'Please select a file to upload',
289
- }
290
- }
291
-
292
- // Validate file type and size
293
- const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']
294
- const maxSize = 5 * 1024 * 1024 // 5MB
295
-
296
- if (!allowedTypes.includes(file.type)) {
297
- return {
298
- success: false,
299
- error: 'Please upload a valid image file (JPEG, PNG, GIF, or WebP)',
300
- }
301
- }
302
-
303
- if (file.size > maxSize) {
304
- return {
305
- success: false,
306
- error: 'File size must be less than 5MB',
307
- }
308
- }
309
-
310
- // Process file upload
311
- // This would typically involve:
312
- // - Uploading to cloud storage (AWS S3, Cloudinary, etc.)
313
- // - Resizing/optimizing the image
314
- // - Updating user record in database
315
-
316
- const avatarUrl = `https://example.com/avatars/${user.id}-${Date.now()}.${file.type.split('/')[1]}`
317
-
318
- after(async () => {
319
- // Generate different image sizes (non-blocking)
320
- console.log('Generating avatar thumbnails')
321
-
322
- // Update CDN cache (non-blocking)
323
- console.log('Updating CDN cache')
324
-
325
- // Log upload event (non-blocking)
326
- console.log('Logging avatar upload event')
327
- })
328
-
329
- return {
330
- success: true,
331
- data: { avatarUrl, message: 'Avatar uploaded successfully!' }
332
- }
333
- } catch (error) {
334
- console.error('Upload avatar error:', error)
335
- return {
336
- success: false,
337
- error: 'An unexpected error occurred. Please try again.',
338
- }
339
- }
1
+ 'use server'
2
+
3
+ import { after } from 'next/server'
4
+ import { revalidateTag, revalidatePath } from 'next/cache'
5
+ import { getCurrentUser } from '@/lib/auth-server'
6
+ import { z } from 'zod'
7
+
8
+ // Common response type
9
+ export type ActionResponse<T = any> = {
10
+ success: boolean
11
+ data?: T
12
+ error?: string
13
+ fieldErrors?: Record<string, string[]>
14
+ }
15
+
16
+ /**
17
+ * Example server action for contact form
18
+ */
19
+ export async function submitContactForm(prevState: any, formData: FormData): Promise<ActionResponse> {
20
+ try {
21
+ const contactSchema = z.object({
22
+ name: z.string().min(2, 'Name must be at least 2 characters'),
23
+ email: z.string().email('Invalid email address'),
24
+ subject: z.string().min(5, 'Subject must be at least 5 characters'),
25
+ message: z.string().min(10, 'Message must be at least 10 characters'),
26
+ })
27
+
28
+ const rawData = {
29
+ name: formData.get('name') as string,
30
+ email: formData.get('email') as string,
31
+ subject: formData.get('subject') as string,
32
+ message: formData.get('message') as string,
33
+ }
34
+
35
+ const validationResult = contactSchema.safeParse(rawData)
36
+
37
+ if (!validationResult.success) {
38
+ return {
39
+ success: false,
40
+ error: 'Please check your input',
41
+ fieldErrors: validationResult.error.flatten().fieldErrors,
42
+ }
43
+ }
44
+
45
+ const { name, email, subject, message } = validationResult.data
46
+
47
+ // Process contact form submission
48
+ // This could involve:
49
+ // - Sending email to admin
50
+ // - Saving to database
51
+ // - Sending auto-reply to user
52
+
53
+ // Use after() for non-blocking operations (Next.js 15.3 feature)
54
+ after(async () => {
55
+ // Send notification email to admin (non-blocking)
56
+ console.log('Sending notification email for contact form submission')
57
+
58
+ // Log analytics event (non-blocking)
59
+ console.log('Logging contact form submission analytics')
60
+
61
+ // Update dashboard statistics (non-blocking)
62
+ console.log('Updating contact form statistics')
63
+ })
64
+
65
+ return {
66
+ success: true,
67
+ data: { message: 'Thank you for your message. We\'ll get back to you soon!' }
68
+ }
69
+ } catch (error) {
70
+ console.error('Contact form error:', error)
71
+ return {
72
+ success: false,
73
+ error: 'An unexpected error occurred. Please try again.',
74
+ }
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Example server action for newsletter signup
80
+ */
81
+ export async function subscribeToNewsletter(prevState: any, formData: FormData): Promise<ActionResponse> {
82
+ try {
83
+ const email = formData.get('email') as string
84
+
85
+ const emailSchema = z.string().email('Invalid email address')
86
+ const validationResult = emailSchema.safeParse(email)
87
+
88
+ if (!validationResult.success) {
89
+ return {
90
+ success: false,
91
+ error: 'Please enter a valid email address',
92
+ }
93
+ }
94
+
95
+ // Add to newsletter list
96
+ // This could involve:
97
+ // - Adding to email service provider (Mailchimp, ConvertKit, etc.)
98
+ // - Saving to database
99
+ // - Sending welcome email
100
+
101
+ after(async () => {
102
+ // Send welcome email (non-blocking)
103
+ console.log(`Sending welcome email to ${email}`)
104
+
105
+ // Add to email marketing platform (non-blocking)
106
+ console.log(`Adding ${email} to newsletter list`)
107
+
108
+ // Track conversion (non-blocking)
109
+ console.log('Tracking newsletter signup conversion')
110
+ })
111
+
112
+ return {
113
+ success: true,
114
+ data: { message: 'Successfully subscribed to newsletter!' }
115
+ }
116
+ } catch (error) {
117
+ console.error('Newsletter subscription error:', error)
118
+ return {
119
+ success: false,
120
+ error: 'An unexpected error occurred. Please try again.',
121
+ }
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Example authenticated server action
127
+ */
128
+ export async function createPost(prevState: any, formData: FormData): Promise<ActionResponse> {
129
+ try {
130
+ // Require authentication
131
+ const user = await getCurrentUser()
132
+ if (!user) {
133
+ return {
134
+ success: false,
135
+ error: 'Authentication required',
136
+ }
137
+ }
138
+
139
+ const postSchema = z.object({
140
+ title: z.string().min(3, 'Title must be at least 3 characters'),
141
+ content: z.string().min(10, 'Content must be at least 10 characters'),
142
+ published: z.boolean().default(false),
143
+ })
144
+
145
+ const rawData = {
146
+ title: formData.get('title') as string,
147
+ content: formData.get('content') as string,
148
+ published: formData.get('published') === 'true',
149
+ }
150
+
151
+ const validationResult = postSchema.safeParse(rawData)
152
+
153
+ if (!validationResult.success) {
154
+ return {
155
+ success: false,
156
+ error: 'Please check your input',
157
+ fieldErrors: validationResult.error.flatten().fieldErrors,
158
+ }
159
+ }
160
+
161
+ const { title, content, published } = validationResult.data
162
+
163
+ // Create post in database
164
+ const post = {
165
+ id: Math.random().toString(36).substr(2, 9),
166
+ title,
167
+ content,
168
+ published,
169
+ authorId: user.id,
170
+ createdAt: new Date().toISOString(),
171
+ }
172
+
173
+ // Revalidate relevant paths and tags
174
+ revalidateTag('posts')
175
+ revalidatePath('/posts')
176
+ if (published) {
177
+ revalidatePath('/')
178
+ }
179
+
180
+ // Non-blocking operations
181
+ after(async () => {
182
+ // Send notifications to subscribers (non-blocking)
183
+ if (published) {
184
+ console.log('Notifying subscribers of new post')
185
+ }
186
+
187
+ // Update search index (non-blocking)
188
+ console.log('Updating search index')
189
+
190
+ // Track content creation analytics (non-blocking)
191
+ console.log('Tracking post creation analytics')
192
+ })
193
+
194
+ return {
195
+ success: true,
196
+ data: { post, message: published ? 'Post published successfully!' : 'Post saved as draft!' }
197
+ }
198
+ } catch (error) {
199
+ console.error('Create post error:', error)
200
+ return {
201
+ success: false,
202
+ error: 'An unexpected error occurred. Please try again.',
203
+ }
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Example action for updating user preferences
209
+ */
210
+ export async function updatePreferences(prevState: any, formData: FormData): Promise<ActionResponse> {
211
+ try {
212
+ const user = await getCurrentUser()
213
+ if (!user) {
214
+ return {
215
+ success: false,
216
+ error: 'Authentication required',
217
+ }
218
+ }
219
+
220
+ const preferencesSchema = z.object({
221
+ emailNotifications: z.boolean().default(true),
222
+ pushNotifications: z.boolean().default(false),
223
+ marketingEmails: z.boolean().default(false),
224
+ theme: z.enum(['light', 'dark', 'system']).default('system'),
225
+ })
226
+
227
+ const rawData = {
228
+ emailNotifications: formData.get('emailNotifications') === 'true',
229
+ pushNotifications: formData.get('pushNotifications') === 'true',
230
+ marketingEmails: formData.get('marketingEmails') === 'true',
231
+ theme: formData.get('theme') as 'light' | 'dark' | 'system' | null || 'system',
232
+ }
233
+
234
+ const validationResult = preferencesSchema.safeParse(rawData)
235
+
236
+ if (!validationResult.success) {
237
+ return {
238
+ success: false,
239
+ error: 'Please check your input',
240
+ fieldErrors: validationResult.error.flatten().fieldErrors,
241
+ }
242
+ }
243
+
244
+ const preferences = validationResult.data
245
+
246
+ // Update user preferences in database
247
+ // This would typically involve a database update
248
+
249
+ after(async () => {
250
+ // Update notification service settings (non-blocking)
251
+ console.log('Updating notification service settings')
252
+
253
+ // Log preference changes for analytics (non-blocking)
254
+ console.log('Logging preference changes')
255
+ })
256
+
257
+ return {
258
+ success: true,
259
+ data: { preferences, message: 'Preferences updated successfully!' }
260
+ }
261
+ } catch (error) {
262
+ console.error('Update preferences error:', error)
263
+ return {
264
+ success: false,
265
+ error: 'An unexpected error occurred. Please try again.',
266
+ }
267
+ }
268
+ }
269
+
270
+ /**
271
+ * Example action with file upload
272
+ */
273
+ export async function uploadAvatar(prevState: any, formData: FormData): Promise<ActionResponse> {
274
+ try {
275
+ const user = await getCurrentUser()
276
+ if (!user) {
277
+ return {
278
+ success: false,
279
+ error: 'Authentication required',
280
+ }
281
+ }
282
+
283
+ const file = formData.get('avatar') as File
284
+
285
+ if (!file || file.size === 0) {
286
+ return {
287
+ success: false,
288
+ error: 'Please select a file to upload',
289
+ }
290
+ }
291
+
292
+ // Validate file type and size
293
+ const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']
294
+ const maxSize = 5 * 1024 * 1024 // 5MB
295
+
296
+ if (!allowedTypes.includes(file.type)) {
297
+ return {
298
+ success: false,
299
+ error: 'Please upload a valid image file (JPEG, PNG, GIF, or WebP)',
300
+ }
301
+ }
302
+
303
+ if (file.size > maxSize) {
304
+ return {
305
+ success: false,
306
+ error: 'File size must be less than 5MB',
307
+ }
308
+ }
309
+
310
+ // Process file upload
311
+ // This would typically involve:
312
+ // - Uploading to cloud storage (AWS S3, Cloudinary, etc.)
313
+ // - Resizing/optimizing the image
314
+ // - Updating user record in database
315
+
316
+ const avatarUrl = `https://example.com/avatars/${user.id}-${Date.now()}.${file.type.split('/')[1]}`
317
+
318
+ after(async () => {
319
+ // Generate different image sizes (non-blocking)
320
+ console.log('Generating avatar thumbnails')
321
+
322
+ // Update CDN cache (non-blocking)
323
+ console.log('Updating CDN cache')
324
+
325
+ // Log upload event (non-blocking)
326
+ console.log('Logging avatar upload event')
327
+ })
328
+
329
+ return {
330
+ success: true,
331
+ data: { avatarUrl, message: 'Avatar uploaded successfully!' }
332
+ }
333
+ } catch (error) {
334
+ console.error('Upload avatar error:', error)
335
+ return {
336
+ success: false,
337
+ error: 'An unexpected error occurred. Please try again.',
338
+ }
339
+ }
340
340
  }