@digilogiclabs/create-saas-app 2.11.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 (358) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/cli/index.js +1 -1
  4. package/dist/cli/index.js.map +1 -1
  5. package/dist/generators/template-generator.d.ts.map +1 -1
  6. package/dist/generators/template-generator.js +15 -8
  7. package/dist/generators/template-generator.js.map +1 -1
  8. package/dist/templates/shared/admin/web/src/components/admin-nav.tsx +3 -3
  9. package/dist/templates/shared/auth/supabase/web/src/lib/auth-session.ts +36 -16
  10. package/dist/templates/shared/auth/supabase/web/src/middleware.ts +6 -0
  11. package/dist/templates/shared/cookie-consent/web/components/cookie-consent.tsx +5 -5
  12. package/dist/templates/shared/design/web/src/components/ui/button.tsx +56 -0
  13. package/dist/templates/shared/email/web/src/lib/email/client.ts +1 -1
  14. package/dist/templates/shared/error-pages/web/src/app/error.tsx +13 -11
  15. package/dist/templates/shared/error-pages/web/src/app/global-error.tsx +2 -0
  16. package/dist/templates/shared/error-pages/web/src/app/not-found.tsx +6 -6
  17. package/dist/templates/shared/legal/web/src/app/(legal)/privacy/page.tsx +4 -4
  18. package/dist/templates/shared/legal/web/src/app/(legal)/terms/page.tsx +4 -4
  19. package/dist/templates/shared/loading/web/components/skeleton.tsx +4 -4
  20. package/dist/templates/shared/mock/web/.env.local +55 -0
  21. package/dist/templates/shared/mock/web/src/components/mock-auth-provider.tsx +72 -0
  22. package/dist/templates/shared/mock/web/src/components/mock-banner.tsx +29 -0
  23. package/dist/templates/shared/mock/web/src/lib/mock.ts +147 -0
  24. package/dist/templates/shared/payments/web/src/app/api/webhooks/stripe/route.ts +10 -4
  25. package/dist/templates/shared/redis/web/src/lib/redis.ts +1 -1
  26. package/dist/templates/web/base/template/eslint.config.mjs +14 -0
  27. package/dist/templates/web/base/template/src/app/auth/callback/route.ts +1 -1
  28. package/dist/templates/web/base/template/src/app/checkout/page.tsx +76 -103
  29. package/dist/templates/web/base/template/src/app/dashboard/page.tsx +145 -329
  30. package/dist/templates/web/base/template/src/app/layout.tsx +40 -38
  31. package/dist/templates/web/base/template/src/app/login/page.tsx +116 -66
  32. package/dist/templates/web/base/template/src/app/page.tsx +97 -193
  33. package/dist/templates/web/base/template/src/app/settings/page.tsx +154 -0
  34. package/dist/templates/web/base/template/src/app/signup/page.tsx +117 -66
  35. package/dist/templates/web/base/template/src/components/providers/app-providers.tsx +8 -3
  36. package/dist/templates/web/base/template/src/components/shared/header.tsx +229 -63
  37. package/dist/templates/web/ui-auth/template/eslint.config.mjs +14 -0
  38. package/dist/templates/web/ui-auth/template/src/app/checkout/page.tsx +3 -3
  39. package/dist/templates/web/ui-auth/template/src/app/dev-setup/page.tsx +81 -91
  40. package/dist/templates/web/ui-auth/template/src/app/layout.tsx +38 -36
  41. package/dist/templates/web/ui-auth/template/src/app/login/page.tsx +22 -45
  42. package/dist/templates/web/ui-auth/template/src/app/page.tsx +106 -306
  43. package/dist/templates/web/ui-auth/template/src/app/setup/page.tsx +387 -402
  44. package/dist/templates/web/ui-auth/template/src/app/signup/page.tsx +24 -47
  45. package/dist/templates/web/ui-auth/template/src/components/providers/app-providers.tsx +8 -3
  46. package/dist/templates/web/ui-auth/template/src/components/shared/header.tsx +229 -94
  47. package/dist/templates/web/ui-auth-ai/template/src/app/layout.tsx +38 -45
  48. package/dist/templates/web/ui-auth-ai/template/src/app/login/page.tsx +86 -0
  49. package/dist/templates/web/ui-auth-ai/template/src/app/page.tsx +107 -193
  50. package/dist/templates/web/ui-auth-ai/template/src/app/signup/page.tsx +105 -0
  51. package/dist/templates/web/ui-auth-ai/template/src/components/ai/audio-generator.tsx +144 -140
  52. package/dist/templates/web/ui-auth-ai/template/src/components/ai/video-generator.tsx +156 -157
  53. package/dist/templates/web/ui-auth-ai/template/src/components/auth/login-form.tsx +7 -3
  54. package/dist/templates/web/ui-auth-ai/template/src/components/providers/app-providers.tsx +25 -0
  55. package/dist/templates/web/ui-auth-ai/template/src/components/shared/footer.tsx +36 -0
  56. package/dist/templates/web/ui-auth-ai/template/src/components/shared/header.tsx +228 -0
  57. package/dist/templates/web/ui-auth-ai/template/src/components/ui/button.tsx +5 -5
  58. package/dist/templates/web/ui-auth-ai/template/src/components/ui/input.tsx +1 -1
  59. package/dist/templates/web/ui-auth-ai/template/src/components/ui/select.tsx +1 -1
  60. package/dist/templates/web/ui-auth-ai/template/src/components/ui/textarea.tsx +1 -1
  61. package/dist/templates/web/ui-auth-ai/template/src/components/ui/theme-toggle.tsx +34 -0
  62. package/dist/templates/web/ui-auth-ai/template/src/lib/supabase.ts +6 -4
  63. package/dist/templates/web/ui-auth-ai/template/src/providers/auth-provider.tsx +7 -5
  64. package/dist/templates/web/ui-auth-payments/template/src/app/billing/page.tsx +63 -192
  65. package/dist/templates/web/ui-auth-payments/template/src/app/checkout/page.tsx +104 -296
  66. package/dist/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +27 -27
  67. package/dist/templates/web/ui-auth-payments/template/src/app/dev-setup/page.tsx +70 -81
  68. package/dist/templates/web/ui-auth-payments/template/src/app/layout.tsx +38 -36
  69. package/dist/templates/web/ui-auth-payments/template/src/app/login/loading.tsx +9 -9
  70. package/dist/templates/web/ui-auth-payments/template/src/app/login/page.tsx +4 -104
  71. package/dist/templates/web/ui-auth-payments/template/src/app/page.tsx +69 -337
  72. package/dist/templates/web/ui-auth-payments/template/src/app/setup/page.tsx +55 -68
  73. package/dist/templates/web/ui-auth-payments/template/src/app/signup/loading.tsx +13 -13
  74. package/dist/templates/web/ui-auth-payments/template/src/app/signup/page.tsx +4 -123
  75. package/dist/templates/web/ui-auth-payments/template/src/components/client/auth-status.tsx +37 -52
  76. package/dist/templates/web/ui-auth-payments/template/src/components/client/login-form.tsx +49 -103
  77. package/dist/templates/web/ui-auth-payments/template/src/components/client/newsletter-signup.tsx +4 -4
  78. package/dist/templates/web/ui-auth-payments/template/src/components/client/signup-form.tsx +60 -140
  79. package/dist/templates/web/ui-auth-payments/template/src/components/providers/app-providers.tsx +25 -28
  80. package/dist/templates/web/ui-auth-payments/template/src/components/shared/header.tsx +229 -230
  81. package/dist/templates/web/ui-auth-payments/template/src/lib/actions/auth.ts +245 -245
  82. package/dist/templates/web/ui-auth-payments/template/src/lib/actions/index.ts +339 -339
  83. package/dist/templates/web/ui-auth-payments-ai/template/src/app/ai/page.tsx +305 -309
  84. package/dist/templates/web/ui-auth-payments-ai/template/src/app/billing/page.tsx +62 -312
  85. package/dist/templates/web/ui-auth-payments-ai/template/src/app/checkout/page.tsx +109 -125
  86. package/dist/templates/web/ui-auth-payments-ai/template/src/app/dashboard/page.tsx +27 -27
  87. package/dist/templates/web/ui-auth-payments-ai/template/src/app/dev-setup/page.tsx +68 -83
  88. package/dist/templates/web/ui-auth-payments-ai/template/src/app/layout.tsx +40 -38
  89. package/dist/templates/web/ui-auth-payments-ai/template/src/app/onboarding/page.tsx +20 -20
  90. package/dist/templates/web/ui-auth-payments-ai/template/src/app/page.tsx +140 -394
  91. package/dist/templates/web/ui-auth-payments-ai/template/src/app/settings/page.tsx +28 -27
  92. package/dist/templates/web/ui-auth-payments-ai/template/src/app/setup/page.tsx +51 -66
  93. package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/auth-status.tsx +37 -52
  94. package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/login-form.tsx +50 -79
  95. package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/signup-form.tsx +58 -111
  96. package/dist/templates/web/ui-auth-payments-ai/template/src/components/providers/app-providers.tsx +8 -3
  97. package/dist/templates/web/ui-auth-payments-ai/template/src/components/shared/header.tsx +229 -252
  98. package/dist/templates/web/ui-auth-payments-ai/template/src/lib/actions/auth.ts +245 -245
  99. package/dist/templates/web/ui-auth-payments-audio/template/src/app/billing/page.tsx +63 -192
  100. package/dist/templates/web/ui-auth-payments-audio/template/src/app/checkout/page.tsx +109 -125
  101. package/dist/templates/web/ui-auth-payments-audio/template/src/app/dashboard/page.tsx +27 -27
  102. package/dist/templates/web/ui-auth-payments-audio/template/src/app/layout.tsx +40 -38
  103. package/dist/templates/web/ui-auth-payments-audio/template/src/app/page.tsx +122 -385
  104. package/dist/templates/web/ui-auth-payments-audio/template/src/app/setup/page.tsx +340 -344
  105. package/dist/templates/web/ui-auth-payments-audio/template/src/components/client/auth-status.tsx +37 -52
  106. package/dist/templates/web/ui-auth-payments-audio/template/src/components/client/login-form.tsx +49 -103
  107. package/dist/templates/web/ui-auth-payments-audio/template/src/components/client/signup-form.tsx +60 -140
  108. package/dist/templates/web/ui-auth-payments-audio/template/src/components/providers/app-providers.tsx +8 -3
  109. package/dist/templates/web/ui-auth-payments-audio/template/src/components/shared/header.tsx +229 -252
  110. package/dist/templates/web/ui-auth-payments-audio/template/src/lib/actions/auth.ts +3 -3
  111. package/dist/templates/web/ui-auth-payments-video/template/src/app/billing/page.tsx +63 -192
  112. package/dist/templates/web/ui-auth-payments-video/template/src/app/checkout/page.tsx +109 -125
  113. package/dist/templates/web/ui-auth-payments-video/template/src/app/layout.tsx +38 -36
  114. package/dist/templates/web/ui-auth-payments-video/template/src/app/login/page.tsx +9 -109
  115. package/dist/templates/web/ui-auth-payments-video/template/src/app/page.tsx +132 -392
  116. package/dist/templates/web/ui-auth-payments-video/template/src/app/setup/page.tsx +346 -350
  117. package/dist/templates/web/ui-auth-payments-video/template/src/app/signup/page.tsx +9 -128
  118. package/dist/templates/web/ui-auth-payments-video/template/src/components/client/login-form.tsx +90 -0
  119. package/dist/templates/web/ui-auth-payments-video/template/src/components/client/signup-form.tsx +105 -0
  120. package/dist/templates/web/ui-auth-payments-video/template/src/components/providers/app-providers.tsx +8 -3
  121. package/dist/templates/web/ui-auth-payments-video/template/src/components/shared/header.tsx +229 -246
  122. package/dist/templates/web/ui-only/template/eslint.config.mjs +14 -0
  123. package/dist/templates/web/ui-only/template/src/app/checkout/page.tsx +2 -2
  124. package/dist/templates/web/ui-only/template/src/app/login/page.tsx +69 -63
  125. package/dist/templates/web/ui-only/template/src/app/page.tsx +69 -91
  126. package/dist/templates/web/ui-only/template/src/app/signup/page.tsx +94 -79
  127. package/dist/templates/web/ui-only/template/src/components/providers/app-providers.tsx +1 -6
  128. package/dist/templates/web/ui-only/template/src/components/shared/header.tsx +90 -53
  129. package/dist/templates/web/ui-package-test/template/package.json +19 -23
  130. package/dist/templates/web/ui-package-test/template/postcss.config.mjs +8 -0
  131. package/dist/templates/web/ui-package-test/template/src/app/globals.css +88 -0
  132. package/dist/templates/web/ui-package-test/template/src/app/layout.tsx +27 -0
  133. package/dist/templates/web/ui-package-test/template/src/app/page.tsx +46 -106
  134. package/package.json +1 -1
  135. package/src/templates/shared/admin/web/src/components/admin-nav.tsx +3 -3
  136. package/src/templates/shared/auth/supabase/web/src/lib/auth-session.ts +36 -16
  137. package/src/templates/shared/auth/supabase/web/src/middleware.ts +6 -0
  138. package/src/templates/shared/cookie-consent/web/components/cookie-consent.tsx +5 -5
  139. package/src/templates/shared/design/web/src/components/ui/button.tsx +56 -0
  140. package/src/templates/shared/email/web/src/lib/email/client.ts +1 -1
  141. package/src/templates/shared/error-pages/web/src/app/error.tsx +13 -11
  142. package/src/templates/shared/error-pages/web/src/app/global-error.tsx +2 -0
  143. package/src/templates/shared/error-pages/web/src/app/not-found.tsx +6 -6
  144. package/src/templates/shared/legal/web/src/app/(legal)/privacy/page.tsx +4 -4
  145. package/src/templates/shared/legal/web/src/app/(legal)/terms/page.tsx +4 -4
  146. package/src/templates/shared/loading/web/components/skeleton.tsx +4 -4
  147. package/src/templates/shared/mock/web/.env.local +55 -0
  148. package/src/templates/shared/mock/web/src/components/mock-auth-provider.tsx +72 -0
  149. package/src/templates/shared/mock/web/src/components/mock-banner.tsx +29 -0
  150. package/src/templates/shared/mock/web/src/lib/mock.ts +147 -0
  151. package/src/templates/shared/payments/web/src/app/api/webhooks/stripe/route.ts +10 -4
  152. package/src/templates/shared/redis/web/src/lib/redis.ts +1 -1
  153. package/src/templates/web/base/template/eslint.config.mjs +14 -0
  154. package/src/templates/web/base/template/src/app/auth/callback/route.ts +1 -1
  155. package/src/templates/web/base/template/src/app/checkout/page.tsx +76 -103
  156. package/src/templates/web/base/template/src/app/dashboard/page.tsx +145 -329
  157. package/src/templates/web/base/template/src/app/layout.tsx +40 -38
  158. package/src/templates/web/base/template/src/app/login/page.tsx +116 -66
  159. package/src/templates/web/base/template/src/app/page.tsx +97 -193
  160. package/src/templates/web/base/template/src/app/settings/page.tsx +154 -0
  161. package/src/templates/web/base/template/src/app/signup/page.tsx +117 -66
  162. package/src/templates/web/base/template/src/components/providers/app-providers.tsx +8 -3
  163. package/src/templates/web/base/template/src/components/shared/header.tsx +229 -63
  164. package/src/templates/web/ui-auth/template/eslint.config.mjs +14 -0
  165. package/src/templates/web/ui-auth/template/src/app/checkout/page.tsx +3 -3
  166. package/src/templates/web/ui-auth/template/src/app/dev-setup/page.tsx +81 -91
  167. package/src/templates/web/ui-auth/template/src/app/layout.tsx +38 -36
  168. package/src/templates/web/ui-auth/template/src/app/login/page.tsx +22 -45
  169. package/src/templates/web/ui-auth/template/src/app/page.tsx +106 -306
  170. package/src/templates/web/ui-auth/template/src/app/setup/page.tsx +387 -402
  171. package/src/templates/web/ui-auth/template/src/app/signup/page.tsx +24 -47
  172. package/src/templates/web/ui-auth/template/src/components/providers/app-providers.tsx +8 -3
  173. package/src/templates/web/ui-auth/template/src/components/shared/header.tsx +229 -94
  174. package/src/templates/web/ui-auth-ai/template/src/app/layout.tsx +38 -45
  175. package/src/templates/web/ui-auth-ai/template/src/app/login/page.tsx +86 -0
  176. package/src/templates/web/ui-auth-ai/template/src/app/page.tsx +107 -193
  177. package/src/templates/web/ui-auth-ai/template/src/app/signup/page.tsx +105 -0
  178. package/src/templates/web/ui-auth-ai/template/src/components/ai/audio-generator.tsx +144 -140
  179. package/src/templates/web/ui-auth-ai/template/src/components/ai/video-generator.tsx +156 -157
  180. package/src/templates/web/ui-auth-ai/template/src/components/auth/login-form.tsx +7 -3
  181. package/src/templates/web/ui-auth-ai/template/src/components/providers/app-providers.tsx +25 -0
  182. package/src/templates/web/ui-auth-ai/template/src/components/shared/footer.tsx +36 -0
  183. package/src/templates/web/ui-auth-ai/template/src/components/shared/header.tsx +228 -0
  184. package/src/templates/web/ui-auth-ai/template/src/components/ui/button.tsx +5 -5
  185. package/src/templates/web/ui-auth-ai/template/src/components/ui/input.tsx +1 -1
  186. package/src/templates/web/ui-auth-ai/template/src/components/ui/select.tsx +1 -1
  187. package/src/templates/web/ui-auth-ai/template/src/components/ui/textarea.tsx +1 -1
  188. package/src/templates/web/ui-auth-ai/template/src/components/ui/theme-toggle.tsx +34 -0
  189. package/src/templates/web/ui-auth-ai/template/src/lib/supabase.ts +6 -4
  190. package/src/templates/web/ui-auth-ai/template/src/providers/auth-provider.tsx +7 -5
  191. package/src/templates/web/ui-auth-payments/template/src/app/billing/page.tsx +63 -192
  192. package/src/templates/web/ui-auth-payments/template/src/app/checkout/page.tsx +104 -296
  193. package/src/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +27 -27
  194. package/src/templates/web/ui-auth-payments/template/src/app/dev-setup/page.tsx +70 -81
  195. package/src/templates/web/ui-auth-payments/template/src/app/layout.tsx +38 -36
  196. package/src/templates/web/ui-auth-payments/template/src/app/login/loading.tsx +9 -9
  197. package/src/templates/web/ui-auth-payments/template/src/app/login/page.tsx +4 -104
  198. package/src/templates/web/ui-auth-payments/template/src/app/page.tsx +69 -337
  199. package/src/templates/web/ui-auth-payments/template/src/app/setup/page.tsx +55 -68
  200. package/src/templates/web/ui-auth-payments/template/src/app/signup/loading.tsx +13 -13
  201. package/src/templates/web/ui-auth-payments/template/src/app/signup/page.tsx +4 -123
  202. package/src/templates/web/ui-auth-payments/template/src/components/client/auth-status.tsx +37 -52
  203. package/src/templates/web/ui-auth-payments/template/src/components/client/login-form.tsx +49 -103
  204. package/src/templates/web/ui-auth-payments/template/src/components/client/newsletter-signup.tsx +4 -4
  205. package/src/templates/web/ui-auth-payments/template/src/components/client/signup-form.tsx +60 -140
  206. package/src/templates/web/ui-auth-payments/template/src/components/providers/app-providers.tsx +25 -28
  207. package/src/templates/web/ui-auth-payments/template/src/components/shared/header.tsx +229 -230
  208. package/src/templates/web/ui-auth-payments/template/src/lib/actions/auth.ts +245 -245
  209. package/src/templates/web/ui-auth-payments/template/src/lib/actions/index.ts +339 -339
  210. package/src/templates/web/ui-auth-payments-ai/template/src/app/ai/page.tsx +305 -309
  211. package/src/templates/web/ui-auth-payments-ai/template/src/app/billing/page.tsx +62 -312
  212. package/src/templates/web/ui-auth-payments-ai/template/src/app/checkout/page.tsx +109 -125
  213. package/src/templates/web/ui-auth-payments-ai/template/src/app/dashboard/page.tsx +27 -27
  214. package/src/templates/web/ui-auth-payments-ai/template/src/app/dev-setup/page.tsx +68 -83
  215. package/src/templates/web/ui-auth-payments-ai/template/src/app/layout.tsx +40 -38
  216. package/src/templates/web/ui-auth-payments-ai/template/src/app/onboarding/page.tsx +20 -20
  217. package/src/templates/web/ui-auth-payments-ai/template/src/app/page.tsx +140 -394
  218. package/src/templates/web/ui-auth-payments-ai/template/src/app/settings/page.tsx +28 -27
  219. package/src/templates/web/ui-auth-payments-ai/template/src/app/setup/page.tsx +51 -66
  220. package/src/templates/web/ui-auth-payments-ai/template/src/components/client/auth-status.tsx +37 -52
  221. package/src/templates/web/ui-auth-payments-ai/template/src/components/client/login-form.tsx +50 -79
  222. package/src/templates/web/ui-auth-payments-ai/template/src/components/client/signup-form.tsx +58 -111
  223. package/src/templates/web/ui-auth-payments-ai/template/src/components/providers/app-providers.tsx +8 -3
  224. package/src/templates/web/ui-auth-payments-ai/template/src/components/shared/header.tsx +229 -252
  225. package/src/templates/web/ui-auth-payments-ai/template/src/lib/actions/auth.ts +245 -245
  226. package/src/templates/web/ui-auth-payments-audio/template/src/app/billing/page.tsx +63 -192
  227. package/src/templates/web/ui-auth-payments-audio/template/src/app/checkout/page.tsx +109 -125
  228. package/src/templates/web/ui-auth-payments-audio/template/src/app/dashboard/page.tsx +27 -27
  229. package/src/templates/web/ui-auth-payments-audio/template/src/app/layout.tsx +40 -38
  230. package/src/templates/web/ui-auth-payments-audio/template/src/app/page.tsx +122 -385
  231. package/src/templates/web/ui-auth-payments-audio/template/src/app/setup/page.tsx +340 -344
  232. package/src/templates/web/ui-auth-payments-audio/template/src/components/client/auth-status.tsx +37 -52
  233. package/src/templates/web/ui-auth-payments-audio/template/src/components/client/login-form.tsx +49 -103
  234. package/src/templates/web/ui-auth-payments-audio/template/src/components/client/signup-form.tsx +60 -140
  235. package/src/templates/web/ui-auth-payments-audio/template/src/components/providers/app-providers.tsx +8 -3
  236. package/src/templates/web/ui-auth-payments-audio/template/src/components/shared/header.tsx +229 -252
  237. package/src/templates/web/ui-auth-payments-audio/template/src/lib/actions/auth.ts +3 -3
  238. package/src/templates/web/ui-auth-payments-video/template/src/app/billing/page.tsx +63 -192
  239. package/src/templates/web/ui-auth-payments-video/template/src/app/checkout/page.tsx +109 -125
  240. package/src/templates/web/ui-auth-payments-video/template/src/app/layout.tsx +38 -36
  241. package/src/templates/web/ui-auth-payments-video/template/src/app/login/page.tsx +9 -109
  242. package/src/templates/web/ui-auth-payments-video/template/src/app/page.tsx +132 -392
  243. package/src/templates/web/ui-auth-payments-video/template/src/app/setup/page.tsx +346 -350
  244. package/src/templates/web/ui-auth-payments-video/template/src/app/signup/page.tsx +9 -128
  245. package/src/templates/web/ui-auth-payments-video/template/src/components/client/login-form.tsx +90 -0
  246. package/src/templates/web/ui-auth-payments-video/template/src/components/client/signup-form.tsx +105 -0
  247. package/src/templates/web/ui-auth-payments-video/template/src/components/providers/app-providers.tsx +8 -3
  248. package/src/templates/web/ui-auth-payments-video/template/src/components/shared/header.tsx +229 -246
  249. package/src/templates/web/ui-only/template/eslint.config.mjs +14 -0
  250. package/src/templates/web/ui-only/template/src/app/checkout/page.tsx +2 -2
  251. package/src/templates/web/ui-only/template/src/app/login/page.tsx +69 -63
  252. package/src/templates/web/ui-only/template/src/app/page.tsx +69 -91
  253. package/src/templates/web/ui-only/template/src/app/signup/page.tsx +94 -79
  254. package/src/templates/web/ui-only/template/src/components/providers/app-providers.tsx +1 -6
  255. package/src/templates/web/ui-only/template/src/components/shared/header.tsx +90 -53
  256. package/src/templates/web/ui-package-test/template/package.json +19 -23
  257. package/src/templates/web/ui-package-test/template/postcss.config.mjs +8 -0
  258. package/src/templates/web/ui-package-test/template/src/app/globals.css +88 -0
  259. package/src/templates/web/ui-package-test/template/src/app/layout.tsx +27 -0
  260. package/src/templates/web/ui-package-test/template/src/app/page.tsx +46 -106
  261. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/README.md +0 -655
  262. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/app/(tabs)/ai.tsx +0 -683
  263. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/app/_layout.tsx +0 -124
  264. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/app.json +0 -74
  265. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/babel.config.js +0 -25
  266. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/docs/MOBILE-SETUP.md +0 -787
  267. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/eas.json +0 -25
  268. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/expo-env.d.ts +0 -3
  269. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +0 -346
  270. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/jest-setup.ts +0 -37
  271. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/lib/rag/config.ts +0 -180
  272. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/metro.config.js +0 -11
  273. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/package.json +0 -122
  274. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +0 -599
  275. package/dist/templates/mobile/ui-auth-payments-ai-rag/template/tsconfig.json +0 -32
  276. package/dist/templates/web/base/template/.eslintrc.js +0 -8
  277. package/dist/templates/web/base/template/src/components/__tests__/example.test.tsx +0 -49
  278. package/dist/templates/web/base/template/src/test/setup.ts +0 -74
  279. package/dist/templates/web/base/template/vitest.config.ts +0 -17
  280. package/dist/templates/web/ui-auth/template/.eslintrc.js +0 -8
  281. package/dist/templates/web/ui-auth/template/src/components/__tests__/example.test.tsx +0 -49
  282. package/dist/templates/web/ui-auth/template/src/test/setup.ts +0 -74
  283. package/dist/templates/web/ui-auth/template/vitest.config.ts +0 -17
  284. package/dist/templates/web/ui-auth-payments/template/src/components/__tests__/example.test.tsx +0 -49
  285. package/dist/templates/web/ui-auth-payments/template/src/test/setup.ts +0 -74
  286. package/dist/templates/web/ui-auth-payments/template/vitest.config.ts +0 -17
  287. package/dist/templates/web/ui-auth-payments-ai/template/src/components/__tests__/example.test.tsx +0 -49
  288. package/dist/templates/web/ui-auth-payments-ai/template/src/test/setup.ts +0 -74
  289. package/dist/templates/web/ui-auth-payments-ai/template/vitest.config.ts +0 -17
  290. package/dist/templates/web/ui-auth-payments-ai-rag/template/README.md +0 -434
  291. package/dist/templates/web/ui-auth-payments-ai-rag/template/components/rag/KnowledgeManager.tsx +0 -642
  292. package/dist/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGAnalytics.tsx +0 -466
  293. package/dist/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGChatInterface.tsx +0 -393
  294. package/dist/templates/web/ui-auth-payments-ai-rag/template/docs/GETTING-STARTED.md +0 -457
  295. package/dist/templates/web/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +0 -478
  296. package/dist/templates/web/ui-auth-payments-ai-rag/template/lib/rag/config.ts +0 -250
  297. package/dist/templates/web/ui-auth-payments-ai-rag/template/package.json +0 -73
  298. package/dist/templates/web/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +0 -622
  299. package/dist/templates/web/ui-auth-payments-ai-rag/template/src/app/ai/page.tsx +0 -396
  300. package/dist/templates/web/ui-auth-payments-audio/template/src/components/__tests__/example.test.tsx +0 -49
  301. package/dist/templates/web/ui-auth-payments-audio/template/src/test/setup.ts +0 -74
  302. package/dist/templates/web/ui-auth-payments-audio/template/vitest.config.ts +0 -17
  303. package/dist/templates/web/ui-auth-payments-video/template/src/components/__tests__/example.test.tsx +0 -49
  304. package/dist/templates/web/ui-auth-payments-video/template/src/test/setup.ts +0 -74
  305. package/dist/templates/web/ui-auth-payments-video/template/vitest.config.ts +0 -17
  306. package/dist/templates/web/ui-only/template/.eslintrc.js +0 -8
  307. package/dist/templates/web/ui-only/template/src/components/__tests__/example.test.tsx +0 -49
  308. package/dist/templates/web/ui-only/template/src/test/setup.ts +0 -74
  309. package/dist/templates/web/ui-only/template/vitest.config.ts +0 -17
  310. package/src/templates/mobile/ui-auth-payments-ai-rag/template/README.md +0 -655
  311. package/src/templates/mobile/ui-auth-payments-ai-rag/template/app/(tabs)/ai.tsx +0 -683
  312. package/src/templates/mobile/ui-auth-payments-ai-rag/template/app/_layout.tsx +0 -124
  313. package/src/templates/mobile/ui-auth-payments-ai-rag/template/app.json +0 -74
  314. package/src/templates/mobile/ui-auth-payments-ai-rag/template/babel.config.js +0 -25
  315. package/src/templates/mobile/ui-auth-payments-ai-rag/template/docs/MOBILE-SETUP.md +0 -787
  316. package/src/templates/mobile/ui-auth-payments-ai-rag/template/eas.json +0 -25
  317. package/src/templates/mobile/ui-auth-payments-ai-rag/template/expo-env.d.ts +0 -3
  318. package/src/templates/mobile/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +0 -346
  319. package/src/templates/mobile/ui-auth-payments-ai-rag/template/jest-setup.ts +0 -37
  320. package/src/templates/mobile/ui-auth-payments-ai-rag/template/lib/rag/config.ts +0 -180
  321. package/src/templates/mobile/ui-auth-payments-ai-rag/template/metro.config.js +0 -11
  322. package/src/templates/mobile/ui-auth-payments-ai-rag/template/package.json +0 -122
  323. package/src/templates/mobile/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +0 -599
  324. package/src/templates/mobile/ui-auth-payments-ai-rag/template/tsconfig.json +0 -32
  325. package/src/templates/web/base/template/.eslintrc.js +0 -8
  326. package/src/templates/web/base/template/src/components/__tests__/example.test.tsx +0 -49
  327. package/src/templates/web/base/template/src/test/setup.ts +0 -74
  328. package/src/templates/web/base/template/vitest.config.ts +0 -17
  329. package/src/templates/web/ui-auth/template/.eslintrc.js +0 -8
  330. package/src/templates/web/ui-auth/template/src/components/__tests__/example.test.tsx +0 -49
  331. package/src/templates/web/ui-auth/template/src/test/setup.ts +0 -74
  332. package/src/templates/web/ui-auth/template/vitest.config.ts +0 -17
  333. package/src/templates/web/ui-auth-payments/template/src/components/__tests__/example.test.tsx +0 -49
  334. package/src/templates/web/ui-auth-payments/template/src/test/setup.ts +0 -74
  335. package/src/templates/web/ui-auth-payments/template/vitest.config.ts +0 -17
  336. package/src/templates/web/ui-auth-payments-ai/template/src/components/__tests__/example.test.tsx +0 -49
  337. package/src/templates/web/ui-auth-payments-ai/template/src/test/setup.ts +0 -74
  338. package/src/templates/web/ui-auth-payments-ai/template/vitest.config.ts +0 -17
  339. package/src/templates/web/ui-auth-payments-ai-rag/template/README.md +0 -434
  340. package/src/templates/web/ui-auth-payments-ai-rag/template/components/rag/KnowledgeManager.tsx +0 -642
  341. package/src/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGAnalytics.tsx +0 -466
  342. package/src/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGChatInterface.tsx +0 -393
  343. package/src/templates/web/ui-auth-payments-ai-rag/template/docs/GETTING-STARTED.md +0 -457
  344. package/src/templates/web/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +0 -478
  345. package/src/templates/web/ui-auth-payments-ai-rag/template/lib/rag/config.ts +0 -250
  346. package/src/templates/web/ui-auth-payments-ai-rag/template/package.json +0 -73
  347. package/src/templates/web/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +0 -622
  348. package/src/templates/web/ui-auth-payments-ai-rag/template/src/app/ai/page.tsx +0 -396
  349. package/src/templates/web/ui-auth-payments-audio/template/src/components/__tests__/example.test.tsx +0 -49
  350. package/src/templates/web/ui-auth-payments-audio/template/src/test/setup.ts +0 -74
  351. package/src/templates/web/ui-auth-payments-audio/template/vitest.config.ts +0 -17
  352. package/src/templates/web/ui-auth-payments-video/template/src/components/__tests__/example.test.tsx +0 -49
  353. package/src/templates/web/ui-auth-payments-video/template/src/test/setup.ts +0 -74
  354. package/src/templates/web/ui-auth-payments-video/template/vitest.config.ts +0 -17
  355. package/src/templates/web/ui-only/template/.eslintrc.js +0 -8
  356. package/src/templates/web/ui-only/template/src/components/__tests__/example.test.tsx +0 -49
  357. package/src/templates/web/ui-only/template/src/test/setup.ts +0 -74
  358. 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
  }