create-nextblock 0.16.4 → 0.17.1

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 (203) hide show
  1. package/CLAUDE.md +22 -0
  2. package/docker-template/.env.docker.example +69 -69
  3. package/docker-template/docker/db/init/99-jwt.sql +6 -6
  4. package/docker-template/docker/db/init/99-roles.sql +25 -25
  5. package/docker-template/docker/kong/kong.yml +112 -112
  6. package/docker-template/scripts/docker-setup.mjs +310 -310
  7. package/package.json +1 -1
  8. package/templates/nextblock-template/.browserslistrc +11 -11
  9. package/templates/nextblock-template/.swcrc +30 -30
  10. package/templates/nextblock-template/CLAUDE.md +26 -0
  11. package/templates/nextblock-template/app/(auth-pages)/sign-up/page.tsx +46 -46
  12. package/templates/nextblock-template/app/(auth-pages)/two-factor/page.tsx +51 -51
  13. package/templates/nextblock-template/app/.well-known/ucp/route.ts +16 -16
  14. package/templates/nextblock-template/app/actions/consent.ts +57 -57
  15. package/templates/nextblock-template/app/actions/twoFactorEmail.ts +22 -22
  16. package/templates/nextblock-template/app/api/ai/cortex/build-widget/route.ts +153 -153
  17. package/templates/nextblock-template/app/api/ai/generate-blocks/route.ts +96 -96
  18. package/templates/nextblock-template/app/api/brand/email-logo/route.ts +48 -48
  19. package/templates/nextblock-template/app/api/checkout/freemius/sync/route.ts +29 -29
  20. package/templates/nextblock-template/app/api/cms/check-updates/route.ts +44 -44
  21. package/templates/nextblock-template/app/api/cms/full-backup/export/route.ts +33 -33
  22. package/templates/nextblock-template/app/api/cms/full-backup/restore/route.ts +63 -63
  23. package/templates/nextblock-template/app/api/cron/reset-sandbox/route.ts +272 -205
  24. package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +10473 -8467
  25. package/templates/nextblock-template/app/api/cron/sync-currencies/route.ts +39 -39
  26. package/templates/nextblock-template/app/api/custom-blocks/db-relations/route.ts +92 -92
  27. package/templates/nextblock-template/app/api/custom-blocks/editor-definitions/route.ts +43 -43
  28. package/templates/nextblock-template/app/api/media/library/route.ts +69 -69
  29. package/templates/nextblock-template/app/api/media/r2-presigned/route.ts +53 -53
  30. package/templates/nextblock-template/app/api/visual-editing/block-draft/route.ts +47 -47
  31. package/templates/nextblock-template/app/api/visual-editing/product-draft/route.ts +47 -47
  32. package/templates/nextblock-template/app/article/[slug]/PostClientContent.tsx +442 -441
  33. package/templates/nextblock-template/app/article/[slug]/page.utils.ts +4 -1
  34. package/templates/nextblock-template/app/checkout/UcpCartHydrator.tsx +20 -20
  35. package/templates/nextblock-template/app/cms/blocks/components/BlockEditorModal.tsx +241 -241
  36. package/templates/nextblock-template/app/cms/blocks/components/CustomBlockEditorPreview.tsx +160 -160
  37. package/templates/nextblock-template/app/cms/blocks/editors/DynamicCustomBlockEditor.tsx +167 -167
  38. package/templates/nextblock-template/app/cms/components/ConnectGitHubButton.tsx +122 -122
  39. package/templates/nextblock-template/app/cms/components/CortexAiActiveContext.tsx +23 -23
  40. package/templates/nextblock-template/app/cms/components/SeoScoreBadge.tsx +3 -3
  41. package/templates/nextblock-template/app/cms/components/SystemAlertsBanner.tsx +112 -112
  42. package/templates/nextblock-template/app/cms/components/TablePagination.tsx +136 -136
  43. package/templates/nextblock-template/app/cms/components/TwoFactorReminderBanner.tsx +45 -45
  44. package/templates/nextblock-template/app/cms/components/github-connect-actions.ts +102 -102
  45. package/templates/nextblock-template/app/cms/components/system-alerts-actions.ts +31 -31
  46. package/templates/nextblock-template/app/cms/coupons/[id]/edit/page.tsx +16 -16
  47. package/templates/nextblock-template/app/cms/coupons/page.tsx +16 -16
  48. package/templates/nextblock-template/app/cms/custom-blocks/[id]/edit/page.tsx +66 -66
  49. package/templates/nextblock-template/app/cms/custom-blocks/actions.ts +519 -519
  50. package/templates/nextblock-template/app/cms/custom-blocks/components/BlocksLibraryTransferControls.tsx +256 -256
  51. package/templates/nextblock-template/app/cms/custom-blocks/components/DBRelationSelect.tsx +384 -384
  52. package/templates/nextblock-template/app/cms/custom-blocks/components/ImageR2Picker.tsx +221 -221
  53. package/templates/nextblock-template/app/cms/custom-blocks/new/page.tsx +12 -12
  54. package/templates/nextblock-template/app/cms/custom-blocks/page.tsx +438 -438
  55. package/templates/nextblock-template/app/cms/dashboard/components/DashboardComponents.tsx +200 -200
  56. package/templates/nextblock-template/app/cms/dashboard/components/DashboardOnboarding.tsx +130 -130
  57. package/templates/nextblock-template/app/cms/import-export/actions.ts +226 -226
  58. package/templates/nextblock-template/app/cms/pages/page.tsx +273 -273
  59. package/templates/nextblock-template/app/cms/posts/page.tsx +251 -251
  60. package/templates/nextblock-template/app/cms/products/categories/page.tsx +12 -12
  61. package/templates/nextblock-template/app/cms/products/new/page.tsx +135 -135
  62. package/templates/nextblock-template/app/cms/promotions/PromotionsWorkspace.tsx +456 -456
  63. package/templates/nextblock-template/app/cms/promotions/actions.ts +115 -115
  64. package/templates/nextblock-template/app/cms/promotions/page.tsx +31 -31
  65. package/templates/nextblock-template/app/cms/settings/backup-restore/BackupRestoreWorkspace.tsx +1004 -1004
  66. package/templates/nextblock-template/app/cms/settings/backup-restore/page.tsx +29 -29
  67. package/templates/nextblock-template/app/cms/settings/bot-protection/page.tsx +24 -24
  68. package/templates/nextblock-template/app/cms/settings/email/page.tsx +28 -28
  69. package/templates/nextblock-template/app/cms/settings/extra-translations/actions.ts +276 -276
  70. package/templates/nextblock-template/app/cms/settings/google-analytics/page.tsx +26 -26
  71. package/templates/nextblock-template/app/cms/settings/logos/components/DeleteLogoButton.tsx +21 -21
  72. package/templates/nextblock-template/app/cms/settings/logos/components/SetActiveLogoButton.tsx +42 -42
  73. package/templates/nextblock-template/app/cms/settings/logos/components/SiteSeoSettingsForm.tsx +133 -133
  74. package/templates/nextblock-template/app/cms/settings/privacy/page.tsx +27 -27
  75. package/templates/nextblock-template/app/cms/settings/registration/page.tsx +27 -27
  76. package/templates/nextblock-template/app/cms/settings/security/page.tsx +33 -33
  77. package/templates/nextblock-template/app/lib/site-settings.ts +105 -105
  78. package/templates/nextblock-template/app/lib/ucp/protocol.ts +190 -190
  79. package/templates/nextblock-template/app/lib/ucp/server.test.ts +56 -56
  80. package/templates/nextblock-template/app/setup/SetupWizard.tsx +678 -678
  81. package/templates/nextblock-template/app/setup/layout.tsx +13 -13
  82. package/templates/nextblock-template/app/setup/page.tsx +111 -111
  83. package/templates/nextblock-template/app/ucp/v1/carts/[id]/cancel/route.ts +38 -38
  84. package/templates/nextblock-template/app/ucp/v1/carts/[id]/route.ts +68 -68
  85. package/templates/nextblock-template/app/ucp/v1/carts/route.ts +35 -35
  86. package/templates/nextblock-template/app/ucp/v1/catalog/lookup/route.ts +35 -35
  87. package/templates/nextblock-template/app/ucp/v1/catalog/product/route.ts +35 -35
  88. package/templates/nextblock-template/app/ucp/v1/catalog/search/route.ts +34 -34
  89. package/templates/nextblock-template/components/CartTranslator.tsx +210 -210
  90. package/templates/nextblock-template/components/DeferredCartTranslator.tsx +51 -51
  91. package/templates/nextblock-template/components/DeferredGlobalSearch.tsx +68 -68
  92. package/templates/nextblock-template/components/DeferredGoogleAnalytics.tsx +70 -70
  93. package/templates/nextblock-template/components/FeatureImageHero.tsx +47 -47
  94. package/templates/nextblock-template/components/GlobalSearch.tsx +557 -557
  95. package/templates/nextblock-template/components/Header.tsx +38 -38
  96. package/templates/nextblock-template/components/PublicEnvBootstrap.tsx +30 -30
  97. package/templates/nextblock-template/components/ResponsiveNav.tsx +14 -14
  98. package/templates/nextblock-template/components/auth/AuthBotProtection.tsx +182 -182
  99. package/templates/nextblock-template/components/blocks/PostsGridClient.tsx +48 -48
  100. package/templates/nextblock-template/components/blocks/TestimonialBlock.tsx +9 -9
  101. package/templates/nextblock-template/components/blocks/publicRendererLoaders.ts +25 -25
  102. package/templates/nextblock-template/components/blocks/renderers/ButtonBlockRenderer.tsx +92 -92
  103. package/templates/nextblock-template/components/blocks/renderers/ClientTextBlockRenderer.tsx +11 -0
  104. package/templates/nextblock-template/components/blocks/renderers/PostsGridBlockRenderer.tsx +24 -24
  105. package/templates/nextblock-template/components/blocks/renderers/TestimonialBlockRenderer.tsx +57 -57
  106. package/templates/nextblock-template/components/blocks/renderers/inline/AlertWidgetRenderer.tsx +2 -2
  107. package/templates/nextblock-template/components/blocks/renderers/inline/CtaWidgetRenderer.tsx +2 -2
  108. package/templates/nextblock-template/components/media/YouTubeFacade.tsx +105 -105
  109. package/templates/nextblock-template/components/media/youtube-embed-replace.tsx +32 -32
  110. package/templates/nextblock-template/components/privacy/ConsentBanner.tsx +170 -170
  111. package/templates/nextblock-template/components/privacy/ConsentGatedAnalytics.tsx +70 -70
  112. package/templates/nextblock-template/components/renderers/CachedDynamicLayoutEngine.tsx +28 -28
  113. package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.test.tsx +166 -166
  114. package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.tsx +471 -471
  115. package/templates/nextblock-template/components/visual-editing/DeferredVisualEditing.tsx +21 -21
  116. package/templates/nextblock-template/context/language-rest-client.ts +32 -32
  117. package/templates/nextblock-template/docker/db/init/99-jwt.sql +6 -6
  118. package/templates/nextblock-template/docker/db/init/99-roles.sql +25 -25
  119. package/templates/nextblock-template/docker/kong/kong.yml +112 -112
  120. package/templates/nextblock-template/docs/02-ECOMMERCE-CAPABILITIES.md +364 -364
  121. package/templates/nextblock-template/docs/03-CMS-AND-EDITOR.md +1 -1
  122. package/templates/nextblock-template/docs/04-DATABASE-AND-AUTH.md +402 -282
  123. package/templates/nextblock-template/docs/05-DEVELOPER-GUIDE.md +15 -8
  124. package/templates/nextblock-template/docs/07-BLOCK-SDK-AND-EXTENSIBILITY.md +146 -146
  125. package/templates/nextblock-template/docs/08-NEXTBLOCK-CORTEX-AI-ARCHITECTURE.md +23 -4
  126. package/templates/nextblock-template/docs/10-CUSTOM-BLOCKS.md +222 -222
  127. package/templates/nextblock-template/docs/11-SELF-HOSTED-DOCKER.md +4 -1
  128. package/templates/nextblock-template/docs/13-STAYING-UP-TO-DATE.md +8 -0
  129. package/templates/nextblock-template/docs/14-MESSAGES-INBOX.md +2 -2
  130. package/templates/nextblock-template/docs/TECHNICAL_SPECIFICATION.md +95 -104
  131. package/templates/nextblock-template/lib/app-secrets.ts +39 -39
  132. package/templates/nextblock-template/lib/auth/cookies.ts +47 -47
  133. package/templates/nextblock-template/lib/auth/crypto.ts +45 -45
  134. package/templates/nextblock-template/lib/auth/trustedDevices.ts +92 -92
  135. package/templates/nextblock-template/lib/blocks/README.md +13 -13
  136. package/templates/nextblock-template/lib/botProtection/verify.ts +134 -134
  137. package/templates/nextblock-template/lib/cms/payments-reminder.test.ts +135 -135
  138. package/templates/nextblock-template/lib/cms/payments-reminder.ts +105 -105
  139. package/templates/nextblock-template/lib/cms-transfer/types.ts +145 -145
  140. package/templates/nextblock-template/lib/custom-block-definitions.ts +87 -87
  141. package/templates/nextblock-template/lib/custom-block-r2-upload-shared.ts +178 -178
  142. package/templates/nextblock-template/lib/custom-block-r2-upload.test.ts +140 -140
  143. package/templates/nextblock-template/lib/custom-block-r2-upload.ts +88 -88
  144. package/templates/nextblock-template/lib/custom-block-relations.test.ts +227 -227
  145. package/templates/nextblock-template/lib/custom-block-relations.ts +279 -279
  146. package/templates/nextblock-template/lib/custom-block-safelist.ts +14 -14
  147. package/templates/nextblock-template/lib/editor/dynamic-extension-core.test.ts +172 -172
  148. package/templates/nextblock-template/lib/editor/dynamic-extension-core.ts +213 -213
  149. package/templates/nextblock-template/lib/editor/dynamic-extension-loader.ts +22 -22
  150. package/templates/nextblock-template/lib/editor/dynamic-extensions.tsx +193 -193
  151. package/templates/nextblock-template/lib/email/branding-format.test.ts +133 -133
  152. package/templates/nextblock-template/lib/email/branding-format.ts +123 -123
  153. package/templates/nextblock-template/lib/email/branding.ts +76 -76
  154. package/templates/nextblock-template/lib/full-backup/manifest.test.ts +121 -121
  155. package/templates/nextblock-template/lib/full-backup/manifest.ts +206 -206
  156. package/templates/nextblock-template/lib/logos/active-logo.ts +53 -53
  157. package/templates/nextblock-template/lib/media/resolveMediaUrl.ts +56 -54
  158. package/templates/nextblock-template/lib/media/youtube.ts +99 -99
  159. package/templates/nextblock-template/lib/onboarding/actions.ts +31 -31
  160. package/templates/nextblock-template/lib/privacy/consent-client.ts +57 -57
  161. package/templates/nextblock-template/lib/privacy/contact-emails.ts +64 -64
  162. package/templates/nextblock-template/lib/privacy/settings.ts +115 -115
  163. package/templates/nextblock-template/lib/privacy/types.ts +69 -69
  164. package/templates/nextblock-template/lib/promotions/server.test.ts +74 -74
  165. package/templates/nextblock-template/lib/promotions/server.ts +741 -741
  166. package/templates/nextblock-template/lib/resolve-block-relations.test.ts +142 -142
  167. package/templates/nextblock-template/lib/resolve-block-relations.ts +255 -255
  168. package/templates/nextblock-template/lib/seo/page-document.ts +4 -4
  169. package/templates/nextblock-template/lib/seo/redirect-store.ts +3 -2
  170. package/templates/nextblock-template/lib/setup/actions.ts +460 -460
  171. package/templates/nextblock-template/lib/setup/env-status.ts +125 -125
  172. package/templates/nextblock-template/lib/setup/env-write.ts +111 -111
  173. package/templates/nextblock-template/lib/setup/migrations-bundle.ts +15 -175
  174. package/templates/nextblock-template/lib/setup/provisioning.ts +59 -59
  175. package/templates/nextblock-template/lib/setup/schema-apply.ts +408 -408
  176. package/templates/nextblock-template/lib/setup/system-config.ts +105 -105
  177. package/templates/nextblock-template/lib/setup/types.ts +18 -18
  178. package/templates/nextblock-template/lib/storage/provider.ts +66 -66
  179. package/templates/nextblock-template/lib/storage/supabase-storage.ts +103 -103
  180. package/templates/nextblock-template/lib/updates/github-device.ts +206 -206
  181. package/templates/nextblock-template/lib/updates/repo-identity.ts +56 -56
  182. package/templates/nextblock-template/lib/visual-editing/draft-content.test.ts +105 -105
  183. package/templates/nextblock-template/lib/visual-editing/draft-route.test.ts +42 -42
  184. package/templates/nextblock-template/lib/visual-editing/edit-info.test.ts +143 -143
  185. package/templates/nextblock-template/lib/visual-editing/edit-info.ts +94 -94
  186. package/templates/nextblock-template/lib/visual-editing/product-drafts.test.ts +81 -81
  187. package/templates/nextblock-template/lib/zod-config.ts +5 -5
  188. package/templates/nextblock-template/next-env.d.ts +1 -0
  189. package/templates/nextblock-template/package.json +1 -1
  190. package/templates/nextblock-template/public/images/cortex_post.webp +0 -0
  191. package/templates/nextblock-template/public/images/update_nextblock.webp +0 -0
  192. package/templates/nextblock-template/scripts/docker-setup.mjs +310 -310
  193. package/templates/nextblock-template/scripts/validate-editor-block-schema.ts +112 -112
  194. package/templates/nextblock-template/scripts/verify-cortex-ai-build-widget.tsx +98 -98
  195. package/templates/nextblock-template/scripts/verify-cortex-ai-generate-blocks.ts +62 -62
  196. package/templates/nextblock-template/scripts/verify-cortex-ai-global-tools.ts +537 -537
  197. package/templates/nextblock-template/scripts/verify-cortex-ai-routing.ts +58 -58
  198. package/templates/nextblock-template/scripts/verify-custom-block-definitions.ts +188 -188
  199. package/templates/nextblock-template/scripts/verify-dynamic-custom-block-extensions.ts +123 -123
  200. package/templates/nextblock-template/scripts/verify-dynamic-layout-engine.tsx +133 -133
  201. package/templates/nextblock-template/scripts/verify-milestone-2-custom-blocks.ts +65 -65
  202. package/templates/nextblock-template/tools/deploy-supabase.js +159 -159
  203. package/templates/nextblock-template/types/jsdom.d.ts +6 -6
