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,6 @@
1
+ declare module 'jsdom' {
2
+ export class JSDOM {
3
+ constructor(html?: string);
4
+ window: any;
5
+ }
6
+ }
@@ -1,31 +0,0 @@
1
- import React from 'react';
2
-
3
- /**
4
- * This component is never rendered but ensures that specific Tailwind classes
5
- * used in the database seeds (SQL files) are generated in the CSS bundle.
6
- *
7
- * We are using this as a fallback because Tailwind's scanning of SQL files
8
- * in the libs directory is proving unreliable on Windows.
9
- */
10
- export default function ForceStyles() {
11
- return (
12
- <div className="hidden">
13
- {/* Spacing & Layout */}
14
- <div className="mt-10 p-8 p-10 p-12 gap-4"></div>
15
- <div className="grid grid-cols-2 sm:grid-cols-4 lg:grid-cols-8"></div>
16
-
17
- {/* Text colors used in blocks */}
18
- <div className="text-slate-200 text-slate-300 text-slate-400 text-slate-600 text-slate-900"></div>
19
- <div className="dark:text-slate-200 dark:text-slate-400 dark:text-white"></div>
20
- <div className="text-sm font-semibold text-center text-white"></div>
21
-
22
- {/* Backgrounds and Borders */}
23
- <div className="bg-white/5 bg-white/10 border-white/10 border-white/20"></div>
24
- <div className="bg-slate-50 hover:bg-slate-100 dark:bg-white/5 dark:hover:bg-white/10"></div>
25
-
26
- {/* Gradients */}
27
- <div className="bg-gradient-to-r bg-gradient-to-br from-blue-400 to-cyan-400"></div>
28
- <div className="from-blue-500/10 to-purple-500/10"></div>
29
- </div>
30
- );
31
- }
@@ -1,63 +0,0 @@
1
- import { fetchAllPublishedPages, fetchAllPublishedPosts } from '../lib/sitemap-utils';
2
- import { NextResponse } from 'next/server';
3
-
4
- const baseUrl = process.env.NEXT_PUBLIC_URL || 'http://localhost:3000';
5
- if (!process.env.NEXT_PUBLIC_URL) {
6
- console.warn("Warning: NEXT_PUBLIC_URL environment variable is not set for sitemap. Defaulting to http://localhost:3000. Ensure this is set for production.");
7
- }
8
-
9
- interface SitemapEntry {
10
- path: string;
11
- lastModified: string;
12
- }
13
-
14
- export async function GET() {
15
- try {
16
- let pages: SitemapEntry[] = [];
17
- try {
18
- pages = await fetchAllPublishedPages();
19
- } catch (error) {
20
- console.error("Error fetching published pages for sitemap:", error);
21
- // Proceed with an empty array for pages
22
- }
23
-
24
- let posts: SitemapEntry[] = [];
25
- try {
26
- posts = await fetchAllPublishedPosts();
27
- } catch (error) {
28
- console.error("Error fetching published posts for sitemap:", error);
29
- // Proceed with an empty array for posts
30
- }
31
-
32
- const staticRoutes: SitemapEntry[] = [
33
- { path: '/', lastModified: new Date().toISOString() },
34
- { path: '/articles', lastModified: new Date().toISOString() },
35
- ];
36
-
37
- const allEntries = [...staticRoutes, ...pages, ...posts];
38
-
39
- const sitemapXml = `<?xml version="1.0" encoding="UTF-8"?>
40
- <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
41
- ${allEntries
42
- .map(
43
- (entry) => `
44
- <url>
45
- <loc>${baseUrl}${entry.path}</loc>
46
- <lastmod>${entry.lastModified}</lastmod>
47
- </url>
48
- `
49
- )
50
- .join('')}
51
- </urlset>`;
52
-
53
- return new Response(sitemapXml, {
54
- headers: {
55
- 'Content-Type': 'application/xml',
56
- 'Cache-Control': 's-maxage=3600, stale-while-revalidate=86400',
57
- },
58
- });
59
- } catch (error) {
60
- console.error("Error generating sitemap:", error);
61
- return new NextResponse('Internal Server Error', { status: 500 });
62
- }
63
- }
@@ -1,273 +0,0 @@
1
- // components/blocks/renderers/HeroBlockRenderer.tsx
2
- import React from "react";
3
- import type { SectionBlockContent, Gradient } from "../../../lib/blocks/blockRegistry";
4
- import Image from 'next/image';
5
-
6
- const R2_BASE_URL = process.env.NEXT_PUBLIC_R2_BASE_URL || "";
7
- const HERO_BACKGROUND_DEFAULT_QUALITY = 60;
8
-
9
- function resolveImageQuality(value: unknown, fallback: number): number {
10
- if (value === undefined || value === null || value === '') {
11
- return fallback;
12
- }
13
-
14
- const numeric =
15
- typeof value === 'number'
16
- ? value
17
- : Number.parseInt(String(value), 10);
18
-
19
- if (!Number.isFinite(numeric)) {
20
- return fallback;
21
- }
22
-
23
- const rounded = Math.round(numeric);
24
- if (rounded < 1 || rounded > 100) {
25
- return fallback;
26
- }
27
-
28
- return rounded;
29
- }
30
-
31
- interface SectionBlockRendererProps {
32
- content: SectionBlockContent;
33
- languageId: number;
34
- }
35
-
36
- // Container class mapping
37
- const containerClasses = {
38
- 'full-width': 'w-full',
39
- 'container': 'container mx-auto px-4',
40
- 'container-sm': 'container mx-auto px-4 max-w-screen-sm',
41
- 'container-lg': 'container mx-auto px-4 max-w-screen-lg',
42
- 'container-xl': 'container mx-auto px-4 max-w-screen-xl'
43
- };
44
-
45
- // Column grid classes
46
- const columnClasses = {
47
- 1: 'grid-cols-1',
48
- 2: 'grid-cols-1 md:grid-cols-2',
49
- 3: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',
50
- 4: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-4'
51
- };
52
-
53
- // Gap classes
54
- const gapClasses = {
55
- none: 'gap-0',
56
- sm: 'gap-2',
57
- md: 'gap-4',
58
- lg: 'gap-6',
59
- xl: 'gap-8'
60
- };
61
-
62
- // Padding classes
63
- const paddingClasses = {
64
- none: '',
65
- sm: 'py-2',
66
- md: 'py-4',
67
- lg: 'py-8',
68
- xl: 'py-12'
69
- };
70
-
71
- // Vertical alignment classes
72
- const verticalAlignmentClasses = {
73
- start: 'items-start',
74
- center: 'items-center',
75
- end: 'items-end',
76
- stretch: 'items-stretch'
77
- };
78
-
79
- // Background style generator
80
- function generateBackgroundStyles(background: SectionBlockContent['background']) {
81
- const styles: React.CSSProperties = {};
82
- let className = '';
83
-
84
- if (background.min_height) {
85
- styles.minHeight = background.min_height;
86
- }
87
-
88
- switch (background.type) {
89
- case 'theme': {
90
- // Theme-based backgrounds using CSS classes
91
- const themeClasses = {
92
- primary: 'bg-primary text-primary-foreground',
93
- secondary: 'bg-secondary text-secondary-foreground',
94
- muted: 'bg-muted text-muted-foreground',
95
- accent: 'bg-accent text-accent-foreground',
96
- destructive: 'bg-destructive text-destructive-foreground'
97
- };
98
- className = background.theme ? themeClasses[background.theme] || '' : '';
99
- break;
100
- }
101
-
102
- case 'solid':
103
- styles.backgroundColor = background.solid_color;
104
- break;
105
-
106
- case 'gradient':
107
- if (background.gradient) {
108
- const { type, direction, stops } = background.gradient;
109
- const gradientStops = stops.map(stop => `${stop.color} ${stop.position}%`).join(', ');
110
- styles.background = `${type}-gradient(${direction || 'to right'}, ${gradientStops})`;
111
- }
112
- break;
113
-
114
- case 'image':
115
- if (background.image) {
116
- const imageUrl = `${R2_BASE_URL}/${background.image.object_key}`;
117
- styles.backgroundSize = background.image.size || 'cover';
118
- styles.backgroundPosition = background.image.position || 'center';
119
-
120
- let finalBackgroundImage = `url(${imageUrl})`;
121
-
122
- if (background.image.overlay && background.image.overlay.gradient) {
123
- const { type, direction, stops } = background.image.overlay.gradient;
124
- const gradientStops = stops.map(stop => `${stop.color} ${stop.position}%`).join(', ');
125
- const gradient = `${type}-gradient(${direction || 'to right'}, ${gradientStops})`;
126
- finalBackgroundImage = `${gradient}, ${finalBackgroundImage}`;
127
- }
128
-
129
- styles.backgroundImage = finalBackgroundImage;
130
- }
131
- break;
132
-
133
- default:
134
- // No background
135
- break;
136
- }
137
-
138
- return { styles, className };
139
- }
140
-
141
- function generateGradientString(gradient: Gradient) {
142
- const { type, direction, stops } = gradient;
143
- const gradientStops = stops.map((stop: { color: string; position: number }) => `${stop.color} ${stop.position}%`).join(', ');
144
- return `${type}-gradient(${direction || 'to right'}, ${gradientStops})`;
145
- }
146
-
147
- // Static imports for critical hero block components
148
- import TextBlockRenderer from './TextBlockRenderer';
149
- import ImageBlockRenderer from './ImageBlockRenderer';
150
- import ButtonBlockRenderer from './ButtonBlockRenderer';
151
- import HeadingBlockRenderer from './HeadingBlockRenderer';
152
-
153
- // Static nested block renderer component for hero blocks (no dynamic imports)
154
- const StaticNestedBlockRenderer: React.FC<{
155
- block: SectionBlockContent['column_blocks'][0][0];
156
- languageId: number;
157
- }> = ({ block, languageId }) => {
158
- // Use static imports for common hero block components to eliminate loading delays
159
- switch (block.block_type) {
160
- case 'text':
161
- return (
162
- <TextBlockRenderer
163
- content={block.content as any}
164
- languageId={languageId}
165
- />
166
- );
167
- case 'heading':
168
- return (
169
- <HeadingBlockRenderer
170
- content={block.content as any}
171
- languageId={languageId}
172
- />
173
- );
174
- case 'image':
175
- return (
176
- <ImageBlockRenderer
177
- content={block.content as any}
178
- languageId={languageId}
179
- priority={true}
180
- />
181
- );
182
- case 'button':
183
- return (
184
- <ButtonBlockRenderer
185
- content={block.content as any}
186
- languageId={languageId}
187
- />
188
- );
189
- default:
190
- // Fallback for unsupported block types in hero
191
- return (
192
- <div className="p-2 border rounded bg-destructive/10 text-destructive text-sm">
193
- <strong>Unsupported hero block type:</strong> {block.block_type}
194
- </div>
195
- );
196
- }
197
- };
198
-
199
- const HeroBlockRenderer: React.FC<SectionBlockRendererProps> = ({
200
- content,
201
- languageId,
202
- }) => {
203
- const { styles, className: backgroundClassName } = generateBackgroundStyles(content.background);
204
-
205
- const backgroundImage = content.background.type === 'image' ? content.background.image : undefined;
206
-
207
- if (backgroundImage) {
208
- delete styles.backgroundImage;
209
- }
210
- const heroImageQuality = resolveImageQuality(backgroundImage?.quality, HERO_BACKGROUND_DEFAULT_QUALITY);
211
-
212
- // Build CSS classes
213
- const containerClass = containerClasses[content.container_type] || containerClasses.container;
214
- const gridClass = columnClasses[content.responsive_columns.desktop] || columnClasses[3];
215
- const gapClass = gapClasses[content.column_gap] || gapClasses.md;
216
- const paddingTopClass = paddingClasses[content.padding.top] || paddingClasses.md;
217
- const paddingBottomClass = paddingClasses[content.padding.bottom] || paddingClasses.md;
218
- const alignmentClass = content.vertical_alignment ? verticalAlignmentClasses[content.vertical_alignment] : 'items-start';
219
-
220
- const imageProps = backgroundImage?.blur_data_url
221
- ? {
222
- placeholder: 'blur' as const,
223
- blurDataURL: backgroundImage.blur_data_url,
224
- }
225
- : {};
226
-
227
- return (
228
- <section
229
- className={`relative w-full flex items-center ${paddingTopClass} ${paddingBottomClass} ${backgroundClassName}`.trim()}
230
- style={styles}
231
- >
232
- {backgroundImage && (
233
- <Image
234
- src={`${R2_BASE_URL}/${backgroundImage.object_key}`}
235
- alt={backgroundImage.alt_text || 'Hero background image'}
236
- fill
237
- style={{
238
- objectFit: backgroundImage.size || 'cover',
239
- objectPosition: backgroundImage.position || 'center'
240
- }}
241
- sizes="(max-width: 768px) 100vw, (max-width: 1200px) 100vw, 100vw"
242
- priority={true}
243
- fetchPriority="high"
244
- quality={heroImageQuality}
245
- {...imageProps}
246
- />
247
- )}
248
- {backgroundImage?.overlay?.gradient && (
249
- <div
250
- className="absolute inset-0"
251
- style={{ background: generateGradientString(backgroundImage.overlay.gradient) }}
252
- />
253
- )}
254
- <div className={`${containerClass} relative`}>
255
- <div className={`grid ${gridClass} ${gapClass} ${alignmentClass}`}>
256
- {content.column_blocks.map((columnBlocks, columnIndex) => (
257
- <div key={`column-${columnIndex}`} className="min-h-0 space-y-4">
258
- {(Array.isArray(columnBlocks) ? columnBlocks : []).map((block, blockIndex) => (
259
- <StaticNestedBlockRenderer
260
- key={`${block.block_type}-${columnIndex}-${blockIndex}`}
261
- block={block}
262
- languageId={languageId}
263
- />
264
- ))}
265
- </div>
266
- ))}
267
- </div>
268
- </div>
269
- </section>
270
- );
271
- };
272
-
273
- export default HeroBlockRenderer;
@@ -1,149 +0,0 @@
1
- # How to Create a Custom Block with the NextBlock SDK
2
-
3
- Custom blocks allow you to extend the functionality of NextBlock CMS while ensuring type safety and seamless integration. The `@nextblock-cms/sdk` package provides the necessary tools and interfaces.
4
-
5
- ## Step 1: Define the Schema (Zod)
6
-
7
- The schema defines the structure of your block's content. It is used for validation and to generate TypeScript types.
8
-
9
- ```typescript
10
- import { z } from 'zod';
11
-
12
- export const MyBlockSchema = z.object({
13
- title: z.string().min(1).describe('The main title'),
14
- description: z.string().optional().describe('Optional description'),
15
- isActive: z.boolean().default(true),
16
- });
17
-
18
- // Derive the content type from the schema
19
- export type MyBlockContent = z.infer<typeof MyBlockSchema>;
20
- ```
21
-
22
- ## Step 2: Define the Components (React/TS)
23
-
24
- Create the components that will render your block. Use the `BlockProps` interface to ensure your component receives the correct data.
25
-
26
- ```typescript
27
- import React from 'react';
28
- import { BlockProps } from '@nextblock-cms/sdk';
29
-
30
- // The Renderer Component (Public View)
31
- const MyBlockRenderer: React.FC<BlockProps<typeof MyBlockSchema>> = ({ content }) => {
32
- return (
33
- <div className="my-block">
34
- <h2>{content.title}</h2>
35
- {content.description && <p>{content.description}</p>}
36
- </div>
37
- );
38
- };
39
-
40
- // The Editor Component (CMS View)
41
- // Currently, the CMS uses auto-generated forms based on the schema,
42
- // but you can provide a custom preview or editor here.
43
- const MyBlockEditor: React.FC<BlockProps<typeof MyBlockSchema>> = ({ content }) => {
44
- return (
45
- <div className="p-4 border">
46
- Preview: {content.title}
47
- </div>
48
- );
49
- };
50
- ```
51
-
52
- ## Step 3: Create the Configuration
53
-
54
- Combine everything into a `BlockConfig` object. This object tells the CMS how to handle your block.
55
-
56
- ```typescript
57
- import { BlockConfig } from '@nextblock-cms/sdk';
58
- import { Star } from 'lucide-react'; // Choose an icon
59
-
60
- export const MyBlockConfig: BlockConfig<typeof MyBlockSchema> = {
61
- type: 'my_block', // Unique identifier
62
- label: 'My Custom Block',
63
- icon: Star,
64
- schema: MyBlockSchema,
65
- initialContent: {
66
- title: 'Default Title',
67
- isActive: true,
68
- },
69
- RendererComponent: MyBlockRenderer,
70
- EditorComponent: MyBlockEditor,
71
- };
72
- ```
73
-
74
- ## Step 4: Building the Editor Component
75
-
76
- The Editor Component is responsible for the editing experience within the CMS. It receives `BlockEditorProps`, which includes the current content and an `onChange` handler.
77
-
78
- You should use the shared UI components from `@nextblock-cms/ui` (like `Input`, `Textarea`, `Button`, `Label`) to ensure a consistent look and feel with the rest of the Admin UI.
79
-
80
- ```typescript
81
- import React from 'react';
82
- import { BlockEditorProps } from '@nextblock-cms/sdk';
83
- import { Input, Label, Textarea } from '@nextblock-cms/ui';
84
-
85
- const MyBlockEditor: React.FC<BlockEditorProps<typeof MyBlockSchema>> = ({ content, onChange }) => {
86
-
87
- const handleChange = (key: keyof typeof content, value: any) => {
88
- onChange({
89
- ...content,
90
- [key]: value,
91
- });
92
- };
93
-
94
- return (
95
- <div className="space-y-4">
96
- <div className="space-y-2">
97
- <Label htmlFor="title">Title</Label>
98
- <Input
99
- id="title"
100
- value={content.title}
101
- onChange={(e) => handleChange('title', e.target.value)}
102
- />
103
- </div>
104
-
105
- <div className="space-y-2">
106
- <Label htmlFor="description">Description</Label>
107
- <Textarea
108
- id="description"
109
- value={content.description || ''}
110
- onChange={(e) => handleChange('description', e.target.value)}
111
- />
112
- </div>
113
- </div>
114
- );
115
- };
116
- ```
117
-
118
- ## Step 5: Register the Block
119
-
120
- To make your block available in the CMS, import it into the main registry file: `apps/nextblock/lib/blocks/blockRegistry.ts`.
121
-
122
- ```typescript
123
- // apps/nextblock/lib/blocks/blockRegistry.ts
124
- import { MyBlockConfig } from '../../components/blocks/MyBlock';
125
-
126
- export const blockRegistry: Record<BlockType, BlockDefinition> = {
127
- // ... existing blocks
128
- [MyBlockConfig.type]: {
129
- ...MyBlockConfig,
130
- // ... any additional internal config if needed
131
- } as BlockDefinition<MyBlockContent>,
132
- };
133
- ```
134
-
135
- Once registered, your block will appear in the CMS block picker and render on the frontend.
136
-
137
- ## Advanced Topic: Schema Evolution and Versioning
138
-
139
- Modifying a Zod schema after a block is in production can be dangerous. If you change the shape of the data (e.g., rename a field, remove a required field), existing blocks in the database may fail to validate or render, causing runtime errors.
140
-
141
- ### Recommended Strategy: Versioning
142
-
143
- Instead of modifying the existing schema, create a new version of the block.
144
-
145
- 1. **Duplicate the Block**: Create a new block type, e.g., `my_block_v2`, with the updated schema and renderer.
146
- 2. **Register the New Block**: Add it to the registry. You can hide the old `my_block` from the picker if you want to prevent new usage, but keep the definition so existing blocks continue to work.
147
- 3. **Migration (Optional)**: You can write a utility to transform `my_block` data to `my_block_v2` format if you want to migrate content programmatically.
148
-
149
- While V1 of the SDK does not enforce a strict versioning system, treating your block schemas as immutable contracts is a best practice for stability.
@@ -1,56 +0,0 @@
1
- # CMS Application: Overview
2
-
3
- This document provides a high-level overview of the main Next.js application for the CMS, detailing its structure, core modules, and key functionalities. It serves as a guide for understanding how the different parts of the CMS are organized and interact.
4
-
5
- ## 1. CMS Root Layout (`app/cms/layout.tsx`)
6
-
7
- The file [`app/cms/layout.tsx`](app/cms/layout.tsx) is the foundational component for the entire CMS interface, wrapping all pages under the `/cms` path.
8
-
9
- ### Key Responsibilities:
10
-
11
- * **Authentication and Access Control**: The layout uses the `useAuth` hook from `AuthContext` to get the current user's status and role (`isAdmin`, `isWriter`). It contains a `useEffect` hook that protects the CMS routes by redirecting unauthenticated users to the sign-in page and users with insufficient permissions to an "unauthorized" page.
12
-
13
- * **UI Structure**: It renders the primary user interface shell, which consists of:
14
- * A **responsive sidebar** for navigation, which is permanently visible on desktop screens and can be toggled on mobile.
15
- * A **main content area** that displays the specific page component for the current route.
16
- * A **dynamic header** within the main content area that displays the title of the current page.
17
-
18
- * **Dynamic Page Title**: The header's title is not static. It's dynamically determined by inspecting the current URL's `pathname` using the `usePathname` hook. A series of `if/else if` statements map URL patterns (e.g., `/cms/pages`, `/cms/pages/new`) to user-friendly titles (e.g., "Pages", "New Page").
19
-
20
- * **User Profile & Logout**: The sidebar includes a section at the bottom displaying the logged-in user's avatar, name, and role, along with a button to sign out.
21
-
22
- ## 2. Core CMS Modules
23
-
24
- The CMS is organized into several modules, each corresponding to a specific content type or area of management. These modules are located in subdirectories within `app/cms/`. They follow a consistent file structure pattern.
25
-
26
- ### Common File Structure:
27
-
28
- * `page.tsx`: The main entry point for the module, typically displaying a list or grid of the items (e.g., a table of pages, a grid of media).
29
- * `[id]/edit/page.tsx`: The page for editing a single, existing item, identified by its ID in the URL.
30
- * `new/page.tsx`: The page for creating a new item.
31
- * `actions.ts`: A file containing all the server actions for the module (e.g., `createPage`, `updatePage`, `deletePage`).
32
- * `components/`: A directory for React components that are specific to this module, such as forms or client-side components that invoke server actions (e.g., `DeletePageButtonClient.tsx`).
33
-
34
- ### Module Breakdown:
35
-
36
- * **Dashboard (`app/cms/dashboard/`)**: The main landing page after logging into the CMS.
37
- * `page.tsx`: Displays welcome information and summary statistics.
38
-
39
- * **Pages (`app/cms/pages/`)**: Manages the static pages of the public-facing website.
40
- * Key files: `page.tsx`, `[id]/edit/page.tsx`, `new/page.tsx`, `actions.ts`, `components/PageForm.tsx`, `components/DeletePageButtonClient.tsx`.
41
-
42
- * **Posts (`app/cms/posts/`)**: Manages blog posts or articles.
43
- * Key files: `page.tsx`, `[id]/edit/page.tsx`, `new/page.tsx`, `actions.ts`, `components/PostForm.tsx`, `components/DeletePostButtonClient.tsx`.
44
-
45
- * **Media (`app/cms/media/`)**: Manages the website's media library (images, documents, etc.).
46
- * Key files: `page.tsx`, `[id]/edit/page.tsx`, `actions.ts`, `components/MediaUploadForm.tsx`, `components/MediaGridClient.tsx`, `components/MediaEditForm.tsx`.
47
-
48
- * **Navigation (`app/cms/navigation/`)**: Manages the site's navigation menus.
49
- * Key files: `page.tsx`, `[id]/edit/page.tsx`, `new/page.tsx`, `actions.ts`, `components/NavigationMenuDnd.tsx`, `components/NavigationItemForm.tsx`.
50
-
51
- * **Users (`app/cms/users/`)**: (Admin only) Manages user accounts and roles.
52
- * Key files: `page.tsx`, `[id]/edit/page.tsx`, `actions.ts`, `components/UserForm.tsx`, `components/DeleteUserButton.tsx`.
53
-
54
- * **Settings (`app/cms/settings/`)**: Manages site-wide settings. This module contains sub-modules for different settings areas.
55
- * **Languages (`app/cms/settings/languages/`)**: (Admin only) Manages available content languages.
56
- * Key files: `page.tsx`, `[id]/edit/page.tsx`, `new/page.tsx`, `actions.ts`, `components/LanguageForm.tsx`.
@@ -1,73 +0,0 @@
1
- # CMS Block Editor: Architecture Overview
2
-
3
- This document provides a comprehensive overview of the block-based content editor's architecture, serving as a technical reference for development.
4
-
5
- ## 1. Core Concepts
6
-
7
- ### Database Schema
8
- The entire system is powered by a single `blocks` table in Supabase. The key field is `content` (a `JSONB` type), which stores a flexible JSON object containing all data for a specific block. This approach allows for adding new block types and modifying existing ones without requiring database schema migrations.
9
-
10
- ### Block Registry
11
- The file [`lib/blocks/blockRegistry.ts`](/lib/blocks/blockRegistry.ts) is the **single source of truth** for all block types. It's a central configuration object that maps a block's `block_type` string to its:
12
- - User-facing `label`.
13
- - `initialContent` structure.
14
- - The filename of its corresponding `editorComponent` and `rendererComponent`.
15
-
16
- Any new block must be defined here first.
17
-
18
- ## 2. Key Architectural Patterns
19
-
20
- ### Editor/Renderer Split
21
- The architecture maintains a strict separation between the editing interface and the final public-facing output.
22
- - **Editors** (`app/cms/blocks/editors/*.tsx`): React components that render the forms and controls for modifying a block's `content`.
23
- - **Renderers** (`components/blocks/renderers/*.tsx`): React components that take a block's `content` and render the final, styled HTML for the public website.
24
-
25
- ### Optimistic UI & Debounced Saves
26
- To provide a fast and smooth user experience, the editor uses an optimistic UI pattern.
27
- - All state is centralized in [`app/cms/blocks/components/BlockEditorArea.tsx`](/app/cms/blocks/components/BlockEditorArea.tsx) and managed with React's `useOptimistic` hook.
28
- - When a user makes a change, the UI updates instantly.
29
- - The actual save operation is handled by a debounced call to the `updateBlock` server action in [`app/cms/blocks/actions.ts`](/app/cms/blocks/actions.ts).
30
- - Crucially, `updateBlock` **does not** call `revalidatePath`, preventing disruptive page reloads during editing sessions.
31
-
32
- ## 3. Component Breakdown & Data Flow
33
-
34
- The editor is a hierarchy of components, each with a specific responsibility.
35
-
36
- #### `BlockEditorArea.tsx`
37
- - **Location:** [`app/cms/blocks/components/BlockEditorArea.tsx`](/app/cms/blocks/components/BlockEditorArea.tsx)
38
- - **Role:** The root component for the editor. It fetches the initial blocks, manages the master `blocks` state (including the optimistic state), and provides the main `DndContext` for top-level drag-and-drop functionality.
39
-
40
- #### `SortableBlockItem.tsx`
41
- - **Location:** [`app/cms/blocks/components/SortableBlockItem.tsx`](/app/cms/blocks/components/SortableBlockItem.tsx)
42
- - **Role:** A wrapper for each individual block that provides the `useSortable` context from `dnd-kit`, making each block draggable. It passes `dragHandleProps` down to its child.
43
-
44
- #### `EditableBlock.tsx`
45
- - **Location:** [`app/cms/blocks/components/EditableBlock.tsx`](/app/cms/blocks/components/EditableBlock.tsx)
46
- - **Role:** The primary controller for a single block. It renders the block's header, including the drag handle and edit/delete buttons.
47
- - **Core Logic:** This component contains the critical conditional logic for the editing experience:
48
- - If the `block.block_type` is `section` or `hero`, clicking the edit icon toggles an `isConfigPanelOpen` state, which shows/hides the inline configuration panel.
49
- - For **all other block types**, clicking the edit icon lazy-loads the appropriate editor component and opens the `BlockEditorModal`.
50
-
51
- #### `BlockEditorModal.tsx`
52
- - **Location:** [`app/cms/blocks/components/BlockEditorModal.tsx`](/app/cms/blocks/components/BlockEditorModal.tsx)
53
- - **Role:** A reusable modal dialog for editing standard blocks.
54
- - **Functionality:** It receives a lazy-loaded editor component and wraps it in `<React.Suspense>`, showing a loading state *inside* the modal. It manages a temporary state for the block's content and calls the `onContentChange` callback on save. For the Rich Text block, it is styled to be extra tall (`h-[90vh]`).
55
-
56
- ---
57
-
58
- ### Section & Column Components
59
-
60
- The "Section" block type enables complex multi-column layouts.
61
-
62
- #### `SectionBlockEditor.tsx`
63
- - **Location:** [`app/cms/blocks/editors/SectionBlockEditor.tsx`](/app/cms/blocks/editors/SectionBlockEditor.tsx)
64
- - **Role:** The editor for the `section` block. It conditionally renders the `SectionConfigPanel` based on the `isConfigPanelOpen` prop and contains the `ColumnEditor`s.
65
-
66
- #### `SectionConfigPanel.tsx` & `BackgroundSelector.tsx`
67
- - **Location:** [`app/cms/blocks/components/SectionConfigPanel.tsx`](/app/cms/blocks/components/SectionConfigPanel.tsx), [`app/cms/blocks/components/BackgroundSelector.tsx`](/app/cms/blocks/components/BackgroundSelector.tsx)
68
- - **Role:** These components render the forms for section-level settings (layout, columns, background).
69
- - **UI Pattern:** The custom inputs (`Minimum Height`, `Image Position`, etc.) use a "disabled save button" pattern. The save icon is disabled by default and only becomes active and green when the user has made a change.
70
-
71
- #### `ColumnEditor.tsx`
72
- - **Location:** [`app/cms/blocks/components/ColumnEditor.tsx`](/app/cms/blocks/components/ColumnEditor.tsx)
73
- - **Role:** Manages the content *within a single column* of a section. It has its own `DndContext` for nested drag-and-drop and uses the same `BlockEditorModal` to edit the blocks it contains.