create-nextblock 0.16.1 → 0.16.2

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 (258) hide show
  1. package/docker-template/.dockerignore +1 -1
  2. package/libs/db/tsconfig.lib.json +3 -3
  3. package/libs/editor/tsconfig.lib.json +3 -3
  4. package/libs/ui/tsconfig.lib.json +3 -3
  5. package/libs/utils/tsconfig.json +3 -3
  6. package/package.json +50 -50
  7. package/project.json +19 -19
  8. package/templates/nextblock-template/.dockerignore +1 -1
  9. package/templates/nextblock-template/.swcrc +30 -30
  10. package/templates/nextblock-template/AGENTS.md +9 -9
  11. package/templates/nextblock-template/CLAUDE.md +1 -1
  12. package/templates/nextblock-template/app/(auth-pages)/layout.tsx +9 -9
  13. package/templates/nextblock-template/app/(auth-pages)/post-sign-in/page.tsx +27 -27
  14. package/templates/nextblock-template/app/.well-known/ucp/route.ts +16 -16
  15. package/templates/nextblock-template/app/ToasterProvider.tsx +26 -26
  16. package/templates/nextblock-template/app/[slug]/pageClientActions.ts +7 -7
  17. package/templates/nextblock-template/app/actions/contactSellerActions.test.ts +280 -280
  18. package/templates/nextblock-template/app/actions/contactSellerActions.ts +222 -222
  19. package/templates/nextblock-template/app/actions/email-retry.test.ts +62 -62
  20. package/templates/nextblock-template/app/actions/email.ts +241 -241
  21. package/templates/nextblock-template/app/actions/formActions.ts +245 -245
  22. package/templates/nextblock-template/app/actions/interactions.ts +489 -489
  23. package/templates/nextblock-template/app/actions/threadActions.ts +166 -166
  24. package/templates/nextblock-template/app/actions/visibilityActions.ts +210 -210
  25. package/templates/nextblock-template/app/api/ai/seo/alt-text/route.ts +221 -221
  26. package/templates/nextblock-template/app/api/ai/seo/metadata/route.ts +186 -186
  27. package/templates/nextblock-template/app/api/checkout/freemius/sync/route.ts +29 -29
  28. package/templates/nextblock-template/app/api/checkout/route.ts +162 -162
  29. package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +3092 -3092
  30. package/templates/nextblock-template/app/api/mcp/route.ts +415 -415
  31. package/templates/nextblock-template/app/api/media/record/route.ts +160 -160
  32. package/templates/nextblock-template/app/api/search/route.ts +43 -43
  33. package/templates/nextblock-template/app/api/view/route.ts +114 -114
  34. package/templates/nextblock-template/app/api/visual-editing/block-draft/route.ts +47 -47
  35. package/templates/nextblock-template/app/api/visual-editing/product-draft/route.ts +47 -47
  36. package/templates/nextblock-template/app/auth/callback/route.ts +31 -31
  37. package/templates/nextblock-template/app/cart/page.tsx +7 -7
  38. package/templates/nextblock-template/app/checkout/UcpCartHydrator.tsx +20 -20
  39. package/templates/nextblock-template/app/checkout/page.tsx +57 -57
  40. package/templates/nextblock-template/app/cms/CmsClientLayout.tsx +558 -558
  41. package/templates/nextblock-template/app/cms/blocks/components/BlockEditorModal.tsx +241 -241
  42. package/templates/nextblock-template/app/cms/blocks/components/MediaLibraryModal.tsx +149 -149
  43. package/templates/nextblock-template/app/cms/blocks/editors/FormBlockEditor.tsx +304 -304
  44. package/templates/nextblock-template/app/cms/blocks/editors/ImageBlockEditor.tsx +406 -406
  45. package/templates/nextblock-template/app/cms/components/ContactReminderBanner.tsx +75 -75
  46. package/templates/nextblock-template/app/cms/components/CortexAiActiveContext.tsx +23 -23
  47. package/templates/nextblock-template/app/cms/components/CortexAiPageContext.tsx +58 -58
  48. package/templates/nextblock-template/app/cms/components/FeatureImageField.tsx +254 -254
  49. package/templates/nextblock-template/app/cms/components/FeedbackModal.tsx +36 -36
  50. package/templates/nextblock-template/app/cms/components/PaymentsReminderBanner.tsx +58 -58
  51. package/templates/nextblock-template/app/cms/components/VisibilityBadge.tsx +62 -62
  52. package/templates/nextblock-template/app/cms/components/VisibilityControl.tsx +542 -542
  53. package/templates/nextblock-template/app/cms/coupons/[id]/edit/page.tsx +16 -16
  54. package/templates/nextblock-template/app/cms/coupons/page.tsx +16 -16
  55. package/templates/nextblock-template/app/cms/dashboard/actions.ts +228 -228
  56. package/templates/nextblock-template/app/cms/dashboard/components/DashboardComponents.tsx +200 -200
  57. package/templates/nextblock-template/app/cms/inquiries/actions.ts +66 -66
  58. package/templates/nextblock-template/app/cms/inquiries/page.tsx +12 -12
  59. package/templates/nextblock-template/app/cms/interactions/page.tsx +12 -12
  60. package/templates/nextblock-template/app/cms/layout.tsx +101 -101
  61. package/templates/nextblock-template/app/cms/media/components/FolderNavigator.tsx +273 -273
  62. package/templates/nextblock-template/app/cms/media/components/FolderTree.tsx +122 -122
  63. package/templates/nextblock-template/app/cms/media/components/MediaGridClient.tsx +69 -69
  64. package/templates/nextblock-template/app/cms/messages/MessagesClient.tsx +661 -661
  65. package/templates/nextblock-template/app/cms/messages/actions.ts +404 -404
  66. package/templates/nextblock-template/app/cms/messages/loadInbox.ts +333 -333
  67. package/templates/nextblock-template/app/cms/messages/page.tsx +87 -87
  68. package/templates/nextblock-template/app/cms/messages/require-admin.ts +37 -37
  69. package/templates/nextblock-template/app/cms/navigation/components/NavigationMenuDnd.tsx +3 -3
  70. package/templates/nextblock-template/app/cms/pages/components/PageForm.tsx +649 -649
  71. package/templates/nextblock-template/app/cms/posts/components/PostForm.tsx +618 -618
  72. package/templates/nextblock-template/app/cms/products/[id]/edit/page.tsx +370 -370
  73. package/templates/nextblock-template/app/cms/products/attributes/page.tsx +12 -12
  74. package/templates/nextblock-template/app/cms/products/inventory/page.tsx +13 -13
  75. package/templates/nextblock-template/app/cms/products/productFormData.ts +133 -133
  76. package/templates/nextblock-template/app/cms/products/settings/page.tsx +5 -5
  77. package/templates/nextblock-template/app/cms/revisions/actions.ts +332 -332
  78. package/templates/nextblock-template/app/cms/revisions/service.test.ts +498 -498
  79. package/templates/nextblock-template/app/cms/revisions/service.ts +569 -569
  80. package/templates/nextblock-template/app/cms/revisions/utils.ts +304 -304
  81. package/templates/nextblock-template/app/cms/settings/cortex-ai/CortexAiSettingsClient.tsx +948 -948
  82. package/templates/nextblock-template/app/cms/settings/cortex-ai/McpServerSettingsCard.tsx +628 -628
  83. package/templates/nextblock-template/app/cms/settings/cortex-ai/mcp-actions.ts +230 -230
  84. package/templates/nextblock-template/app/cms/settings/cortex-ai/require-admin.ts +34 -34
  85. package/templates/nextblock-template/app/cms/settings/currencies/actions.ts +331 -331
  86. package/templates/nextblock-template/app/cms/settings/currencies/page.tsx +494 -494
  87. package/templates/nextblock-template/app/cms/settings/email/components/EmailForm.tsx +227 -227
  88. package/templates/nextblock-template/app/cms/settings/extra-translations/ExtraTranslationsWorkspace.tsx +767 -767
  89. package/templates/nextblock-template/app/cms/settings/extra-translations/actions.ts +276 -276
  90. package/templates/nextblock-template/app/cms/settings/extra-translations/page.tsx +93 -93
  91. package/templates/nextblock-template/app/cms/settings/global-css/components/ThemeEditor.tsx +382 -382
  92. package/templates/nextblock-template/app/cms/settings/global-css/components/ThemeManager.tsx +267 -267
  93. package/templates/nextblock-template/app/cms/settings/global-css/page.tsx +40 -40
  94. package/templates/nextblock-template/app/cms/settings/global-css/theme-actions.ts +259 -259
  95. package/templates/nextblock-template/app/cms/settings/logos/[id]/edit/page.tsx +7 -7
  96. package/templates/nextblock-template/app/cms/settings/logos/components/BrandingSettingsForm.tsx +339 -339
  97. package/templates/nextblock-template/app/cms/settings/logos/new/page.tsx +8 -8
  98. package/templates/nextblock-template/app/cms/settings/seo/RedirectsCard.tsx +514 -514
  99. package/templates/nextblock-template/app/cms/settings/seo/RobotsCard.tsx +529 -529
  100. package/templates/nextblock-template/app/cms/settings/seo/SeoSettingsClient.tsx +57 -57
  101. package/templates/nextblock-template/app/cms/settings/seo/actions.ts +448 -448
  102. package/templates/nextblock-template/app/cms/settings/seo/mappers.ts +93 -93
  103. package/templates/nextblock-template/app/cms/settings/seo/page.tsx +46 -46
  104. package/templates/nextblock-template/app/cms/settings/seo/require-admin.ts +47 -47
  105. package/templates/nextblock-template/app/cms/settings/site-scripts/page.tsx +51 -51
  106. package/templates/nextblock-template/app/cms/settings/taxes/page.tsx +21 -21
  107. package/templates/nextblock-template/app/cms/shipping/page.tsx +20 -20
  108. package/templates/nextblock-template/app/cms/users/components/DeleteUserButton.tsx +12 -12
  109. package/templates/nextblock-template/app/layout.tsx +671 -671
  110. package/templates/nextblock-template/app/lib/seo.ts +319 -319
  111. package/templates/nextblock-template/app/lib/ucp/protocol.ts +190 -190
  112. package/templates/nextblock-template/app/lib/ucp/server.test.ts +56 -56
  113. package/templates/nextblock-template/app/product/[slug]/page.tsx +502 -502
  114. package/templates/nextblock-template/app/profile/ProfilePageHeader.tsx +16 -16
  115. package/templates/nextblock-template/app/profile/ProfilePageMissingState.tsx +9 -9
  116. package/templates/nextblock-template/app/profile/account-links.ts +22 -22
  117. package/templates/nextblock-template/app/profile/orders/CustomerOrdersPageClient.tsx +124 -124
  118. package/templates/nextblock-template/app/profile/orders/page.tsx +19 -19
  119. package/templates/nextblock-template/app/profile/password/PasswordSettingsPageClient.tsx +128 -128
  120. package/templates/nextblock-template/app/profile/password/actions.ts +59 -59
  121. package/templates/nextblock-template/app/profile/password/page.tsx +27 -27
  122. package/templates/nextblock-template/app/providers.tsx +96 -96
  123. package/templates/nextblock-template/app/robots.ts +123 -123
  124. package/templates/nextblock-template/app/thread/ThreadView.tsx +164 -164
  125. package/templates/nextblock-template/app/thread/[token]/route.ts +57 -57
  126. package/templates/nextblock-template/app/thread/layout.tsx +15 -15
  127. package/templates/nextblock-template/app/thread/page.tsx +98 -98
  128. package/templates/nextblock-template/app/ucp/v1/carts/[id]/cancel/route.ts +38 -38
  129. package/templates/nextblock-template/app/ucp/v1/carts/[id]/route.ts +68 -68
  130. package/templates/nextblock-template/app/ucp/v1/carts/route.ts +35 -35
  131. package/templates/nextblock-template/app/ucp/v1/catalog/lookup/route.ts +35 -35
  132. package/templates/nextblock-template/app/ucp/v1/catalog/product/route.ts +35 -35
  133. package/templates/nextblock-template/app/ucp/v1/catalog/search/route.ts +34 -34
  134. package/templates/nextblock-template/components/BlockRenderer.tsx +312 -312
  135. package/templates/nextblock-template/components/CartDrawerLoader.tsx +7 -7
  136. package/templates/nextblock-template/components/CartTranslator.tsx +210 -210
  137. package/templates/nextblock-template/components/ContactSellerSection.tsx +188 -188
  138. package/templates/nextblock-template/components/DeferredCartDrawer.tsx +23 -23
  139. package/templates/nextblock-template/components/DeferredCartTranslator.tsx +51 -51
  140. package/templates/nextblock-template/components/DeferredGlobalSearch.tsx +68 -68
  141. package/templates/nextblock-template/components/DeferredGoogleTagManager.tsx +70 -70
  142. package/templates/nextblock-template/components/DeferredSpeedInsights.tsx +69 -69
  143. package/templates/nextblock-template/components/FooterNavigation.tsx +32 -32
  144. package/templates/nextblock-template/components/GlobalSearch.tsx +557 -557
  145. package/templates/nextblock-template/components/Header.tsx +38 -38
  146. package/templates/nextblock-template/components/HtmlScriptExecutor.tsx +47 -47
  147. package/templates/nextblock-template/components/LanguageSwitcher.tsx +2 -2
  148. package/templates/nextblock-template/components/PostCommentsSection.tsx +378 -378
  149. package/templates/nextblock-template/components/ProductReviewsSection.tsx +426 -426
  150. package/templates/nextblock-template/components/SiteScripts.tsx +56 -56
  151. package/templates/nextblock-template/components/StaffReplies.tsx +102 -102
  152. package/templates/nextblock-template/components/blocks/PostCardSkeleton.tsx +12 -12
  153. package/templates/nextblock-template/components/blocks/PostsGridBlock.tsx +12 -12
  154. package/templates/nextblock-template/components/blocks/PostsGridClient.tsx +48 -48
  155. package/templates/nextblock-template/components/blocks/TestimonialBlock.tsx +9 -9
  156. package/templates/nextblock-template/components/blocks/ecommerceRendererLoaders.ts +23 -23
  157. package/templates/nextblock-template/components/blocks/publicRendererLoaders.ts +25 -25
  158. package/templates/nextblock-template/components/blocks/renderers/ButtonBlockRenderer.tsx +92 -92
  159. package/templates/nextblock-template/components/blocks/renderers/CartBlockRenderer.tsx +18 -18
  160. package/templates/nextblock-template/components/blocks/renderers/CheckoutBlockRenderer.tsx +20 -20
  161. package/templates/nextblock-template/components/blocks/renderers/FeaturedProductBlockRenderer.tsx +25 -25
  162. package/templates/nextblock-template/components/blocks/renderers/FormBlockRenderer.tsx +385 -385
  163. package/templates/nextblock-template/components/blocks/renderers/PostsGridBlockRenderer.tsx +24 -24
  164. package/templates/nextblock-template/components/blocks/renderers/ProductDetailsBlockRenderer.tsx +157 -157
  165. package/templates/nextblock-template/components/blocks/renderers/ProductGridBlockRenderer.tsx +34 -34
  166. package/templates/nextblock-template/components/blocks/renderers/SectionBlockRenderer.tsx +612 -612
  167. package/templates/nextblock-template/components/blocks/renderers/TestimonialBlockRenderer.tsx +57 -57
  168. package/templates/nextblock-template/components/blocks/renderers/inline/AlertWidgetRenderer.tsx +2 -2
  169. package/templates/nextblock-template/components/blocks/renderers/inline/CtaWidgetRenderer.tsx +2 -2
  170. package/templates/nextblock-template/components/blocks/types.ts +7 -7
  171. package/templates/nextblock-template/components/commerce/PaymentReadinessBoundary.tsx +32 -32
  172. package/templates/nextblock-template/components/env-var-warning.tsx +3 -3
  173. package/templates/nextblock-template/components/form-message.tsx +32 -32
  174. package/templates/nextblock-template/components/seo/GenerateMetaButton.tsx +137 -137
  175. package/templates/nextblock-template/components/seo/PageSeoAuditSection.tsx +244 -244
  176. package/templates/nextblock-template/components/seo/SeoAuditPanel.tsx +749 -749
  177. package/templates/nextblock-template/components/seo/SeoIssueList.tsx +195 -195
  178. package/templates/nextblock-template/components/seo/SeoScoreDial.tsx +144 -144
  179. package/templates/nextblock-template/components/seo/SocialPreview.tsx +243 -243
  180. package/templates/nextblock-template/components/seo/SocialPreviewDialog.tsx +110 -110
  181. package/templates/nextblock-template/components/submit-button.tsx +23 -23
  182. package/templates/nextblock-template/components/theme-icon.tsx +78 -78
  183. package/templates/nextblock-template/components/theme-switcher.tsx +85 -85
  184. package/templates/nextblock-template/context/AuthContext.tsx +23 -23
  185. package/templates/nextblock-template/context/ThemeCatalogContext.tsx +44 -44
  186. package/templates/nextblock-template/docs/01-PROJECT-OVERVIEW.md +94 -94
  187. package/templates/nextblock-template/docs/03-CMS-AND-EDITOR.md +77 -77
  188. package/templates/nextblock-template/docs/13-STAYING-UP-TO-DATE.md +372 -372
  189. package/templates/nextblock-template/docs/14-MESSAGES-INBOX.md +309 -309
  190. package/templates/nextblock-template/docs/README.md +42 -42
  191. package/templates/nextblock-template/docs/TECHNICAL_SPECIFICATION.md +12506 -12506
  192. package/templates/nextblock-template/hooks/use-hotkeys.ts +21 -21
  193. package/templates/nextblock-template/hooks/useGlobalSearch.ts +101 -101
  194. package/templates/nextblock-template/index.d.ts +7 -7
  195. package/templates/nextblock-template/lib/auth-redirects.ts +46 -46
  196. package/templates/nextblock-template/lib/blocks/blockColors.test.ts +134 -134
  197. package/templates/nextblock-template/lib/blocks/blockColors.ts +175 -175
  198. package/templates/nextblock-template/lib/blocks/blockRegistry.ts +761 -761
  199. package/templates/nextblock-template/lib/blocks/inlineScriptNonce.ts +20 -20
  200. package/templates/nextblock-template/lib/cms/contact-reminder.ts +64 -64
  201. package/templates/nextblock-template/lib/cms/payments-reminder.test.ts +135 -0
  202. package/templates/nextblock-template/lib/cms/payments-reminder.ts +30 -23
  203. package/templates/nextblock-template/lib/cms/unread-messages.ts +42 -42
  204. package/templates/nextblock-template/lib/commerce/seller-contact.ts +162 -162
  205. package/templates/nextblock-template/lib/config/email-settings.ts +323 -323
  206. package/templates/nextblock-template/lib/config/email-tls.test.ts +57 -57
  207. package/templates/nextblock-template/lib/cortex-ai/alt-text-request.ts +86 -86
  208. package/templates/nextblock-template/lib/cortex-ai/sandbox-headers.ts +60 -60
  209. package/templates/nextblock-template/lib/email/placeholder-address.test.ts +59 -59
  210. package/templates/nextblock-template/lib/email/placeholder-address.ts +39 -39
  211. package/templates/nextblock-template/lib/messages/thread-reference.test.ts +70 -70
  212. package/templates/nextblock-template/lib/messages/thread-token.test.ts +93 -93
  213. package/templates/nextblock-template/lib/messages/thread-token.ts +157 -157
  214. package/templates/nextblock-template/lib/messages/threads.ts +579 -579
  215. package/templates/nextblock-template/lib/posts/readTime.ts +60 -60
  216. package/templates/nextblock-template/lib/publishing/viewUrl.ts +26 -26
  217. package/templates/nextblock-template/lib/search/types.ts +27 -27
  218. package/templates/nextblock-template/lib/seo/alt-text-write-back.test.ts +154 -154
  219. package/templates/nextblock-template/lib/seo/alt-text-write-back.ts +109 -109
  220. package/templates/nextblock-template/lib/seo/block-content.ts +123 -123
  221. package/templates/nextblock-template/lib/seo/fix-prompts.test.ts +242 -242
  222. package/templates/nextblock-template/lib/seo/fix-prompts.ts +204 -204
  223. package/templates/nextblock-template/lib/seo/page-audit-context.tsx +140 -140
  224. package/templates/nextblock-template/lib/seo/page-document.test.ts +350 -350
  225. package/templates/nextblock-template/lib/seo/page-document.ts +412 -412
  226. package/templates/nextblock-template/lib/seo/redirect-store.test.ts +479 -479
  227. package/templates/nextblock-template/lib/seo/redirect-store.ts +466 -466
  228. package/templates/nextblock-template/lib/seo/robots-settings-signature.test.ts +102 -102
  229. package/templates/nextblock-template/lib/seo/robots-settings-signature.ts +41 -41
  230. package/templates/nextblock-template/lib/seo/robots-txt.test.ts +370 -370
  231. package/templates/nextblock-template/lib/seo/robots-txt.ts +510 -510
  232. package/templates/nextblock-template/lib/setup/migrations-bundle.ts +177 -177
  233. package/templates/nextblock-template/lib/site-scripts/revisions.ts +71 -71
  234. package/templates/nextblock-template/lib/site-scripts/types.ts +46 -46
  235. package/templates/nextblock-template/lib/site-url.test.ts +89 -89
  236. package/templates/nextblock-template/lib/site-url.ts +102 -102
  237. package/templates/nextblock-template/lib/themes/buildThemeCss.ts +124 -124
  238. package/templates/nextblock-template/lib/themes/tokenColor.ts +31 -31
  239. package/templates/nextblock-template/lib/themes/tokens.ts +143 -143
  240. package/templates/nextblock-template/lib/visual-editing/draft-content.test.ts +105 -105
  241. package/templates/nextblock-template/lib/visual-editing/draft-route.test.ts +42 -42
  242. package/templates/nextblock-template/lib/visual-editing/edit-info.test.ts +143 -143
  243. package/templates/nextblock-template/lib/visual-editing/edit-info.ts +94 -94
  244. package/templates/nextblock-template/lib/visual-editing/product-drafts.test.ts +81 -81
  245. package/templates/nextblock-template/lib/zod-config.ts +5 -5
  246. package/templates/nextblock-template/next-env.d.ts +1 -2
  247. package/templates/nextblock-template/package.json +1 -1
  248. package/templates/nextblock-template/postcss.config.js +6 -6
  249. package/templates/nextblock-template/scripts/backup.js +115 -115
  250. package/templates/nextblock-template/scripts/restore.js +385 -385
  251. package/templates/nextblock-template/scripts/validate-editor-block-schema.ts +112 -112
  252. package/templates/nextblock-template/tailwind.config.js +25 -25
  253. package/templates/nextblock-template/tools/build-migrate.mjs +102 -102
  254. package/templates/nextblock-template/tools/configure-supabase-auth.js +282 -282
  255. package/templates/nextblock-template/tools/deploy-supabase.js +159 -159
  256. package/templates/nextblock-template/tools/lib/migrate-core.mjs +569 -569
  257. package/templates/nextblock-template/tools/update.mjs +1303 -1303
  258. package/tsconfig.base.json +3 -3