@@ -178,11 +178,17 @@ Production rule:
178
178
  - Add a new forward-only `.sql` file under
179
179
  `libs/db/src/supabase/migrations` for each production schema/data change.
180
180
  - Use `npm run db:migrate:check` before `npm run db:migrate`.
181
- - If `db:migrate:check` lists historical baseline migrations such as
182
- `00000000000000_setup_foundation_and_enums.sql` on an existing production database, do
183
- not run `db:migrate` yet. Run `npm run db:migrate:repair-history:check`,
184
- then `npm run db:migrate:repair-history`, then check again. The expected
185
- result after repair is that only new unapplied migrations remain.
181
+ - Migration files are named `GGNNN_<snake_name>.sql` (GG = squash generation, NNN =
182
+ sequence, contiguous). The next number is the highest sequence on disk + 1 in the same
183
+ generation; `db:migrate:check` prints it and fails on any other name shape. See
184
+ [04-DATABASE-AND-AUTH.md](./04-DATABASE-AND-AUTH.md) "Migration Structure".
185
+ - If `db:migrate:check` lists the generation baseline (`02001_baseline_schema.sql` …) as
186
+ pending on an existing database whose history is empty, do not run `db:migrate` yet.
187
+ Run `npm run db:migrate:repair-history:check`, then `npm run db:migrate:repair-history`,
188
+ then check again. If instead it shows retired 14-digit versions "recorded remotely with
189
+ no local file" beside the pending baseline, the database has not crossed the squash:
190
+ run `npm run db:migrate:repair-history:check -- --reconcile-squash`, then the same without
191
+ `:check`. The expected result after either repair is that only new unapplied migrations remain.
186
192
  - Do not use `npm run db:reset`, `npm run sandbox:reset`,
