create-nextblock 0.2.77 → 0.8.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 (413) hide show
  1. package/bin/create-nextblock.js +740 -459
  2. package/package.json +1 -2
  3. package/scripts/sync-template.js +18 -1
  4. package/templates/nextblock-template/.browserslistrc +11 -0
  5. package/templates/nextblock-template/.swcrc +30 -30
  6. package/templates/nextblock-template/README.md +23 -114
  7. package/templates/nextblock-template/app/(auth-pages)/post-sign-in/page.tsx +27 -28
  8. package/templates/nextblock-template/app/(auth-pages)/sign-in/page.tsx +50 -25
  9. package/templates/nextblock-template/app/(auth-pages)/sign-up/page.tsx +111 -56
  10. package/templates/nextblock-template/app/(auth-pages)/two-factor/actions.ts +91 -0
  11. package/templates/nextblock-template/app/(auth-pages)/two-factor/components/TwoFactorForm.tsx +118 -0
  12. package/templates/nextblock-template/app/(auth-pages)/two-factor/page.tsx +51 -0
  13. package/templates/nextblock-template/app/.well-known/ucp/route.ts +16 -0
  14. package/templates/nextblock-template/app/[slug]/PageClientContent.tsx +48 -28
  15. package/templates/nextblock-template/app/[slug]/page.tsx +63 -6
  16. package/templates/nextblock-template/app/[slug]/page.utils.ts +374 -157
  17. package/templates/nextblock-template/app/[slug]/pageClientActions.ts +7 -0
  18. package/templates/nextblock-template/app/actions/consent.ts +57 -0
  19. package/templates/nextblock-template/app/actions/formActions.ts +130 -11
  20. package/templates/nextblock-template/app/actions/languageActions.ts +31 -30
  21. package/templates/nextblock-template/app/actions/package-actions.ts +183 -0
  22. package/templates/nextblock-template/app/actions/postActions.ts +146 -48
  23. package/templates/nextblock-template/app/actions/twoFactorEmail.ts +21 -0
  24. package/templates/nextblock-template/app/actions/visualEditingActions.test.ts +179 -0
  25. package/templates/nextblock-template/app/actions/visualEditingActions.ts +345 -0
  26. package/templates/nextblock-template/app/actions.ts +67 -12
  27. package/templates/nextblock-template/app/api/ai/cortex/build-widget/route.ts +153 -0
  28. package/templates/nextblock-template/app/api/ai/generate-blocks/route.ts +96 -0
  29. package/templates/nextblock-template/app/api/ai/global-agent/route.ts +965 -0
  30. package/templates/nextblock-template/app/api/checkout/freemius/sync/route.ts +29 -0
  31. package/templates/nextblock-template/app/api/checkout/route.ts +146 -0
  32. package/templates/nextblock-template/app/api/cms/full-backup/export/route.ts +33 -0
  33. package/templates/nextblock-template/app/api/cms/full-backup/restore/route.ts +63 -0
  34. package/templates/nextblock-template/app/api/cron/reset-sandbox/route.ts +3413 -17
  35. package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +7830 -0
  36. package/templates/nextblock-template/app/api/cron/sync-currencies/route.ts +35 -0
  37. package/templates/nextblock-template/app/api/custom-blocks/db-relations/route.ts +92 -0
  38. package/templates/nextblock-template/app/api/custom-blocks/editor-definitions/route.ts +43 -0
  39. package/templates/nextblock-template/app/api/draft/disable/route.ts +25 -0
  40. package/templates/nextblock-template/app/api/draft/route.ts +93 -0
  41. package/templates/nextblock-template/app/api/draft/start/route.ts +77 -0
  42. package/templates/nextblock-template/app/api/media/library/route.ts +65 -0
  43. package/templates/nextblock-template/app/api/media/r2-presigned/route.ts +53 -0
  44. package/templates/nextblock-template/app/api/media/record/route.ts +160 -0
  45. package/templates/nextblock-template/app/api/search/route.ts +43 -0
  46. package/templates/nextblock-template/app/api/visual-editing/block-draft/route.ts +47 -0
  47. package/templates/nextblock-template/app/api/visual-editing/product-draft/route.ts +47 -0
  48. package/templates/nextblock-template/app/api/webhooks/freemius/route.ts +34 -0
  49. package/templates/nextblock-template/app/api/webhooks/stripe/route.ts +27 -0
  50. package/templates/nextblock-template/app/article/[slug]/PostClientContent.tsx +392 -128
  51. package/templates/nextblock-template/app/article/[slug]/page.tsx +179 -127
  52. package/templates/nextblock-template/app/article/[slug]/page.utils.ts +262 -77
  53. package/templates/nextblock-template/app/auth/callback/route.ts +31 -58
  54. package/templates/nextblock-template/app/cart/page.tsx +7 -0
  55. package/templates/nextblock-template/app/checkout/UcpCartHydrator.tsx +20 -0
  56. package/templates/nextblock-template/app/checkout/page.tsx +52 -0
  57. package/templates/nextblock-template/app/checkout/success/actions.ts +136 -0
  58. package/templates/nextblock-template/app/checkout/success/page.tsx +186 -0
  59. package/templates/nextblock-template/app/cms/CmsClientLayout.tsx +163 -33
  60. package/templates/nextblock-template/app/cms/blocks/actions.ts +424 -235
  61. package/templates/nextblock-template/app/cms/blocks/components/BackgroundSelector.tsx +212 -151
  62. package/templates/nextblock-template/app/cms/blocks/components/BlockEditorArea.tsx +41 -20
  63. package/templates/nextblock-template/app/cms/blocks/components/BlockEditorModal.tsx +152 -19
  64. package/templates/nextblock-template/app/cms/blocks/components/BlockTypeCard.tsx +25 -17
  65. package/templates/nextblock-template/app/cms/blocks/components/BlockTypeSelector.tsx +200 -18
  66. package/templates/nextblock-template/app/cms/blocks/components/ColumnEditor.tsx +33 -16
  67. package/templates/nextblock-template/app/cms/blocks/components/CustomBlockEditorPreview.tsx +160 -0
  68. package/templates/nextblock-template/app/cms/blocks/components/EditableBlock.tsx +37 -18
  69. package/templates/nextblock-template/app/cms/blocks/components/MediaLibraryModal.tsx +149 -67
  70. package/templates/nextblock-template/app/cms/blocks/components/SectionConfigPanel.tsx +108 -31
  71. package/templates/nextblock-template/app/cms/blocks/editors/DynamicCustomBlockEditor.tsx +167 -0
  72. package/templates/nextblock-template/app/cms/blocks/editors/FeaturedProductBlockEditor.tsx +31 -0
  73. package/templates/nextblock-template/app/cms/blocks/editors/FormBlockEditor.tsx +2 -2
  74. package/templates/nextblock-template/app/cms/blocks/editors/HeadingBlockEditor.tsx +1 -1
  75. package/templates/nextblock-template/app/cms/blocks/editors/ImageBlockEditor.tsx +29 -29
  76. package/templates/nextblock-template/app/cms/blocks/editors/PostsGridBlockEditor.tsx +14 -18
  77. package/templates/nextblock-template/app/cms/blocks/editors/ProductGridBlockEditor.tsx +41 -0
  78. package/templates/nextblock-template/app/cms/blocks/editors/SectionBlockEditor.tsx +318 -118
  79. package/templates/nextblock-template/app/cms/blocks/editors/TextBlockEditor.tsx +98 -21
  80. package/templates/nextblock-template/app/cms/blocks/editors/VideoEmbedBlockEditor.tsx +1 -1
  81. package/templates/nextblock-template/app/cms/components/ContentLanguageSwitcher.tsx +27 -9
  82. package/templates/nextblock-template/app/cms/components/CopyContentFromLanguage.tsx +1 -1
  83. package/templates/nextblock-template/app/cms/components/CortexAiActiveContext.tsx +23 -0
  84. package/templates/nextblock-template/app/cms/components/CortexAiPageContext.tsx +58 -0
  85. package/templates/nextblock-template/app/cms/components/CortexGlobalAgentChat.tsx +1507 -0
  86. package/templates/nextblock-template/app/cms/components/DraftStatusActions.tsx +145 -0
  87. package/templates/nextblock-template/app/cms/components/FeatureImageField.tsx +244 -0
  88. package/templates/nextblock-template/app/cms/components/FeedbackModal.tsx +38 -24
  89. package/templates/nextblock-template/app/cms/coupons/[id]/edit/page.tsx +16 -0
  90. package/templates/nextblock-template/app/cms/coupons/page.tsx +16 -0
  91. package/templates/nextblock-template/app/cms/custom-blocks/[id]/edit/page.tsx +66 -0
  92. package/templates/nextblock-template/app/cms/custom-blocks/actions.ts +519 -0
  93. package/templates/nextblock-template/app/cms/custom-blocks/components/BlockComposer.tsx +1522 -0
  94. package/templates/nextblock-template/app/cms/custom-blocks/components/BlocksLibraryTransferControls.tsx +256 -0
  95. package/templates/nextblock-template/app/cms/custom-blocks/components/DBRelationSelect.tsx +384 -0
  96. package/templates/nextblock-template/app/cms/custom-blocks/components/ImageR2Picker.tsx +221 -0
  97. package/templates/nextblock-template/app/cms/custom-blocks/new/page.tsx +12 -0
  98. package/templates/nextblock-template/app/cms/custom-blocks/page.tsx +438 -0
  99. package/templates/nextblock-template/app/cms/dashboard/actions.ts +228 -98
  100. package/templates/nextblock-template/app/cms/dashboard/components/DashboardComponents.tsx +200 -0
  101. package/templates/nextblock-template/app/cms/dashboard/page.tsx +191 -151
  102. package/templates/nextblock-template/app/cms/import-export/ContentTransferControls.tsx +391 -0
  103. package/templates/nextblock-template/app/cms/import-export/actions.ts +226 -0
  104. package/templates/nextblock-template/app/cms/layout.tsx +29 -10
  105. package/templates/nextblock-template/app/cms/media/UploadFolderContext.tsx +22 -22
  106. package/templates/nextblock-template/app/cms/media/actions.ts +45 -124
  107. package/templates/nextblock-template/app/cms/media/components/DeleteMediaButtonClient.tsx +1 -1
  108. package/templates/nextblock-template/app/cms/media/components/MediaEditForm.tsx +26 -26
  109. package/templates/nextblock-template/app/cms/media/components/MediaGridClient.tsx +69 -64
  110. package/templates/nextblock-template/app/cms/media/components/MediaPickerDialog.tsx +227 -158
  111. package/templates/nextblock-template/app/cms/media/components/MediaUploadForm.tsx +101 -89
  112. package/templates/nextblock-template/app/cms/media/page.tsx +1 -1
  113. package/templates/nextblock-template/app/cms/navigation/components/NavigationItemForm.tsx +2 -2
  114. package/templates/nextblock-template/app/cms/orders/[id]/MarkPaidButton.tsx +44 -0
  115. package/templates/nextblock-template/app/cms/orders/[id]/page.tsx +16 -0
  116. package/templates/nextblock-template/app/cms/orders/actions.ts +201 -0
  117. package/templates/nextblock-template/app/cms/orders/page.tsx +20 -0
  118. package/templates/nextblock-template/app/cms/orders/types.ts +20 -0
  119. package/templates/nextblock-template/app/cms/pages/[id]/edit/EditPageClient.tsx +156 -121
  120. package/templates/nextblock-template/app/cms/pages/[id]/edit/page.tsx +79 -26
  121. package/templates/nextblock-template/app/cms/pages/actions.ts +54 -38
  122. package/templates/nextblock-template/app/cms/pages/components/DeletePageButtonClient.tsx +1 -1
  123. package/templates/nextblock-template/app/cms/pages/components/PageForm.tsx +267 -116
  124. package/templates/nextblock-template/app/cms/pages/page.tsx +25 -18
  125. package/templates/nextblock-template/app/cms/payments/page.tsx +16 -0
  126. package/templates/nextblock-template/app/cms/posts/[id]/edit/page.tsx +132 -90
  127. package/templates/nextblock-template/app/cms/posts/actions.ts +71 -72
  128. package/templates/nextblock-template/app/cms/posts/components/DeletePostButtonClient.tsx +1 -1
  129. package/templates/nextblock-template/app/cms/posts/components/PostForm.tsx +256 -245
  130. package/templates/nextblock-template/app/cms/posts/new/page.tsx +1 -1
  131. package/templates/nextblock-template/app/cms/posts/page.tsx +20 -13
  132. package/templates/nextblock-template/app/cms/products/ClientNotionEditor.tsx +16 -0
  133. package/templates/nextblock-template/app/cms/products/ProductFormClientShell.tsx +56 -0
  134. package/templates/nextblock-template/app/cms/products/[id]/edit/page.tsx +292 -0
  135. package/templates/nextblock-template/app/cms/products/attributes/page.tsx +12 -0
  136. package/templates/nextblock-template/app/cms/products/categories/page.tsx +12 -0
  137. package/templates/nextblock-template/app/cms/products/inventory/page.tsx +13 -0
  138. package/templates/nextblock-template/app/cms/products/new/page.tsx +143 -0
  139. package/templates/nextblock-template/app/cms/products/page.tsx +42 -0
  140. package/templates/nextblock-template/app/cms/products/productFormData.ts +133 -0
  141. package/templates/nextblock-template/app/cms/products/settings/page.tsx +5 -0
  142. package/templates/nextblock-template/app/cms/promotions/PromotionsWorkspace.tsx +456 -0
  143. package/templates/nextblock-template/app/cms/promotions/actions.ts +115 -0
  144. package/templates/nextblock-template/app/cms/promotions/page.tsx +31 -0
  145. package/templates/nextblock-template/app/cms/revisions/RevisionHistoryButton.tsx +2 -2
  146. package/templates/nextblock-template/app/cms/revisions/actions.ts +285 -285
  147. package/templates/nextblock-template/app/cms/revisions/service.ts +19 -16
  148. package/templates/nextblock-template/app/cms/revisions/utils.ts +8 -3
  149. package/templates/nextblock-template/app/cms/settings/backup-restore/BackupRestoreWorkspace.tsx +1004 -0
  150. package/templates/nextblock-template/app/cms/settings/backup-restore/page.tsx +29 -0
  151. package/templates/nextblock-template/app/cms/settings/bot-protection/actions.ts +93 -0
  152. package/templates/nextblock-template/app/cms/settings/bot-protection/components/BotProtectionForm.tsx +129 -0
  153. package/templates/nextblock-template/app/cms/settings/bot-protection/page.tsx +24 -0
  154. package/templates/nextblock-template/app/cms/settings/copyright/actions.ts +1 -1
  155. package/templates/nextblock-template/app/cms/settings/copyright/components/CopyrightForm.tsx +2 -2
  156. package/templates/nextblock-template/app/cms/settings/copyright/page.tsx +1 -1
  157. package/templates/nextblock-template/app/cms/settings/cortex-ai/SandboxCortexAiSettingsClient.tsx +496 -0
  158. package/templates/nextblock-template/app/cms/settings/cortex-ai/StoredCortexAiSettingsClient.tsx +410 -0
  159. package/templates/nextblock-template/app/cms/settings/cortex-ai/actions.ts +248 -0
  160. package/templates/nextblock-template/app/cms/settings/cortex-ai/page.tsx +80 -0
  161. package/templates/nextblock-template/app/cms/settings/currencies/actions.ts +331 -0
  162. package/templates/nextblock-template/app/cms/settings/currencies/page.tsx +494 -0
  163. package/templates/nextblock-template/app/cms/settings/extra-translations/ExtraTranslationsWorkspace.tsx +767 -0
  164. package/templates/nextblock-template/app/cms/settings/extra-translations/actions.ts +203 -44
  165. package/templates/nextblock-template/app/cms/settings/extra-translations/page.tsx +93 -242
  166. package/templates/nextblock-template/app/cms/settings/global-css/actions.ts +65 -0
  167. package/templates/nextblock-template/app/cms/settings/global-css/components/GlobalCssForm.tsx +46 -0
  168. package/templates/nextblock-template/app/cms/settings/global-css/page.tsx +24 -0
  169. package/templates/nextblock-template/app/cms/settings/languages/components/DeleteLanguageButton.tsx +1 -1
  170. package/templates/nextblock-template/app/cms/settings/languages/components/LanguageForm.tsx +2 -2
  171. package/templates/nextblock-template/app/cms/settings/languages/page.tsx +1 -1
  172. package/templates/nextblock-template/app/cms/settings/logos/[id]/edit/page.tsx +7 -7
  173. package/templates/nextblock-template/app/cms/settings/logos/actions.ts +82 -6
  174. package/templates/nextblock-template/app/cms/settings/logos/components/BrandingSettingsForm.tsx +339 -0
  175. package/templates/nextblock-template/app/cms/settings/logos/components/DeleteLogoButton.tsx +21 -18
  176. package/templates/nextblock-template/app/cms/settings/logos/components/LogoForm.tsx +20 -16
  177. package/templates/nextblock-template/app/cms/settings/logos/components/SiteSeoSettingsForm.tsx +133 -0
  178. package/templates/nextblock-template/app/cms/settings/logos/new/page.tsx +8 -8
  179. package/templates/nextblock-template/app/cms/settings/logos/page.tsx +120 -82
  180. package/templates/nextblock-template/app/cms/settings/logos/types.ts +8 -8
  181. package/templates/nextblock-template/app/cms/settings/packages/activation-form.tsx +84 -0
  182. package/templates/nextblock-template/app/cms/settings/packages/package-card.tsx +122 -0
  183. package/templates/nextblock-template/app/cms/settings/packages/page.tsx +49 -0
  184. package/templates/nextblock-template/app/cms/settings/privacy/actions.ts +53 -0
  185. package/templates/nextblock-template/app/cms/settings/privacy/components/PrivacyForm.tsx +196 -0
  186. package/templates/nextblock-template/app/cms/settings/privacy/page.tsx +26 -0
  187. package/templates/nextblock-template/app/cms/settings/security/actions.ts +251 -0
  188. package/templates/nextblock-template/app/cms/settings/security/components/SecurityPanel.tsx +453 -0
  189. package/templates/nextblock-template/app/cms/settings/security/page.tsx +13 -0
  190. package/templates/nextblock-template/app/cms/settings/taxes/page.tsx +21 -0
  191. package/templates/nextblock-template/app/cms/shipping/page.tsx +20 -0
  192. package/templates/nextblock-template/app/cms/users/[id]/edit/page.tsx +28 -23
  193. package/templates/nextblock-template/app/cms/users/actions.ts +105 -40
  194. package/templates/nextblock-template/app/cms/users/components/DeleteUserButton.tsx +1 -1
  195. package/templates/nextblock-template/app/cms/users/components/UserForm.tsx +65 -152
  196. package/templates/nextblock-template/app/cms/users/page.tsx +15 -10
  197. package/templates/nextblock-template/app/globals.css +9 -0
  198. package/templates/nextblock-template/app/layout.tsx +372 -116
  199. package/templates/nextblock-template/app/lib/seo.test.ts +52 -0
  200. package/templates/nextblock-template/app/lib/seo.ts +279 -0
  201. package/templates/nextblock-template/app/lib/site-settings.ts +87 -0
  202. package/templates/nextblock-template/app/lib/sitemap-utils.ts +224 -39
  203. package/templates/nextblock-template/app/lib/ucp/protocol.ts +190 -0
  204. package/templates/nextblock-template/app/lib/ucp/server.test.ts +56 -0
  205. package/templates/nextblock-template/app/lib/ucp/server.ts +1914 -0
  206. package/templates/nextblock-template/app/page.tsx +165 -73
  207. package/templates/nextblock-template/app/product/[slug]/page.tsx +433 -0
  208. package/templates/nextblock-template/app/profile/ProfileAccountSidebar.tsx +73 -0
  209. package/templates/nextblock-template/app/profile/ProfilePageHeader.tsx +16 -0
  210. package/templates/nextblock-template/app/profile/ProfilePageMissingState.tsx +9 -0
  211. package/templates/nextblock-template/app/profile/account-data.ts +37 -0
  212. package/templates/nextblock-template/app/profile/account-links.ts +22 -0
  213. package/templates/nextblock-template/app/profile/account-types.ts +11 -0
  214. package/templates/nextblock-template/app/profile/orders/CustomerOrdersPageClient.tsx +124 -0
  215. package/templates/nextblock-template/app/profile/orders/[id]/CustomerOrderDetailPageClient.tsx +79 -0
  216. package/templates/nextblock-template/app/profile/orders/[id]/page.tsx +32 -0
  217. package/templates/nextblock-template/app/profile/orders/page.tsx +19 -0
  218. package/templates/nextblock-template/app/profile/page.tsx +51 -0
  219. package/templates/nextblock-template/app/profile/password/PasswordSettingsPageClient.tsx +128 -0
  220. package/templates/nextblock-template/app/profile/password/actions.ts +59 -0
  221. package/templates/nextblock-template/app/profile/password/page.tsx +27 -0
  222. package/templates/nextblock-template/app/providers.tsx +55 -17
  223. package/templates/nextblock-template/app/robots.txt/route.ts +11 -1
  224. package/templates/nextblock-template/app/sitemap.ts +128 -0
  225. package/templates/nextblock-template/app/ucp/v1/carts/[id]/cancel/route.ts +38 -0
  226. package/templates/nextblock-template/app/ucp/v1/carts/[id]/route.ts +68 -0
  227. package/templates/nextblock-template/app/ucp/v1/carts/route.ts +35 -0
  228. package/templates/nextblock-template/app/ucp/v1/catalog/lookup/route.ts +35 -0
  229. package/templates/nextblock-template/app/ucp/v1/catalog/product/route.ts +35 -0
  230. package/templates/nextblock-template/app/ucp/v1/catalog/search/route.ts +34 -0
  231. package/templates/nextblock-template/components/AppShell.tsx +154 -0
  232. package/templates/nextblock-template/components/BlockRenderer.tsx +210 -64
  233. package/templates/nextblock-template/components/CartDrawerLoader.tsx +7 -0
  234. package/templates/nextblock-template/components/CartTranslator.tsx +210 -0
  235. package/templates/nextblock-template/components/CurrentContentSetter.tsx +25 -0
  236. package/templates/nextblock-template/components/DeferredCartDrawer.tsx +23 -0
  237. package/templates/nextblock-template/components/DeferredCartTranslator.tsx +51 -0
  238. package/templates/nextblock-template/components/DeferredGlobalSearch.tsx +68 -0
  239. package/templates/nextblock-template/components/DeferredGoogleTagManager.tsx +70 -0
  240. package/templates/nextblock-template/components/DeferredSpeedInsights.tsx +69 -0
  241. package/templates/nextblock-template/components/FeatureImageHero.tsx +47 -0
  242. package/templates/nextblock-template/components/GitHubLoginButton.tsx +36 -0
  243. package/templates/nextblock-template/components/GlobalSearch.tsx +557 -0
  244. package/templates/nextblock-template/components/Header.tsx +49 -41
  245. package/templates/nextblock-template/components/LanguageSwitcher.tsx +55 -32
  246. package/templates/nextblock-template/components/ResponsiveNav.tsx +138 -43
  247. package/templates/nextblock-template/components/blocks/PostCardSkeleton.tsx +12 -8
  248. package/templates/nextblock-template/components/blocks/PostsGridBlock.tsx +12 -55
  249. package/templates/nextblock-template/components/blocks/PostsGridClient.tsx +42 -37
  250. package/templates/nextblock-template/components/blocks/TestimonialBlock.tsx +6 -2
  251. package/templates/nextblock-template/components/blocks/ecommerceRendererLoaders.ts +23 -0
  252. package/templates/nextblock-template/components/blocks/publicRendererLoaders.ts +25 -0
  253. package/templates/nextblock-template/components/blocks/renderers/ButtonBlockRenderer.tsx +92 -84
  254. package/templates/nextblock-template/components/blocks/renderers/CartBlockRenderer.tsx +17 -0
  255. package/templates/nextblock-template/components/blocks/renderers/CheckoutBlockRenderer.tsx +19 -0
  256. package/templates/nextblock-template/components/blocks/renderers/ClientTextBlockRenderer.tsx +262 -8
  257. package/templates/nextblock-template/components/blocks/renderers/FeaturedProductBlockRenderer.tsx +22 -0
  258. package/templates/nextblock-template/components/blocks/renderers/FormBlockRenderer.tsx +320 -37
  259. package/templates/nextblock-template/components/blocks/renderers/HeadingBlockRenderer.tsx +11 -8
  260. package/templates/nextblock-template/components/blocks/renderers/ImageBlockRenderer.tsx +12 -3
  261. package/templates/nextblock-template/components/blocks/renderers/PostsGridBlockRenderer.tsx +18 -13
  262. package/templates/nextblock-template/components/blocks/renderers/ProductDetailsBlockRenderer.tsx +90 -0
  263. package/templates/nextblock-template/components/blocks/renderers/ProductGridBlockRenderer.tsx +31 -0
  264. package/templates/nextblock-template/components/blocks/renderers/SectionBlockRenderer.tsx +424 -55
  265. package/templates/nextblock-template/components/blocks/renderers/SectionSlider.tsx +137 -0
  266. package/templates/nextblock-template/components/blocks/renderers/TestimonialBlockRenderer.tsx +57 -0
  267. package/templates/nextblock-template/components/blocks/renderers/TextBlockRenderer.tsx +37 -22
  268. package/templates/nextblock-template/components/blocks/renderers/VideoEmbedBlockRenderer.tsx +23 -15
  269. package/templates/nextblock-template/components/blocks/renderers/inline/AlertWidgetRenderer.tsx +1 -3
  270. package/templates/nextblock-template/components/blocks/renderers/inline/CtaWidgetRenderer.tsx +1 -3
  271. package/templates/nextblock-template/components/blocks/types.ts +7 -6
  272. package/templates/nextblock-template/components/env-var-warning.tsx +3 -3
  273. package/templates/nextblock-template/components/form-message.tsx +32 -26
  274. package/templates/nextblock-template/components/header-auth.tsx +69 -17
  275. package/templates/nextblock-template/components/privacy/ConsentBanner.tsx +127 -0
  276. package/templates/nextblock-template/components/privacy/ConsentGatedAnalytics.tsx +59 -0
  277. package/templates/nextblock-template/components/renderers/CachedDynamicLayoutEngine.tsx +28 -0
  278. package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.test.tsx +166 -0
  279. package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.tsx +464 -0
  280. package/templates/nextblock-template/components/theme-switcher.tsx +8 -8
  281. package/templates/nextblock-template/components/visual-editing/DeferredVisualEditing.tsx +21 -0
  282. package/templates/nextblock-template/components/visual-editing/NextblockVisualEditing.tsx +1172 -0
  283. package/templates/nextblock-template/context/AuthContext.tsx +23 -90
  284. package/templates/nextblock-template/context/CurrentContentContext.tsx +10 -4
  285. package/templates/nextblock-template/context/LanguageContext.tsx +16 -16
  286. package/templates/nextblock-template/context/language-rest-client.ts +31 -0
  287. package/templates/nextblock-template/docs/01-PROJECT-OVERVIEW.md +94 -0
  288. package/templates/nextblock-template/docs/02-ECOMMERCE-CAPABILITIES.md +364 -0
  289. package/templates/nextblock-template/docs/03-CMS-AND-EDITOR.md +202 -0
  290. package/templates/nextblock-template/docs/04-DATABASE-AND-AUTH.md +252 -0
  291. package/templates/nextblock-template/docs/05-DEVELOPER-GUIDE.md +238 -0
  292. package/templates/nextblock-template/docs/06-CLI-AND-SCAFFOLDING.md +125 -0
  293. package/templates/nextblock-template/docs/07-BLOCK-SDK-AND-EXTENSIBILITY.md +146 -0
  294. package/templates/nextblock-template/docs/08-NEXTBLOCK-CORTEX-AI-ARCHITECTURE.md +1319 -0
  295. package/templates/nextblock-template/docs/09-LIVE-DRAFT-MODE.md +104 -0
  296. package/templates/nextblock-template/docs/10-CUSTOM-BLOCKS.md +222 -0
  297. package/templates/nextblock-template/docs/README.md +34 -0
  298. package/templates/nextblock-template/docs/TECHNICAL_SPECIFICATION.md +12507 -0
  299. package/templates/nextblock-template/hooks/use-hotkeys.ts +21 -14
  300. package/templates/nextblock-template/hooks/useGlobalSearch.ts +101 -0
  301. package/templates/nextblock-template/index.d.ts +2 -0
  302. package/templates/nextblock-template/lib/ai-block-generation.ts +339 -0
  303. package/templates/nextblock-template/lib/ai-client.ts +247 -0
  304. package/templates/nextblock-template/lib/ai-config.ts +81 -0
  305. package/templates/nextblock-template/lib/ai-cortex-widget-builder.ts +125 -0
  306. package/templates/nextblock-template/lib/ai-global-agent-custom-block-tools.ts +363 -0
  307. package/templates/nextblock-template/lib/ai-global-agent-db-tools.test.ts +405 -0
  308. package/templates/nextblock-template/lib/ai-global-agent-db-tools.ts +1228 -0
  309. package/templates/nextblock-template/lib/ai-global-agent-ecommerce.ts +5 -0
  310. package/templates/nextblock-template/lib/ai-global-agent-tools-stats.test.ts +223 -0
  311. package/templates/nextblock-template/lib/ai-global-agent-tools.test.ts +2183 -0
  312. package/templates/nextblock-template/lib/ai-global-agent-tools.ts +4807 -0
  313. package/templates/nextblock-template/lib/ai-key-crypto.test.ts +70 -0
  314. package/templates/nextblock-template/lib/ai-key-crypto.ts +132 -0
  315. package/templates/nextblock-template/lib/ai-model-catalog.test.ts +49 -0
  316. package/templates/nextblock-template/lib/ai-model-catalog.ts +41 -0
  317. package/templates/nextblock-template/lib/ai-model-registry.test.ts +231 -0
  318. package/templates/nextblock-template/lib/ai-model-registry.ts +522 -0
  319. package/templates/nextblock-template/lib/auth/cookies.ts +47 -0
  320. package/templates/nextblock-template/lib/auth/crypto.ts +42 -0
  321. package/templates/nextblock-template/lib/auth/trustedDevices.ts +92 -0
  322. package/templates/nextblock-template/lib/auth/twoFactor.ts +167 -0
  323. package/templates/nextblock-template/lib/auth-redirects.ts +46 -0
  324. package/templates/nextblock-template/lib/blocks/FeaturedProductBlock.tsx +94 -0
  325. package/templates/nextblock-template/lib/blocks/ProductGridBlock.tsx +137 -0
  326. package/templates/nextblock-template/lib/blocks/README.md +13 -670
  327. package/templates/nextblock-template/lib/blocks/blockRegistry.ts +138 -56
  328. package/templates/nextblock-template/lib/blocks/blockTypes.ts +18 -0
  329. package/templates/nextblock-template/lib/blocks/ecommerce-block-schemas.ts +31 -0
  330. package/templates/nextblock-template/lib/cms-transfer/csv.test.ts +77 -0
  331. package/templates/nextblock-template/lib/cms-transfer/csv.ts +399 -0
  332. package/templates/nextblock-template/lib/cms-transfer/server.ts +2243 -0
  333. package/templates/nextblock-template/lib/cms-transfer/types.ts +145 -0
  334. package/templates/nextblock-template/lib/cortex-widget-registry.test.ts +199 -0
  335. package/templates/nextblock-template/lib/cortex-widget-registry.ts +88 -0
  336. package/templates/nextblock-template/lib/cortex-widget-schema.test.tsx +237 -0
  337. package/templates/nextblock-template/lib/cortex-widget-schema.ts +393 -0
  338. package/templates/nextblock-template/lib/custom-block-definitions.ts +87 -0
  339. package/templates/nextblock-template/lib/custom-block-r2-upload-shared.ts +178 -0
  340. package/templates/nextblock-template/lib/custom-block-r2-upload.test.ts +140 -0
  341. package/templates/nextblock-template/lib/custom-block-r2-upload.ts +68 -0
  342. package/templates/nextblock-template/lib/custom-block-relation-registry.ts +256 -0
  343. package/templates/nextblock-template/lib/custom-block-relations.test.ts +227 -0
  344. package/templates/nextblock-template/lib/custom-block-relations.ts +279 -0
  345. package/templates/nextblock-template/lib/custom-block-safelist.ts +14 -0
  346. package/templates/nextblock-template/lib/editor/dynamic-extension-core.test.ts +172 -0
  347. package/templates/nextblock-template/lib/editor/dynamic-extension-core.ts +213 -0
  348. package/templates/nextblock-template/lib/editor/dynamic-extension-loader.ts +22 -0
  349. package/templates/nextblock-template/lib/editor/dynamic-extensions.tsx +193 -0
  350. package/templates/nextblock-template/lib/full-backup/manifest.test.ts +121 -0
  351. package/templates/nextblock-template/lib/full-backup/manifest.ts +206 -0
  352. package/templates/nextblock-template/lib/full-backup/server.ts +743 -0
  353. package/templates/nextblock-template/lib/media/resolveMediaUrl.ts +45 -0
  354. package/templates/nextblock-template/lib/posts/readTime.ts +60 -0
  355. package/templates/nextblock-template/lib/privacy/consent-client.ts +57 -0
  356. package/templates/nextblock-template/lib/privacy/settings.ts +103 -0
  357. package/templates/nextblock-template/lib/privacy/types.ts +67 -0
  358. package/templates/nextblock-template/lib/promotions/server.test.ts +74 -0
  359. package/templates/nextblock-template/lib/promotions/server.ts +741 -0
  360. package/templates/nextblock-template/lib/resolve-block-relations.test.ts +142 -0
  361. package/templates/nextblock-template/lib/resolve-block-relations.ts +255 -0
  362. package/templates/nextblock-template/lib/search/server.ts +585 -0
  363. package/templates/nextblock-template/lib/search/types.ts +27 -0
  364. package/templates/nextblock-template/lib/visual-editing/draft-content.test.ts +105 -0
  365. package/templates/nextblock-template/lib/visual-editing/draft-content.ts +380 -0
  366. package/templates/nextblock-template/lib/visual-editing/draft-route.test.ts +42 -0
  367. package/templates/nextblock-template/lib/visual-editing/draft-route.ts +82 -0
  368. package/templates/nextblock-template/lib/visual-editing/edit-info.test.ts +143 -0
  369. package/templates/nextblock-template/lib/visual-editing/edit-info.ts +94 -0
  370. package/templates/nextblock-template/lib/visual-editing/mutations.ts +190 -0
  371. package/templates/nextblock-template/lib/visual-editing/product-drafts.test.ts +81 -0
  372. package/templates/nextblock-template/lib/visual-editing/product-drafts.ts +511 -0
  373. package/templates/nextblock-template/lib/visual-editing/types.ts +122 -0
  374. package/templates/nextblock-template/lib/zod-config.ts +5 -0
  375. package/templates/nextblock-template/next.config.js +190 -66
  376. package/templates/nextblock-template/package.json +34 -30
  377. package/templates/nextblock-template/proxy.ts +435 -253
  378. package/templates/nextblock-template/public/images/NBcover.webp +0 -0
  379. package/templates/nextblock-template/public/images/cap.webp +0 -0
  380. package/templates/nextblock-template/public/images/commerce-plan.webp +0 -0
  381. package/templates/nextblock-template/public/images/commerce-square.webp +0 -0
  382. package/templates/nextblock-template/public/images/commerce-wide.webp +0 -0
  383. package/templates/nextblock-template/public/images/cortex-ai-square.webp +0 -0
  384. package/templates/nextblock-template/public/images/cortex-ai.webp +0 -0
  385. package/templates/nextblock-template/public/images/extensibility.webp +0 -0
  386. package/templates/nextblock-template/public/images/goals.webp +0 -0
  387. package/templates/nextblock-template/public/images/included.webp +0 -0
  388. package/templates/nextblock-template/public/images/nx-graph.webp +0 -0
  389. package/templates/nextblock-template/public/images/pants.webp +0 -0
  390. package/templates/nextblock-template/public/images/t-shirt.webp +0 -0
  391. package/templates/nextblock-template/scripts/validate-editor-block-schema.ts +112 -0
  392. package/templates/nextblock-template/scripts/verify-cortex-ai-build-widget.tsx +100 -0
  393. package/templates/nextblock-template/scripts/verify-cortex-ai-generate-blocks.ts +62 -0
  394. package/templates/nextblock-template/scripts/verify-cortex-ai-global-tools.ts +537 -0
  395. package/templates/nextblock-template/scripts/verify-cortex-ai-routing.ts +58 -0
  396. package/templates/nextblock-template/scripts/verify-custom-block-definitions.ts +188 -0
  397. package/templates/nextblock-template/scripts/verify-dynamic-custom-block-extensions.ts +123 -0
  398. package/templates/nextblock-template/scripts/verify-dynamic-layout-engine.tsx +133 -0
  399. package/templates/nextblock-template/scripts/verify-milestone-2-custom-blocks.ts +65 -0
  400. package/templates/nextblock-template/tailwind.config.js +1 -0
  401. package/templates/nextblock-template/tools/configure-supabase-auth.js +282 -0
  402. package/templates/nextblock-template/tools/deploy-supabase.js +69 -71
  403. package/templates/nextblock-template/tsconfig.json +52 -66
  404. package/templates/nextblock-template/tsconfig.tsbuildinfo +1 -1
  405. package/templates/nextblock-template/types/jsdom.d.ts +6 -0
  406. package/templates/nextblock-template/app/force-styles.tsx +0 -31
  407. package/templates/nextblock-template/app/sitemap.xml/route.ts +0 -63
  408. package/templates/nextblock-template/components/blocks/renderers/HeroBlockRenderer.tsx +0 -273
  409. package/templates/nextblock-template/docs/How to Create a Custom Block.md +0 -149
  410. package/templates/nextblock-template/docs/cms-application-overview.md +0 -56
  411. package/templates/nextblock-template/docs/cms-architecture-overview.md +0 -73
  412. package/templates/nextblock-template/docs/files-structure.md +0 -426
  413. package/templates/nextblock-template/docs/tiptap-bundle-optimization-summary.md +0 -174