@@ -1,59 +1,59 @@
1
- 'use server';
2
-
3
- import { createClient } from '@nextblock-cms/db/server';
4
- import { encodedRedirect } from '@nextblock-cms/utils/server';
5
- import { redirect } from 'next/navigation';
6
-
7
- export async function changePasswordAction(formData: FormData) {
8
- if (process.env.NEXT_PUBLIC_IS_SANDBOX === 'true') {
9
- redirect('/profile');
10
- }
11
-
12
- const supabase = createClient();
13
- const {
14
- data: { user },
15
- error: authError,
16
- } = await supabase.auth.getUser();
17
-
18
- if (authError || !user) {
19
- redirect('/sign-in?redirect=%2Fprofile%2Fpassword');
20
- }
21
-
22
- const password = formData.get('password')?.toString() || '';
23
- const confirmPassword =
24
- formData.get('confirmPassword')?.toString() || '';
25
-
26
- if (!password || !confirmPassword) {
27
- return encodedRedirect(
28
- 'error',
29
- '/profile/password',
30
- 'password_update_failed'
31
- );
32
- }
33
-
34
- if (password !== confirmPassword) {
35
- return encodedRedirect(
36
- 'error',
37
- '/profile/password',
38
- 'passwords_do_not_match'
39
- );
40
- }
41
-
42
- const { error } = await supabase.auth.updateUser({
43
- password,
44
- });
45
-
46
- if (error) {
47
- return encodedRedirect(
48
- 'error',
49
- '/profile/password',
50
- 'password_update_failed'
51
- );
52
- }
53
-
54
- return encodedRedirect(
55
- 'success',
56
- '/profile/password',
57
- 'password_updated_success'
58
- );
59
- }
1
+ 'use server';
2
+
3
+ import { createClient } from '@nextblock-cms/db/server';
4
+ import { encodedRedirect } from '@nextblock-cms/utils/server';
5
+ import { redirect } from 'next/navigation';
6
+
7
+ export async function changePasswordAction(formData: FormData) {
8
+ if (process.env.NEXT_PUBLIC_IS_SANDBOX === 'true') {
9
+ redirect('/profile');
10
+ }
11
+
12
+ const supabase = createClient();
13
+ const {
14
+ data: { user },
15
+ error: authError,
16
+ } = await supabase.auth.getUser();
17
+
18
+ if (authError || !user) {
19
+ redirect('/sign-in?redirect=%2Fprofile%2Fpassword');
20
+ }
21
+
22
+ const password = formData.get('password')?.toString() || '';
23
+ const confirmPassword =
24
+ formData.get('confirmPassword')?.toString() || '';
25
+
26
+ if (!password || !confirmPassword) {
27
+ return encodedRedirect(
28
+ 'error',
29
+ '/profile/password',
30
+ 'password_update_failed'
31
+ );
32
+ }
33
+
34
+ if (password !== confirmPassword) {
35
+ return encodedRedirect(
36
+ 'error',
37
+ '/profile/password',
38
+ 'passwords_do_not_match'
39
+ );
40
+ }
41
+
42
+ const { error } = await supabase.auth.updateUser({
43
+ password,
44
+ });
45
+
46
+ if (error) {
47
+ return encodedRedirect(
48
+ 'error',
49
+ '/profile/password',
50
+ 'password_update_failed'
51
+ );
52
+ }
53
+
54
+ return encodedRedirect(
55
+ 'success',
56
+ '/profile/password',
57
+ 'password_updated_success'
58
+ );
59
+ }
@@ -1,27 +1,27 @@
1
- import { requireProfileAccountContext } from '../account-data';
2
- import { PasswordSettingsPageClient } from './PasswordSettingsPageClient';
3
- import { notFound } from 'next/navigation';
4
-
5
- export default async function ProfilePasswordPage({
6
- searchParams,
7
- }: {
8
- searchParams: Promise<{ success?: string; error?: string }>;
9
- }) {
10
- if (process.env.NEXT_PUBLIC_IS_SANDBOX === 'true') {
11
- notFound();
12
- }
13
-
14
- const { profile, user } = await requireProfileAccountContext(
15
- '/profile/password'
16
- );
17
- const params = await searchParams;
18
-
19
- return (
20
- <PasswordSettingsPageClient
21
- profile={profile}
22
- user={user}
23
- successMessage={params.success || null}
24
- errorMessage={params.error || null}
25
- />
26
- );
27
- }
1
+ import { requireProfileAccountContext } from '../account-data';
2
+ import { PasswordSettingsPageClient } from './PasswordSettingsPageClient';
3
+ import { notFound } from 'next/navigation';
4
+
5
+ export default async function ProfilePasswordPage({
6
+ searchParams,
7
+ }: {
8
+ searchParams: Promise<{ success?: string; error?: string }>;
9
+ }) {
10
+ if (process.env.NEXT_PUBLIC_IS_SANDBOX === 'true') {
11
+ notFound();
12
+ }
13
+
14
+ const { profile, user } = await requireProfileAccountContext(
15
+ '/profile/password'
16
+ );
17
+ const params = await searchParams;
18
+
19
+ return (
20
+ <PasswordSettingsPageClient
21
+ profile={profile}
22
+ user={user}
23
+ successMessage={params.success || null}
24
+ errorMessage={params.error || null}
25
+ />
26
+ );
27
+ }
@@ -1,96 +1,96 @@
1
- "use client";
2
-
3
- import { ThemeProvider } from "next-themes";
4
-
5
- // Suppress the React 19 warning for the <script> tag generated by next-themes in development
6
- if (typeof window !== 'undefined' && process.env.NODE_ENV === 'development') {
7
- const orig = console.error;
8
- console.error = (...args: any[]) => {
9
- if (typeof args[0] === 'string' && args[0].includes('Encountered a script tag')) {
10
- return;
11
- }
12
- orig.apply(console, args);
13
- };
14
- }
15
- import { AuthProvider } from '../context/AuthContext';
16
- import { LanguageProvider, useLanguage } from '../context/LanguageContext';
17
- import { CurrentContentProvider } from '../context/CurrentContentContext';
18
- import { ThemeCatalogProvider } from '../context/ThemeCatalogContext';
19
- import { DeferredCartTranslator } from '../components/DeferredCartTranslator';
20
- import { CurrencyProvider } from '@nextblock-cms/ecommerce/CurrencyProvider';
21
- import { TranslationsProvider } from '@nextblock-cms/utils';
22
-
23
- function TranslationBridge({
24
- children,
25
- translations,
26
- }: {
27
- children: React.ReactNode;
28
- translations: { key: string; translations: Record<string, string> }[];
29
- }) {
30
- const { currentLocale } = useLanguage();
31
-
32
- return (
33
- <TranslationsProvider translations={translations} lang={currentLocale}>
34
- {children}
35
- </TranslationsProvider>
36
- );
37
- }
38
-
39
- export function Providers({ children, ...props }: { children: React.ReactNode;[key: string]: any; }) {
40
- const {
41
- serverUser,
42
- serverProfile,
43
- serverLocale,
44
- initialCurrencies,
45
- initialCurrencyCode,
46
- initialAvailableLanguages,
47
- initialDefaultLanguage,
48
- rememberVisitorChoice,
49
- translations,
50
- nonce,
51
- themeSlugs,
52
- initialTheme,
53
- themeCatalog,
54
- } = props;
55
-
56
- // Themes come from the site_themes table. Fall back to the three that ship in
57
- // libs/ui/src/styles/theme.css if the table is empty or unreachable, so the
58
- // switcher never renders an empty list.
59
- const resolvedThemes: string[] =
60
- Array.isArray(themeSlugs) && themeSlugs.length > 0 ? themeSlugs : ['light', 'dark', 'vibrant'];
61
- const resolvedDefault: string =
62
- typeof initialTheme === 'string' && resolvedThemes.includes(initialTheme) ? initialTheme : 'light';
63
-
64
- return (
65
- <AuthProvider serverUser={serverUser} serverProfile={serverProfile}>
66
- <LanguageProvider
67
- serverLocale={serverLocale}
68
- initialAvailableLanguages={initialAvailableLanguages}
69
- initialDefaultLanguage={initialDefaultLanguage}
70
- rememberVisitorChoice={rememberVisitorChoice}
71
- >
72
- <CurrencyProvider
73
- initialCurrencies={initialCurrencies}
74
- initialCurrencyCode={initialCurrencyCode}
75
- locale={serverLocale}
76
- >
77
- <CurrentContentProvider>
78
- <DeferredCartTranslator />
79
- <TranslationBridge translations={translations}>
80
- <ThemeProvider
81
- attribute="class"
82
- defaultTheme={resolvedDefault}
83
- enableSystem
84
- disableTransitionOnChange
85
- nonce={nonce}
86
- themes={resolvedThemes}
87
- >
88
- <ThemeCatalogProvider themes={themeCatalog}>{children}</ThemeCatalogProvider>
89
- </ThemeProvider>
90
- </TranslationBridge>
91
- </CurrentContentProvider>
92
- </CurrencyProvider>
93
- </LanguageProvider>
94
- </AuthProvider>
95
- );
96
- }
1
+ "use client";
2
+
3
+ import { ThemeProvider } from "next-themes";
4
+
5
+ // Suppress the React 19 warning for the <script> tag generated by next-themes in development
6
+ if (typeof window !== 'undefined' && process.env.NODE_ENV === 'development') {
7
+ const orig = console.error;
8
+ console.error = (...args: any[]) => {
9
+ if (typeof args[0] === 'string' && args[0].includes('Encountered a script tag')) {
10
+ return;
11
+ }
12
+ orig.apply(console, args);
13
+ };
14
+ }
15
+ import { AuthProvider } from '../context/AuthContext';
16
+ import { LanguageProvider, useLanguage } from '../context/LanguageContext';
17
+ import { CurrentContentProvider } from '../context/CurrentContentContext';
18
+ import { ThemeCatalogProvider } from '../context/ThemeCatalogContext';
19
+ import { DeferredCartTranslator } from '../components/DeferredCartTranslator';
20
+ import { CurrencyProvider } from '@nextblock-cms/ecommerce/CurrencyProvider';
21
+ import { TranslationsProvider } from '@nextblock-cms/utils';
22
+
23
+ function TranslationBridge({
24
+ children,
25
+ translations,
26
+ }: {
27
+ children: React.ReactNode;
28
+ translations: { key: string; translations: Record<string, string> }[];
29
+ }) {
30
+ const { currentLocale } = useLanguage();
31
+
32
+ return (
33
+ <TranslationsProvider translations={translations} lang={currentLocale}>
34
+ {children}
35
+ </TranslationsProvider>
36
+ );
37
+ }
38
+
39
+ export function Providers({ children, ...props }: { children: React.ReactNode;[key: string]: any; }) {
40
+ const {
41
+ serverUser,
42
+ serverProfile,
43
+ serverLocale,
44
+ initialCurrencies,
45
+ initialCurrencyCode,
46
+ initialAvailableLanguages,
47
+ initialDefaultLanguage,
48
+ rememberVisitorChoice,
49
+ translations,
50
+ nonce,
51
+ themeSlugs,
52
+ initialTheme,
53
+ themeCatalog,
54
+ } = props;
55
+
56
+ // Themes come from the site_themes table. Fall back to the three that ship in
57
+ // libs/ui/src/styles/theme.css if the table is empty or unreachable, so the
58
+ // switcher never renders an empty list.
59
+ const resolvedThemes: string[] =
60
+ Array.isArray(themeSlugs) && themeSlugs.length > 0 ? themeSlugs : ['light', 'dark', 'vibrant'];
61
+ const resolvedDefault: string =
62
+ typeof initialTheme === 'string' && resolvedThemes.includes(initialTheme) ? initialTheme : 'light';
63
+
64
+ return (
65
+ <AuthProvider serverUser={serverUser} serverProfile={serverProfile}>
66
+ <LanguageProvider
67
+ serverLocale={serverLocale}
68
+ initialAvailableLanguages={initialAvailableLanguages}
69
+ initialDefaultLanguage={initialDefaultLanguage}
70
+ rememberVisitorChoice={rememberVisitorChoice}
71
+ >
72
+ <CurrencyProvider
73
+ initialCurrencies={initialCurrencies}
74
+ initialCurrencyCode={initialCurrencyCode}
75
+ locale={serverLocale}
76
+ >
77
+ <CurrentContentProvider>
78
+ <DeferredCartTranslator />
79
+ <TranslationBridge translations={translations}>
80
+ <ThemeProvider
81
+ attribute="class"
82
+ defaultTheme={resolvedDefault}
83
+ enableSystem
84
+ disableTransitionOnChange
85
+ nonce={nonce}
86
+ themes={resolvedThemes}
87
+ >
88
+ <ThemeCatalogProvider themes={themeCatalog}>{children}</ThemeCatalogProvider>
89
+ </ThemeProvider>
90
+ </TranslationBridge>
91
+ </CurrentContentProvider>
92
+ </CurrencyProvider>
93
+ </LanguageProvider>
94
+ </AuthProvider>
95
+ );
96
+ }
@@ -1,123 +1,123 @@
1
- import type { MetadataRoute } from 'next';
2
- import { getSsgSupabaseClient } from '@nextblock-cms/db/server';
3
- import { normalizeRobotsSettings, type RobotsSettings } from '@nextblock-cms/utils/seo';
4
- import { buildRobotsMetadata } from '../lib/seo/robots-txt';
5
- import { resolveSiteUrl, hasResolvedSiteUrl } from '../lib/site-url';
6
-
7
- /**
8
- * /robots.txt, generated from the operator's stored settings.
9
- *
10
- * This replaces the hand-rolled `app/robots.txt/route.ts` that used to live here,
11
- * and the two CANNOT coexist: Next's `normalizeMetadataRoute` rewrites the page
12
- * `/robots` to `/robots.txt` and then appends `/route`, which is character for
13
- * character the app path the old handler occupied. Keeping both would be a
14
- * duplicate-route collision, not a fallback — so the old file was deleted in the
15
- * same change that added this one. The externally visible path is unchanged, which
16
- * is why `isSetupAllowlisted()` in proxy.ts still allowlists the literal
17
- * '/robots.txt' and needed no edit.
18
- *
19
- * The move from a route handler to the metadata route is what buys the caching
20
- * below. Everything else about the response — the served path, the content type, the
21
- * sandbox behaviour — is identical to what shipped before.
22
- */
23
-
24
- /**
25
- * Cache the generated file and rebuild it at most once an hour, mirroring
26
- * app/sitemap.ts. Crawlers get a fast, statically-served response while a change an
27
- * operator saves in /cms/settings still takes effect without a redeploy.
28
- *
29
- * NextBlock does not enable Next.js Cache Components, so the route-segment
30
- * `revalidate` config is the idiomatic caching control here. If `cacheComponents`
31
- * were turned on, the equivalent would be a `'use cache'` body paired with
32
- * `cacheLife('hours')` instead of this export.
33
- */
34
- export const revalidate = 3600;
35
-
36
- /**
37
- * The `site_settings` row the SEO screen writes, seeded by migration 30 and moved into
38
- * the ADMIN-only write group by migration 31 — a WRITER could otherwise have PATCHed
39
- * this row through PostgREST and de-indexed the whole site, since RLS, not the server
40
- * action, is the boundary that actually holds.
41
- */
42
- const ROBOTS_SETTINGS_KEY = 'seo_robots_settings';
43
-
44
- /**
45
- * Reads the stored robots configuration, falling back to the permissive defaults on
46
- * any failure whatsoever.
47
- *
48
- * The anon client is the right one here, and deliberately so: `seo_robots_settings`
49
- * is a non-secret key and `site_settings`' read policy is already public for
50
- * non-secret keys, so nothing on this path needs the service role. Handing a
51
- * service-role client to a route that anonymous crawlers hit would be a needless
52
- * escalation.
53
- *
54
- * That read has to stay anonymous, which is why migration 31 tightened only the
55
- * INSERT/UPDATE/DELETE policies and left `site_settings_read_policy` alone. Adding
56
- * this key to the read policy's sensitive array would not fail loudly — the query
57
- * below would simply return no row, every crawler would be served the permissive
58
- * defaults, and the operator's configuration would stop applying without a single
59
- * error anywhere.
60
- *
61
- * The failure handling matters more than it looks. A crawler that receives a 500 for
62
- * robots.txt may treat the entire site as disallowed until it next succeeds, so an
63
- * unreachable database — or a `cms_redirects`-era install that has not yet run
64
- * `npm run db:migrate`, where this settings row does not exist — must produce a
65
- * valid, permissive file rather than an error. `normalizeRobotsSettings` handles the
66
- * other half of that: whatever jsonb hands back, including null, a string or a
67
- * half-migrated object, becomes a complete `RobotsSettings`.
68
- */
69
- async function loadRobotsSettings(): Promise<RobotsSettings> {
70
- try {
71
- const supabase = getSsgSupabaseClient();
72
- const { data, error } = await supabase
73
- .from('site_settings')
74
- .select('value')
75
- .eq('key', ROBOTS_SETTINGS_KEY)
76
- .maybeSingle();
77
-
78
- if (error) {
79
- console.error('robots.txt: failed to read the robots settings; serving defaults.', error);
80
- return normalizeRobotsSettings(undefined);
81
- }
82
-
83
- // A missing row is not an error — it is a site whose operator has never opened
84
- // the SEO screen — and the defaults are exactly what that site should serve.
85
- return normalizeRobotsSettings(data?.value);
86
- } catch (error) {
87
- console.error('robots.txt: robots settings lookup threw; serving defaults.', error);
88
- return normalizeRobotsSettings(undefined);
89
- }
90
- }
91
-
92
- export default async function robots(): Promise<MetadataRoute.Robots> {
93
- const isSandbox = process.env.NEXT_PUBLIC_IS_SANDBOX === 'true';
94
-
95
- // The sandbox answer ignores every stored setting, so there is nothing to read.
96
- // Skipping the query keeps a disposable deployment's robots.txt working even when
97
- // its database is asleep or being reset by the cron job. The reasoning for why the
98
- // sandbox ALLOWS crawling rather than disallowing it lives on SANDBOX_USER_AGENT_RULE
99
- // in lib/seo/robots-txt.ts — it is the counter-intuitive part of this feature and
100
- // that is where it is written down in full.
101
- if (isSandbox) {
102
- return buildRobotsMetadata(normalizeRobotsSettings(undefined), {
103
- isSandbox: true,
104
- sitemapUrl: null,
105
- });
106
- }
107
-
108
- // Explicit NEXT_PUBLIC_URL → Vercel production URL → local-dev fallback.
109
- const siteUrl = resolveSiteUrl();
110
-
111
- if (!hasResolvedSiteUrl()) {
112
- console.warn(
113
- 'Warning: no site URL is set for robots.txt (NEXT_PUBLIC_URL / Vercel production URL). Defaulting to http://localhost:3000. Set NEXT_PUBLIC_URL for production.'
114
- );
115
- }
116
-
117
- const settings = await loadRobotsSettings();
118
-
119
- return buildRobotsMetadata(settings, {
120
- isSandbox: false,
121
- sitemapUrl: `${siteUrl}/sitemap.xml`,
122
- });
123
- }
1
+ import type { MetadataRoute } from 'next';
2
+ import { getSsgSupabaseClient } from '@nextblock-cms/db/server';
3
+ import { normalizeRobotsSettings, type RobotsSettings } from '@nextblock-cms/utils/seo';
4
+ import { buildRobotsMetadata } from '../lib/seo/robots-txt';
5
+ import { resolveSiteUrl, hasResolvedSiteUrl } from '../lib/site-url';
6
+
7
+ /**
8
+ * /robots.txt, generated from the operator's stored settings.
9
+ *
10
+ * This replaces the hand-rolled `app/robots.txt/route.ts` that used to live here,
11
+ * and the two CANNOT coexist: Next's `normalizeMetadataRoute` rewrites the page
12
+ * `/robots` to `/robots.txt` and then appends `/route`, which is character for
13
+ * character the app path the old handler occupied. Keeping both would be a
14
+ * duplicate-route collision, not a fallback — so the old file was deleted in the
15
+ * same change that added this one. The externally visible path is unchanged, which
16
+ * is why `isSetupAllowlisted()` in proxy.ts still allowlists the literal
17
+ * '/robots.txt' and needed no edit.
18
+ *
19
+ * The move from a route handler to the metadata route is what buys the caching
20
+ * below. Everything else about the response — the served path, the content type, the
21
+ * sandbox behaviour — is identical to what shipped before.
22
+ */
23
+
24
+ /**
25
+ * Cache the generated file and rebuild it at most once an hour, mirroring
26
+ * app/sitemap.ts. Crawlers get a fast, statically-served response while a change an
27
+ * operator saves in /cms/settings still takes effect without a redeploy.
28
+ *
29
+ * NextBlock does not enable Next.js Cache Components, so the route-segment
30
+ * `revalidate` config is the idiomatic caching control here. If `cacheComponents`
31
+ * were turned on, the equivalent would be a `'use cache'` body paired with
32
+ * `cacheLife('hours')` instead of this export.
33
+ */
34
+ export const revalidate = 3600;
35
+
36
+ /**
37
+ * The `site_settings` row the SEO screen writes, seeded by migration 30 and moved into
38
+ * the ADMIN-only write group by migration 31 — a WRITER could otherwise have PATCHed
39
+ * this row through PostgREST and de-indexed the whole site, since RLS, not the server
40
+ * action, is the boundary that actually holds.
41
+ */
42
+ const ROBOTS_SETTINGS_KEY = 'seo_robots_settings';
43
+
44
+ /**
45
+ * Reads the stored robots configuration, falling back to the permissive defaults on
46
+ * any failure whatsoever.
47
+ *
48
+ * The anon client is the right one here, and deliberately so: `seo_robots_settings`
49
+ * is a non-secret key and `site_settings`' read policy is already public for
50
+ * non-secret keys, so nothing on this path needs the service role. Handing a
51
+ * service-role client to a route that anonymous crawlers hit would be a needless
52
+ * escalation.
53
+ *
54
+ * That read has to stay anonymous, which is why migration 31 tightened only the
55
+ * INSERT/UPDATE/DELETE policies and left `site_settings_read_policy` alone. Adding
56
+ * this key to the read policy's sensitive array would not fail loudly — the query
57
+ * below would simply return no row, every crawler would be served the permissive
58
+ * defaults, and the operator's configuration would stop applying without a single
59
+ * error anywhere.
60
+ *
61
+ * The failure handling matters more than it looks. A crawler that receives a 500 for
62
+ * robots.txt may treat the entire site as disallowed until it next succeeds, so an
63
+ * unreachable database — or a `cms_redirects`-era install that has not yet run
64
+ * `npm run db:migrate`, where this settings row does not exist — must produce a
65
+ * valid, permissive file rather than an error. `normalizeRobotsSettings` handles the
66
+ * other half of that: whatever jsonb hands back, including null, a string or a
67
+ * half-migrated object, becomes a complete `RobotsSettings`.
68
+ */
69
+ async function loadRobotsSettings(): Promise<RobotsSettings> {
70
+ try {
71
+ const supabase = getSsgSupabaseClient();
72
+ const { data, error } = await supabase
73
+ .from('site_settings')
74
+ .select('value')
75
+ .eq('key', ROBOTS_SETTINGS_KEY)
76
+ .maybeSingle();
77
+
78
+ if (error) {
79
+ console.error('robots.txt: failed to read the robots settings; serving defaults.', error);
80
+ return normalizeRobotsSettings(undefined);
81
+ }
82
+
83
+ // A missing row is not an error — it is a site whose operator has never opened
84
+ // the SEO screen — and the defaults are exactly what that site should serve.
85
+ return normalizeRobotsSettings(data?.value);
86
+ } catch (error) {
87
+ console.error('robots.txt: robots settings lookup threw; serving defaults.', error);
88
+ return normalizeRobotsSettings(undefined);
89
+ }
90
+ }
91
+
92
+ export default async function robots(): Promise<MetadataRoute.Robots> {
93
+ const isSandbox = process.env.NEXT_PUBLIC_IS_SANDBOX === 'true';
94
+
95
+ // The sandbox answer ignores every stored setting, so there is nothing to read.
96
+ // Skipping the query keeps a disposable deployment's robots.txt working even when
97
+ // its database is asleep or being reset by the cron job. The reasoning for why the
98
+ // sandbox ALLOWS crawling rather than disallowing it lives on SANDBOX_USER_AGENT_RULE
99
+ // in lib/seo/robots-txt.ts — it is the counter-intuitive part of this feature and
100
+ // that is where it is written down in full.
101
+ if (isSandbox) {
102
+ return buildRobotsMetadata(normalizeRobotsSettings(undefined), {
103
+ isSandbox: true,
104
+ sitemapUrl: null,
105
+ });
106
+ }
107
+
108
+ // Explicit NEXT_PUBLIC_URL → Vercel production URL → local-dev fallback.
109
+ const siteUrl = resolveSiteUrl();
110
+
111
+ if (!hasResolvedSiteUrl()) {
112
+ console.warn(
113
+ 'Warning: no site URL is set for robots.txt (NEXT_PUBLIC_URL / Vercel production URL). Defaulting to http://localhost:3000. Set NEXT_PUBLIC_URL for production.'
114
+ );
115
+ }
116
+
117
+ const settings = await loadRobotsSettings();
118
+
119
+ return buildRobotsMetadata(settings, {
120
+ isSandbox: false,
121
+ sitemapUrl: `${siteUrl}/sitemap.xml`,
122
+ });
123
+ }