187
193
  `npm run db:migrate:fresh`, or `npm run db:push:sandbox` against production.
188
194
 
@@ -198,9 +204,10 @@ The migration-only script:
198
204
  - runs `supabase db push` without `--include-all`
199
205
  - never runs a reset, seed script, function deploy, or config push
200
206
 
201
- Because the migration set started as a squashed baseline, contributors should
202
- treat the existing baseline files as grouped domains. New production changes
203
- after the baseline should be appended as new migrations.
207
+ The migration set is a squashed baseline (one generation at a time — see
208
+ [04-DATABASE-AND-AUTH.md](./04-DATABASE-AND-AUTH.md) "Migration Structure"). Treat the
209
+ baseline files as grouped domains and append every new production change as a new
210
+ `GGNNN` migration; never edit the baseline or the catch-up.
204
211
 
205
212
  ## Sandbox Reset Operations
206
213
 
@@ -1,146 +1,146 @@
1
- # 07 Block SDK and Extensibility
2
-
3
- ## What the SDK Is
4
-
5
- `libs/sdk` is the typed contract for block-style extensibility. It is much
6
- smaller than the in-app block registry because it defines an external authoring
7
- interface, not the full CMS implementation.
8
-
9
- The main export is:
10
-
11
- - `@nextblock-cms/sdk`
12
-
13
- ## Current SDK Surface
14
-
15
- `libs/sdk/src/lib/sdk.ts` currently exports the following core types:
16
-
17
- - `BlockContentSchema`
18
- - `BlockData<TSchema>`
19
- - `BlockProps<TSchema>`
20
- - `BlockEditorProps<TSchema>`
21
- - `BlockConfig<TSchema>`
22
- - `LucideIcon`
23
-
24
- ## Contract Shape
25
-
26
- ### Schema
27
-
28
- Every block is defined around a Zod object schema:
29
-
30
- ```ts
31
- type BlockContentSchema = z.ZodObject<any>;
32
- ```
33
-
34
- The runtime content type is inferred from that schema through `BlockData`.
35
-
36
- ### Renderer contract
37
-
38
- The public rendering contract is:
39
-
40
- - `content`
41
- - optional `className`
42
- - `isInEditor`
43
- - `languageKey`
44
-
45
- ### Editor contract
46
-
47
- The editing contract is:
48
-
49
- - `content`
50
- - `block`
51
- - `onChange`
52
-
53
- ### Registration contract
54
-
55
- A block registration object currently requires:
56
-
57
- - `type`
58
- - `label`
59
- - optional `icon`
60
- - `schema`
61
- - `initialContent`
62
- - `RendererComponent`
63
- - `EditorComponent`
64
-
65
- ## Relationship to the App Block Registry
66
-
67
- The app already has an internal registry in
68
- `apps/nextblock/lib/blocks/blockRegistry.ts`.
69
-
70
- That registry is richer than the SDK because it also includes:
71
-
72
- - filename-based editor loading
73
- - filename-based renderer loading
74
- - CMS-specific helper metadata
75
- - in-repo block defaults for built-in block types
76
-
77
- The important distinction is:
78
-
79
- - `libs/sdk` defines the reusable contract
80
- - `apps/nextblock/lib/blocks/blockRegistry.ts` defines the current built-in
81
- implementation
82
-
83
- They are related, but they are not the same file or the same level of
84
- abstraction.
85
-
86
- ## Current Built-In Extensibility Pattern
87
-
88
- Today, adding a built-in block to the app usually means updating:
89
-
90
- - the app block registry
91
- - a CMS editor component
92
- - a front-end renderer component
93
- - any supporting schemas or helpers
94
-
95
- The existing registry already exposes enough information to support:
96
-
97
- - runtime validation
98
- - default content generation
99
- - block label lookup
100
- - block picker rendering
101
-
102
- ## Commerce-Aware Extensibility
103
-
104
- The built-in block registry already contains ecommerce-aware blocks:
105
-
106
- - `product_grid`
107
- - `featured_product`
108
- - `cart`
109
- - `checkout`
110
- - `product_details`
111
-
112
- That means the current extensibility surface is not limited to editorial
113
- content. It already supports block types that render premium commerce
114
- components.
115
-
116
- ## Data-Driven Custom Blocks
117
-
118
- There is now a third extensibility path that needs no code deploy at all.
119
- Editors can define block types at runtime from the CMS; each definition is a
120
- `custom_block_definitions` row (typed fields plus a recursive layout schema)
121
- rendered on the public site by a dynamic layout engine rather than a compiled
122
- React component.
123
-
124
- So the extensibility surface has three layers:
125
-
126
- - **Code-defined built-ins** — the app block registry plus React
127
- editor/renderer files. Most flexible, requires a deploy.
128
- - **The typed SDK contract** (`libs/sdk`) — a small, typed authoring interface
129
- for reusable or external blocks.
130
- - **Data-defined custom blocks** (`custom_block_definitions`) — full CRUD from
131
- the CMS, no deploy, rendered from stored JSONB.
132
-
133
- Custom blocks are documented in detail in
134
- [10-CUSTOM-BLOCKS.md](./10-CUSTOM-BLOCKS.md).
135
-
136
- ## Practical Guidance
137
-
138
- - If you are building or refactoring built-in CMS blocks, start with the app
139
- registry and editor/renderer files.
140
- - If you are shaping an external or reusable authoring contract, start with
141
- `libs/sdk`.
142
- - If you need both, keep the SDK contract small and typed, and let the app
143
- registry stay responsible for CMS-specific loading behavior.
144
- - If you want editors to create block types without a deploy, reach for
145
- data-driven custom blocks (`custom_block_definitions`) instead of either of
146
- the above.
1
+ # 07 Block SDK and Extensibility
2
+
3
+ ## What the SDK Is
4
+
5
+ `libs/sdk` is the typed contract for block-style extensibility. It is much
6
+ smaller than the in-app block registry because it defines an external authoring
7
+ interface, not the full CMS implementation.
8
+
9
+ The main export is:
10
+
11
+ - `@nextblock-cms/sdk`
12
+
13
+ ## Current SDK Surface
14
+
15
+ `libs/sdk/src/lib/sdk.ts` currently exports the following core types:
16
+
17
+ - `BlockContentSchema`
18
+ - `BlockData<TSchema>`
19
+ - `BlockProps<TSchema>`
20
+ - `BlockEditorProps<TSchema>`
21
+ - `BlockConfig<TSchema>`
22
+ - `LucideIcon`
23
+
24
+ ## Contract Shape
25
+
26
+ ### Schema
27
+
28
+ Every block is defined around a Zod object schema:
29
+
30
+ ```ts
31
+ type BlockContentSchema = z.ZodObject<any>;
32
+ ```
33
+
34
+ The runtime content type is inferred from that schema through `BlockData`.
35
+
36
+ ### Renderer contract
37
+
38
+ The public rendering contract is:
39
+
40
+ - `content`
41
+ - optional `className`
42
+ - `isInEditor`
43
+ - `languageKey`
44
+
45
+ ### Editor contract
46
+
47
+ The editing contract is:
48
+
49
+ - `content`
50
+ - `block`
51
+ - `onChange`
52
+
53
+ ### Registration contract
54
+
55
+ A block registration object currently requires:
56
+
57
+ - `type`
58
+ - `label`
59
+ - optional `icon`
60
+ - `schema`
61
+ - `initialContent`
62
+ - `RendererComponent`
63
+ - `EditorComponent`
64
+
65
+ ## Relationship to the App Block Registry
66
+
67
+ The app already has an internal registry in
68
+ `apps/nextblock/lib/blocks/blockRegistry.ts`.
69
+
70
+ That registry is richer than the SDK because it also includes:
71
+
72
+ - filename-based editor loading
73
+ - filename-based renderer loading
74
+ - CMS-specific helper metadata
75
+ - in-repo block defaults for built-in block types
76
+
77
+ The important distinction is:
78
+
79
+ - `libs/sdk` defines the reusable contract
80
+ - `apps/nextblock/lib/blocks/blockRegistry.ts` defines the current built-in
81
+ implementation
82
+
83
+ They are related, but they are not the same file or the same level of
84
+ abstraction.
85
+
86
+ ## Current Built-In Extensibility Pattern
87
+
88
+ Today, adding a built-in block to the app usually means updating:
89
+
90
+ - the app block registry
91
+ - a CMS editor component
92
+ - a front-end renderer component
93
+ - any supporting schemas or helpers
94
+
95
+ The existing registry already exposes enough information to support:
96
+
97
+ - runtime validation
98
+ - default content generation
99
+ - block label lookup
100
+ - block picker rendering
101
+
102
+ ## Commerce-Aware Extensibility
103
+
104
+ The built-in block registry already contains ecommerce-aware blocks:
105
+
106
+ - `product_grid`
107
+ - `featured_product`
108
+ - `cart`
109
+ - `checkout`
110
+ - `product_details`
111
+
112
+ That means the current extensibility surface is not limited to editorial
113
+ content. It already supports block types that render premium commerce
114
+ components.
115
+
116
+ ## Data-Driven Custom Blocks
117
+
118
+ There is now a third extensibility path that needs no code deploy at all.
119
+ Editors can define block types at runtime from the CMS; each definition is a
120
+ `custom_block_definitions` row (typed fields plus a recursive layout schema)
121
+ rendered on the public site by a dynamic layout engine rather than a compiled
122
+ React component.
123
+
124
+ So the extensibility surface has three layers:
125
+
126
+ - **Code-defined built-ins** — the app block registry plus React
127
+ editor/renderer files. Most flexible, requires a deploy.
128
+ - **The typed SDK contract** (`libs/sdk`) — a small, typed authoring interface
129
+ for reusable or external blocks.
130
+ - **Data-defined custom blocks** (`custom_block_definitions`) — full CRUD from
131
+ the CMS, no deploy, rendered from stored JSONB.
132
+
133
+ Custom blocks are documented in detail in
134
+ [10-CUSTOM-BLOCKS.md](./10-CUSTOM-BLOCKS.md).
135
+
136
+ ## Practical Guidance
137
+
138
+ - If you are building or refactoring built-in CMS blocks, start with the app
139
+ registry and editor/renderer files.
140
+ - If you are shaping an external or reusable authoring contract, start with
141
+ `libs/sdk`.
142
+ - If you need both, keep the SDK contract small and typed, and let the app
143
+ registry stay responsible for CMS-specific loading behavior.
144
+ - If you want editors to create block types without a deploy, reach for
145
+ data-driven custom blocks (`custom_block_definitions`) instead of either of
146
+ the above.
@@ -82,7 +82,7 @@ Known incomplete or future work:
82
82
 