@@ -0,0 +1,364 @@
1
+ # 02 Ecommerce Capabilities
2
+
3
+ ## Scope and Source of Truth
4
+
5
+ The commerce feature set is implemented across:
6
+
7
+ - `libs/ecommerce/src/lib/*`
8
+ - `libs/db/src/supabase/migrations/00000000000003` through `00000000000006`
9
+ - `apps/nextblock/app/api/checkout/route.ts`
10
+ - `apps/nextblock/app/api/webhooks/*`
11
+ - `apps/nextblock/app/cms/products`, `orders`, `shipping`, `payments`, and
12
+ `settings/taxes`
13
+
14
+ In workspace code, the developer-facing import paths are:
15
+
16
+ - `@nextblock-cms/ecommerce`
17
+ - `@nextblock-cms/ecommerce/server`
18
+ - `@nextblock-cms/ecommerce/actions`
19
+
20
+ One packaging discrepancy exists today: `libs/ecommerce/package.json` is still
21
+ named `@nextblock-cms/ecom`, while the workspace and CLI activation flow expose
22
+ the package through the `@nextblock-cms/ecommerce` alias.
23
+
24
+ ## Commerce Data Model
25
+
26
+ The commerce schema spans:
27
+
28
+ - Catalog: `products`, `product_media`, `product_attributes`,
29
+ `product_attribute_terms`, `product_variants`,
30
+ `variant_attribute_mapping`, `categories`, `product_categories`
31
+ (categories and their translations were added by migrations
32
+ `00000000000019` and `00000000000020`)
33
+ - Inventory and licensing: `inventory_items`, `package_activations`,
34
+ `freemius_plans`, `freemius_pricing`
35
+ - Checkout and fulfillment: `orders`, `order_items`, `shipping_zones`,
36
+ `shipping_zone_locations`, `shipping_zone_methods`, `tax_rates`,
37
+ `currencies`
38
+
39
+ `products` can be physical or digital. The current provider selection logic
40
+ resolves:
41
+
42
+ - physical -> Stripe
43
+ - digital -> Freemius
44
+
45
+ Mixed-provider carts are rejected by `app/api/checkout/route.ts`.
46
+
47
+ ## Multi-Currency
48
+
49
+ The multi-currency implementation is real and fairly deep.
50
+
51
+ ### Store currencies
52
+
53
+ `currencies` stores:
54
+
55
+ - ISO code and symbol
56
+ - exchange rate relative to the current store default
57
+ - default and active flags
58
+ - rounding mode, rounding increment, and optional charm ending
59
+ - automatic FX refresh flag
60
+ - automatic product price sync flag
61
+ - last exchange-rate source and refresh timestamp
62
+
63
+ Supported rounding modes in code are:
64
+
65
+ - `none`
66
+ - `nearest`
67
+ - `up`
68
+ - `down`
69
+ - `charm`
70
+
71
+ ### Product and variant pricing
72
+
73
+ Products and variants support:
74
+
75
+ - legacy single-currency `price` and `sale_price`
76
+ - multi-currency `prices` and `sale_prices`
77
+
78
+ The pricing helpers resolve amounts by:
79
+
80
+ 1. looking for an explicit amount in the selected currency
81
+ 2. falling back to the base price
82
+ 3. converting from the default currency when store-managed auto-sync pricing is
83
+ enabled
84
+
85
+ The CMS product editor respects that distinction. Store-managed currencies can
86
+ be displayed in forms, but their saved overrides are stripped before
87
+ persisting.
88
+
89
+ ### Scheduled sales, price changes, and promotions
90
+
91
+ Products and variants carry a scheduled-pricing layer (migration
92
+ `00000000000025_add_sale_schedule_columns.sql`):
93
+
94
+ - `sale_start_at` / `sale_end_at` — the time window during which `sale_price` /
95
+ `sale_prices` apply. Both null = always-on (back-compat with static sales).
96
+ - `scheduled_price` / `scheduled_prices` / `scheduled_price_at` — a pending,
97
+ permanent regular-price change applied once `scheduled_price_at` passes
98
+ (bulk/Stripe-oriented; Freemius regular prices are owned by Freemius).
99
+ - `product_freemius_sale_coupons` — maps a product to an auto-generated,
100
+ time-bounded Freemius coupon so a scheduled Freemius sale is actually enforced
101
+ at Freemius-hosted checkout (Freemius enforces the coupon's start/end dates).
102
+
103
+ **Enforcement is read-time, not cron-driven.** The helpers in
104
+ `libs/ecommerce/src/lib/currency.ts` decide what applies *now*:
105
+
106
+ - `isSaleWindowActive({ saleStartAt, saleEndAt, now })`
107
+ - `resolveEffectivePriceForCurrency({ ..., saleStartAt, saleEndAt, scheduledPrice*, now })`
108
+ — wraps `resolvePriceForCurrency`, gating the sale by its window and swapping in
109
+ a due scheduled price. A sale outside its window resolves to `sale_price: null`.
110
+
111
+ Every place that computes a payable or displayed amount goes through the
112
+ window-aware helper: checkout providers (`providers/stripe.ts`,
113
+ `providers/freemius.ts`), cart/tax/coupon math, and storefront components
114
+ (`ProductCard`, `FeaturedProduct`, `ProductDetailsLayout`, UCP). The CMS edit
115
+ form exposes the window per-product and per-variant (`SaleScheduleFields`); the
116
+ bulk **Promotions** admin (`/cms/promotions`, `apps/nextblock/lib/promotions/`)
117
+ imports/exports sales and price changes via CSV.
118
+
119
+ > **Gotchas for future agents (these caused real revert/display bugs):**
120
+ >
121
+ > 1. **`generateVariantDrafts` (`variation-utils.ts`) must carry over every
122
+ > per-variant field**, including `sale_start_at`/`sale_end_at`. It re-runs on
123
+ > editor mount/attribute change; an omitted field resets to null and is then
124
+ > autosaved away ("dates revert after publish").
125
+ > 2. **Storefront block mappers must pass the window through** on *both* the
126
+ > product and each variant — `ProductGridBlock`, `FeaturedProductBlock`,
127
+ > `app/product/[slug]/page.tsx`. If the window is dropped, `isSaleWindowActive`
128
+ > sees both bounds null and treats the sale as always-on, so an inactive sale
129
+ > price shows (e.g. a "$25 – $32" range before the sale starts).
130
+ > 3. **`getVariantEffectivePriceRange` is window-aware** — pass
131
+ > `sale_start_at`/`sale_end_at` per variant or it ignores the schedule.
132
+ > 4. **Persisting on save/publish does not rely on the RPC.** Products are
133
+ > written via `upsert_product_with_variants`, but some databases run a stale
134
+ > copy of that function. `persistProductSaleSchedule` (`product-actions.ts`)
135
+ > writes the window columns with a direct `update` right after the RPC (same
136
+ > pattern as `persistProductTaxability`), matching variants by SKU.
137
+ > 5. **Autosave must not `reset()` the form or revalidate the edit route.** The
138
+ > edit-form autosave (`ProductForm.tsx`) uses a serialized-snapshot guard to
139
+ > avoid a render loop; `updateProductAction` writes only the draft (no
140
+ > `revalidatePath`). Re-rendering mid-edit resets native datetime inputs.
141
+
142
+ ### FX sync and rebasing
143
+
144
+ `libs/ecommerce/src/lib/currency-sync.ts` implements two separate operations:
145
+
146
+ - `syncStoreCurrencyRates()`: pulls fresh FX rates from `https://api.frankfurter.dev`
147
+ unless `FX_API_BASE_URL` overrides the provider.
148
+ - `rebaseStoreCurrencyExchangeRates()`: when an admin changes the default
149
+ currency, every stored rate is rebased so the new default becomes `1`.
150
+
151
+ The app exposes both through:
152
+
153
+ - CMS currency settings actions in
154
+ `apps/nextblock/app/cms/settings/currencies/actions.ts`
155
+ - `GET /api/cron/sync-currencies`, guarded by `CRON_SECRET`
156
+
157
+ ## Tax Calculation
158
+
159
+ Tax behavior is driven by the `ecommerce_inventory_settings` site setting,
160
+ loaded through `getEcommerceInventorySettings()`.
161
+
162
+ The current settings shape is:
163
+
164
+ - `trackQuantities`
165
+ - `enableTaxes`
166
+ - `taxCalculationMode`
167
+
168
+ Supported tax modes are:
169
+
170
+ - `manual`
171
+ - `automatic`
172
+
173
+ ### Manual mode
174
+
175
+ Manual mode uses `tax_rates` rows keyed by country and optional state/province.
176
+ Multiple rows can exist for the same jurisdiction, so stacked taxes such as GST
177
+ plus PST are supported.
178
+
179
+ During checkout:
180
+
181
+ - only taxable products are included
182
+ - the destination is normalized from shipping or billing data
183
+ - matching `tax_rates` are loaded
184
+ - tax lines are calculated and stored in `orders.tax_details`
185
+
186
+ ### Automatic mode
187
+
188
+ Automatic mode defers final tax calculation to Stripe Tax.
189
+
190
+ In this mode:
191
+
192
+ - checkout still records a tax intent in `orders.tax_details`
193
+ - the Stripe provider marks product and shipping tax codes on line items
194
+ - the webhook resync step replaces provisional tax data with finalized Stripe
195
+ checkout data
196
+
197
+ ## Shipping Zones and Rate Resolution
198
+
199
+ Shipping is backed by:
200
+
201
+ - `shipping_zones`
202
+ - `shipping_zone_locations`
203
+ - `shipping_zone_methods`
204
+
205
+ Each method stores:
206
+
207
+ - base amount and currency
208
+ - localized names
209
+ - per-currency amount maps and threshold maps
210
+ - `currency_pricing_mode` of `auto` or `manual`
211
+
212
+ ### Current resolver behavior
213
+
214
+ `libs/ecommerce/src/lib/shipping/resolver.ts` currently:
215
+
216
+ 1. loads active currencies
217
+ 2. queries zone locations by destination country
218
+ 3. prefers a state match when one exists
219
+ 4. otherwise prefers a country-wide match
220
+ 5. otherwise falls back to the first zone by `priority_order`
221
+ 6. filters methods by the cart total and minimum threshold
222
+ 7. converts method prices into the shopper currency
223
+ 8. returns only the cheapest valid method
224
+
225
+ Important implementation detail: `shipping_zone_locations.postal_code` exists in
226
+ schema, but the current resolver does not yet use postal code matching during
227
+ runtime resolution.
228
+
229
+ The storefront calls this through
230
+ `libs/ecommerce/src/lib/server-actions/shipping-actions.ts`.
231
+
232
+ ## Stripe Integration
233
+
234
+ Stripe is the current payment flow for physical products.
235
+
236
+ ### Checkout flow
237
+
238
+ `app/api/checkout/route.ts`:
239
+
240
+ - verifies the ecommerce package is active
241
+ - rejects carts without provider-aware items
242
+ - rejects mixed-provider carts
243
+ - requires a billing address
244
+ - resolves the provider through `getPaymentProvider()`
245
+
246
+ `StripeProvider.createCheckoutSession()` then:
247
+
248
+ - loads currencies and store settings
249
+ - validates products and variants against the database
250
+ - validates inventory before session creation when quantity tracking is enabled
251
+ - resolves shipping cost from the selected shipping method
252
+ - calculates tax in manual or automatic mode
253
+ - upserts a Stripe customer when an email is available
254
+ - inserts a pending `orders` row plus `order_items`
255
+ - stores currency, subtotal, shipping, tax, and exchange-rate data
256
+ - creates the Stripe Checkout Session and stores `stripe_session_id`
257
+
258
+ ### Webhook flow
259
+
260
+ `app/api/webhooks/stripe/route.ts` passes the raw body to
261
+ `handleStripeWebhook()`.
262
+
263
+ On `checkout.session.completed`, the sync layer:
264
+
265
+ - reloads the session with tax breakdown details
266
+ - finds the existing order
267
+ - stores payment intent, customer details, and finalized totals
268
+ - normalizes tax details from Stripe
269
+ - updates saved customer addresses
270
+ - assigns invoice metadata
271
+ - applies inventory deduction
272
+
273
+ ## Freemius Licensing and Product Sync
274
+
275
+ Freemius currently handles digital-product checkout and product synchronization.
276
+
277
+ ### Checkout behavior
278
+
279
+ `FreemiusProvider.createCheckoutSession()`:
280
+
281
+ - only allows one item per checkout
282
+ - loads the product from Supabase
283
+ - requires `freemius_product_id` and `freemius_plan_id`
284
+ - resolves pricing in the chosen currency
285
+ - inserts a pending order and order item
286
+ - optionally syncs default addresses and profile fields for the current user
287
+ - builds a Freemius checkout URL, including sandbox parameters when enabled
288
+
289
+ Supported credential sources include:
290
+
291
+ - product-scoped JSON map
292
+ - single-product sandbox overrides
293
+ - single-product env vars
294
+ - legacy shared env vars
295
+
296
+ ### Product sync
297
+
298
+ `syncFreemiusProductsToSupabase()` and `syncSingleFreemiusProduct()`:
299
+
300
+ - call the Freemius API with signed requests
301
+ - fetch plugins, plans, and pricing
302
+ - upsert digital products into `products`
303
+ - upsert related `freemius_plans` and `freemius_pricing`
304
+
305
+ These flows are surfaced in the CMS product actions and the sandbox reset route.
306
+
307
+ ### Current webhook limitation
308
+
309
+ `app/api/webhooks/freemius/route.ts` currently verifies the webhook signature
310
+ and acknowledges selected event types, but it does not yet reconcile license or
311
+ order state back into the local database.
312
+
313
+ ## Inventory Management and Fulfillment
314
+
315
+ Inventory behavior is controlled by `trackQuantities`.
316
+
317
+ When tracking is enabled:
318
+
319
+ - checkout validates requested quantity against `inventory_items`
320
+ - if a SKU is not yet cached there, product or variant stock fields are used as
321
+ fallback
322
+ - a paid order triggers `apply_order_inventory_deduction()`
323
+
324
+ The deduction flow is resilient:
325
+
326
+ - first it calls the database RPC `apply_order_inventory_deduction`
327
+ - if that fails, it falls back to a direct SQL reconciliation path using
328
+ `POSTGRES_URL` or `DATABASE_URL`
329
+
330
+ Order statuses currently supported in code are:
331
+
332
+ - `pending`
333
+ - `paid`
334
+ - `shipped`
335
+ - `cancelled`
336
+ - `refunded`
337
+
338
+ Manual CMS order status changes also trigger invoice assignment and inventory
339
+ deduction when an order is moved to `paid`.
340
+
341
+ ## Invoice and Order Presentation
342
+
343
+ The order/invoice layer includes:
344
+
345
+ - stable invoice numbering through database functions
346
+ - `invoice_settings` in `site_settings`
347
+ - printable invoice presentation data via `invoice-server.ts`
348
+ - UI components such as `InvoiceDocument` and `InvoiceViewerShell`
349
+ - customer order history and invoice access through `customer-orders.ts`
350
+
351
+ ## CMS Commerce Surfaces
352
+
353
+ The active ecommerce CMS surface includes:
354
+
355
+ - product list, create, edit, media, attribute, and variation management
356
+ - inventory management
357
+ - orders list and detail management
358
+ - shipping zones and shipping rate management
359
+ - payment-provider enablement
360
+ - tax settings and manual tax-rate management
361
+ - currency settings under `/cms/settings/currencies`
362
+
363
+ The CMS shell only exposes these store sections when the ecommerce package is
364
+ reported as active.
@@ -0,0 +1,202 @@
1
+ # 03 CMS and Editor
2
+
3
+ ## Two Related Systems
4
+
5
+ NextBlock's content authoring experience is split across two real subsystems:
6
+
7
+ - `libs/editor`: a reusable Tiptap-based rich text package
8
+ - `apps/nextblock/lib/blocks`: the block registry and page-builder layer used
9
+ by pages, posts, and some commerce surfaces
10
+
11
+ They work together, but they are not the same thing.
12
+
13
+ ## Block Registry and Page Builder
14
+
15
+ The block registry lives in `apps/nextblock/lib/blocks/blockRegistry.ts`. It is
16
+ the current source of truth for:
17
+
18
+ - available block types
19
+ - Zod schemas
20
+ - default content
21
+ - editor component filenames
22
+ - renderer component filenames
23
+ - human-facing labels and block metadata
24
+
25
+ ### Current registered block types
26
+
27
+ The registry currently includes:
28
+
29
+ - `text`
30
+ - `heading`
31
+ - `image`
32
+ - `button`
33
+ - `posts_grid`
34
+ - `video_embed`
35
+ - `section`
36
+ - `form`
37
+ - `testimonial`
38
+ - `product_grid`
39
+ - `featured_product`
40
+ - `cart`
41
+ - `checkout`
42
+ - `product_details`
43
+
44
+ The authoritative type list is `apps/nextblock/lib/blocks/blockTypes.ts`
45
+ (`availableBlockTypes`).
46
+
47
+ A `section` block can contain nested column block arrays, so the page builder
48
+ supports multi-column compositions instead of only flat block lists. Legacy
49
+ `hero` blocks were folded into `section` (carrying an `is_hero` flag) by
50
+ migration `00000000000021_migrate_hero_blocks_to_sections.sql`, so `hero` is no
51
+ longer a standalone registered block type.
52
+
53
+ ### How the CMS uses the registry
54
+
55
+ The CMS block editor components under `app/cms/blocks` use the registry to:
56
+
57
+ - validate block types
58
+ - build new block payloads from default content
59
+ - dynamically load editor components
60
+ - dynamically load renderer components
61
+ - render block labels and picker entries
62
+
63
+ The registry also exposes helper functions such as:
64
+
65
+ - `getBlockDefinition()`
66
+ - `getInitialContent()`
67
+ - `getBlockSchema()`
68
+ - `validateBlockContent()`
69
+ - `generateDefaultContent()`
70
+
71
+ ## Tiptap Editor Package
72
+
73
+ The reusable editor surface lives in `libs/editor`.
74
+
75
+ The main exports today are:
76
+
77
+ - `Editor`
78
+ - `NotionEditor`
79
+ - `EditorToolbar`
80
+ - `EditorBubbleMenu`
81
+ - `EditorFloatingMenu`
82
+ - `EnhancedFloatingMenu`
83
+ - `SlashCommandList`
84
+ - `DragHandle`
85
+ - `HtmlContent`
86
+ - `editorExtensions`
87
+
88
+ ### Core editing capabilities
89
+
90
+ `libs/editor/src/lib/kit.ts` composes the editor from Tiptap extensions and
91
+ custom nodes. The shipped editing surface includes:
92
+
93
+ - StarterKit-based rich text
94
+ - syntax-highlighted code blocks via `CodeBlockLowlight`
95
+ - tables
96
+ - task lists
97
+ - link handling
98
+ - text styling through `TextStyleKit`
99
+ - highlight, subscript, superscript, and typography helpers
100
+ - character counting
101
+ - slash commands
102
+ - drag handles and draggable node movement
103
+ - image handling
104
+
105
+ ### Custom HTML-preserving extensions
106
+
107
+ The editor intentionally preserves more HTML than a minimal rich text field.
108
+ Current custom nodes/extensions include support for:
109
+
110
+ - `div`
111
+ - `style`
112
+ - `script`
113
+ - `svg`
114
+ - `span`
115
+ - a catch-all attribute preservation layer
116
+
117
+ This matters because some CMS-authored content and seeded content store richer
118
+ HTML fragments than plain paragraph markup.
119
+
120
+ ## Inline Widgets
121
+
122
+ The editor currently ships two inline widget node types:
123
+
124
+ - alert widget
125
+ - call-to-action widget
126
+
127
+ These appear in multiple places:
128
+
129
+ - Tiptap commands and slash-command actions
130
+ - editor node views in `libs/editor`
131
+ - runtime React renderers in `apps/nextblock/components/blocks/renderers/inline`
132
+
133
+ So the widgets are not just editor-only decorations; they have both editing and
134
+ front-end rendering paths.
135
+
136
+ ## NotionEditor Integration Pattern
137
+
138
+ `NotionEditor` is the higher-level client component used by the app. It wraps:
139
+
140
+ - the extension kit
141
+ - toolbars and menus
142
+ - content synchronization through `onChange` and `onUpdate`
143
+ - media picker bridging through editor storage
144
+ - hydration-safe initialization with `immediatelyRender: false`
145
+ - a scrollable editing shell and character counts
146
+
147
+ The app currently mounts it in multiple places, including:
148
+
149
+ - text block editing
150
+ - product description editing
151
+
152
+ ## Media Picker Integration
153
+
154
+ The editor integrates with a pluggable image picker bridge:
155
+
156
+ - `setOpenImagePicker()` stores a picker callback on the editor instance
157
+ - menus and extensions can open the media picker without knowing app details
158
+ - the CMS supplies the actual picker UI
159
+
160
+ This keeps the editor package reusable while still supporting CMS media
161
+ selection.
162
+
163
+ ## Commerce-Aware Blocks
164
+
165
+ The block layer is not content-only. The app also ships block types that render
166
+ commerce primitives backed by `@nextblock-cms/ecommerce`, including:
167
+
168
+ - product grid
169
+ - featured product
170
+ - cart
171
+ - checkout
172
+ - product details
173
+
174
+ These bridge the CMS page builder to the premium commerce library without
175
+ copying storefront logic into the app.
176
+
177
+ ## Custom Blocks (Data-Driven CRUD)
178
+
179
+ Beyond the code-defined built-ins above, editors can create their own block
180
+ types at runtime from the CMS, with no code deploy. These **custom block
181
+ definitions** are stored as rows in `custom_block_definitions` (typed fields
182
+ plus a recursive layout schema) and rendered on the public site by a dynamic
183
+ layout engine instead of a compiled React renderer.
184
+
185
+ The wiring is intentionally simple: a page/post block whose `block_type` equals
186
+ a custom definition's `slug` is resolved through
187
+ `getCachedCustomBlockDefinitionBySlug()` and rendered by
188
+ `CachedDynamicLayoutEngine`. Authoring, CRUD, duplicate, and JSON
189
+ import/export/backup all live under `app/cms/custom-blocks`.
190
+
191
+ Full details, including the field types, the layout schema, caching, and the
192
+ Cortex AI "build widget" path, are in
193
+ [10-CUSTOM-BLOCKS.md](./10-CUSTOM-BLOCKS.md).
194
+
195
+ ## Relationship to the SDK
196
+
197
+ The registry is the current in-app block system. The formal external authoring
198
+ contract lives in `libs/sdk` and is documented in
199
+ [07-BLOCK-SDK-AND-EXTENSIBILITY.md](./07-BLOCK-SDK-AND-EXTENSIBILITY.md).
200
+
201
+ If you are changing how blocks work inside the CMS, start here. If you are
202
+ designing a reusable third-party block contract, start with the SDK doc.