83
83
  | File | Purpose |
84
84
  | --- | --- |
85
- | `libs/db/src/supabase/migrations/00000000000011_setup_cortex_ai_settings.sql` | RLS hardening for the sensitive `site_settings` Cortex AI key row. |
85
+ | `libs/db/src/supabase/migrations/02003_baseline_security_and_grants.sql` (originally `00000000000011_setup_cortex_ai_settings`, folded in by the generation-2 squash) | RLS hardening for the sensitive `site_settings` Cortex AI key row. |
86
86
  | `apps/nextblock/app/api/cron/reset-sandbox/route.ts` | Sandbox reset route. Upserts active package activation for `cortex-ai` when `FREEMIUS_AI_SANDBOX_KEY` exists. |
87
87
  | `apps/nextblock/app/api/cron/reset-sandbox/sandboxResetSql.ts` | Generated SQL bundle that includes the Cortex AI migration. |
88
88
 
@@ -271,7 +271,7 @@ The value is a JSON envelope:
271
271
  }
272
272
  ```
273
273
 
274
- The migration `00000000000011_setup_cortex_ai_settings.sql` hardens RLS:
274
+ The migration `libs/db/src/supabase/migrations/02003_baseline_security_and_grants.sql` (originally `00000000000011_setup_cortex_ai_settings`, folded in by the generation-2 squash) hardens RLS:
275
275
 
276
276
  - Public users can read non-sensitive site settings.
277
277
  - The sensitive Cortex AI key row is readable only by authenticated admins.
@@ -1061,7 +1061,7 @@ Cortex can insert real photos into pages at zero inference cost, and external im
1061
1061
  - In `libs/cortex/src/lib/ai-global-agent-tools.ts`; registered in `createCortexGlobalAgentTools`.
1062
1062
  - Input: `{ query: string, count?: 1-15 (default 6), orientation?: 'landscape'|'portrait'|'square' }`.
1063
1063
  - Key resolution: `resolveCortexAiStockPhotoProvider(supabase)` prefers an admin-stored, encrypted key in `site_settings` (`cortex_ai_pexels_api_key` / `cortex_ai_unsplash_access_key`, read via the service-role client), then falls back to the `PEXELS_API_KEY` / `UNSPLASH_ACCESS_KEY` env vars. Pexels wins when both exist. Returns a clear "not configured" message if neither is set. Both are free API keys.
1064
- - The stored keys are protected by migration `00000000000012_cortex_ai_stock_photo_settings.sql`, which adds them to the `site_settings` sensitive-keys RLS group (admin-only read/write, never anon-readable), and encrypted with the same envelope as the OpenRouter BYOK key.
1064
+ - The stored keys are protected by migration `libs/db/src/supabase/migrations/02003_baseline_security_and_grants.sql` (originally `00000000000012_cortex_ai_stock_photo_settings`, folded in by the generation-2 squash), which adds them to the `site_settings` sensitive-keys RLS group (admin-only read/write, never anon-readable), and encrypted with the same envelope as the OpenRouter BYOK key.
1065
1065
  - **The model is told up front whether stock photos are available.** The global-agent route resolves the provider and injects it into the system prompt: available → "use search_stock_photos"; not configured → "do NOT call search_stock_photos; use gradient/theme backgrounds." So a missing key never wastes a tool call, and the keys are never mandatory — Cortex builds pages either way.
1066
1066
  - Admin UI: `/cms/settings/cortex-ai` has a Stock Photos card (save/clear Pexels + Unsplash keys, step-by-step, and why) via `saveStockPhotoKeysAction` / `clearStockPhotoKeysAction`.
1067
1067
  - Rate-limit fallback: `resolveCortexAiStockPhotoProviders` returns ALL configured providers ordered Pexels→Unsplash; `executeSearchStockPhotos` tries them in order, falling through to the next on error/HTTP 429/empty results, and returns `attemptedProviders`.
@@ -1106,7 +1106,7 @@ from inside the editor.
1106
1106
  | `apps/nextblock/app/cms/settings/cortex-ai/mcp-actions.ts` | Admin server actions: settings, mint, revoke. |
1107
1107
  | `apps/nextblock/app/cms/settings/cortex-ai/McpServerSettingsCard.tsx` | Settings UI + copy-paste client config. |
1108
1108
  | `apps/nextblock/app/cms/settings/cortex-ai/require-admin.ts` | Shared admin gate (also used by `actions.ts`). |
1109
- | `libs/db/src/supabase/migrations/00000000000017_cortex_ai_mcp_server.sql` | `mcp_access_tokens` table + `cortex_ai_mcp_settings` RLS. |
1109
+ | `libs/db/src/supabase/migrations/02003_baseline_security_and_grants.sql` (originally `00000000000017_cortex_ai_mcp_server`, folded in by the generation-2 squash) | `mcp_access_tokens` table + `cortex_ai_mcp_settings` RLS. |
1110
1110
 
1111
1111
  ### Protocol decisions
1112
1112
 
@@ -1238,6 +1238,25 @@ now carries `PROTECTED_SITE_SETTING_KEYS`, redacted on read and refused on write
1238
1238
  `mcp_access_tokens` is deliberately **absent** from `tableConfigs`, so the generic DB
1239
1239
  tools cannot read token hashes or insert rows.
1240
1240
 
1241
+ ### Marketing surfaces that describe the MCP server
1242
+
1243
+ Three seeded content rows sell the MCP story and are kept at 100/100 in the built-in SEO
1244
+ engine (`libs/utils/src/lib/seo`). Migration `libs/db/src/supabase/migrations/02004_baseline_seed.sql` (originally `00000000000037_reposition_marketing_and_cortex_mcp`, folded in by the generation-2 squash)
1245
+ owns them; the sandbox reset route (`enrichCortexAiProducts`) mirrors the product sections
1246
+ because it deletes and re-inserts product blocks after the SQL replay, so edit both together.
1247
+
1248
+ | Surface | Focus keyphrase (type it into the audit panel; it is not persisted) | Body format |
1249
+ | :-- | :-- | :-- |
1250
+ | Home page `home` (EN) — hero, "why" (seven-row prototype-tools-vs-NextBlock chart + pricing tiles), "how MCP works", Cortex promo sections | `AI website builder CMS` | styled HTML in `section` → `text` blocks; 040 added the chart, 041 put the pricing message on every section: CMS free forever, Cortex AI (in-editor AI + MCP server) is the one paid license with a 30-day no-card trial, "deploy to Vercel in one click, up in ten minutes" |
1251
+ | Product `nextblock-cortex-ai-cortex-ai-license` (EN) | `Cortex AI MCP server` | styled HTML in five `section` blocks; title "NextBlock™ Cortex AI MCP Server & AI Editor License" (041 — never "copilot", the product is Cortex AI) |
1252
+ | Post `cortex-ai-mcp-connection-guide` (EN) | `connect Claude to NextBlock CMS` | styled HTML in one `text` block: comparison chart, a CSS/HTML flow diagram (four cards, `not-prose`), terminal panels; 037 seeded a plain Tiptap doc, 038 replaced it with a rasterised diagram, 041 replaced that with the CSS version and retired the media row |
1253
+ | Articles page `articles` (EN + FR) | none set (grades 100 without; EN also 100 with `NextBlock Journal`) | short hero + `posts_grid` + a "What the journal covers" section with four topic cards below the grid (041 moved the ~300-word essay out of the hero) |
1254
+ | Posts `how-nextblock-works` / `comment-nextblock-fonctionne` | none set (both grade 100) | styled HTML; 042 replaced the `extensibility.webp` figure with a CSS/HTML architecture diagram (core hub with the site logo, four spokes, three panels, stack strip, tagline) built inside the text block — the image file and media row stay because the sandbox reset registers it as a core asset |
1255
+
1256
+ The copy names only the five contract tools above plus the real transport and auth rules
1257
+ (Streamable HTTP, bearer tokens, localhost trust in development, Live Draft staging). If any
1258
+ of those change, the product page and the guide are the two places that go stale.
1259
+
1241
1260
  ## Advanced Agent Settings
1242
1261
 
1243
1262
  The global agent's model limits are admin-tunable from `/cms/settings/cortex-ai` (collapsible "Advanced settings"), stored as a non-secret JSON `site_settings` row `cortex_ai_agent_settings` and read by the route via `resolveCortexAiAgentSettings(supabase)` (defaults + clamping in `normalizeCortexAiAgentSettings`, `libs/cortex/src/lib/ai-config.ts`):