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.
- package/CLAUDE.md +22 -0
- package/docker-template/.env.docker.example +69 -69
- package/docker-template/docker/db/init/99-jwt.sql +6 -6
- package/docker-template/docker/db/init/99-roles.sql +25 -25
- package/docker-template/docker/kong/kong.yml +112 -112
- package/docker-template/scripts/docker-setup.mjs +310 -310
- package/package.json +1 -1
- package/templates/nextblock-template/.browserslistrc +11 -11
- package/templates/nextblock-template/.swcrc +30 -30
- package/templates/nextblock-template/CLAUDE.md +26 -0
- package/templates/nextblock-template/app/(auth-pages)/sign-up/page.tsx +46 -46
- package/templates/nextblock-template/app/(auth-pages)/two-factor/page.tsx +51 -51
- package/templates/nextblock-template/app/.well-known/ucp/route.ts +16 -16
- package/templates/nextblock-template/app/actions/consent.ts +57 -57
- package/templates/nextblock-template/app/actions/twoFactorEmail.ts +22 -22
- package/templates/nextblock-template/app/api/ai/cortex/build-widget/route.ts +153 -153
- package/templates/nextblock-template/app/api/ai/generate-blocks/route.ts +96 -96
- package/templates/nextblock-template/app/api/brand/email-logo/route.ts +48 -48
- package/templates/nextblock-template/app/api/checkout/freemius/sync/route.ts +29 -29
- package/templates/nextblock-template/app/api/cms/check-updates/route.ts +44 -44
- package/templates/nextblock-template/app/api/cms/full-backup/export/route.ts +33 -33
- package/templates/nextblock-template/app/api/cms/full-backup/restore/route.ts +63 -63
- package/templates/nextblock-template/app/api/cron/reset-sandbox/route.ts +272 -205
- package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +10473 -8467
- package/templates/nextblock-template/app/api/cron/sync-currencies/route.ts +39 -39
- package/templates/nextblock-template/app/api/custom-blocks/db-relations/route.ts +92 -92
- package/templates/nextblock-template/app/api/custom-blocks/editor-definitions/route.ts +43 -43
- package/templates/nextblock-template/app/api/media/library/route.ts +69 -69
- package/templates/nextblock-template/app/api/media/r2-presigned/route.ts +53 -53
- package/templates/nextblock-template/app/api/visual-editing/block-draft/route.ts +47 -47
- package/templates/nextblock-template/app/api/visual-editing/product-draft/route.ts +47 -47
- package/templates/nextblock-template/app/article/[slug]/PostClientContent.tsx +442 -441
- package/templates/nextblock-template/app/article/[slug]/page.utils.ts +4 -1
- package/templates/nextblock-template/app/checkout/UcpCartHydrator.tsx +20 -20
- package/templates/nextblock-template/app/cms/blocks/components/BlockEditorModal.tsx +241 -241
- package/templates/nextblock-template/app/cms/blocks/components/CustomBlockEditorPreview.tsx +160 -160
- package/templates/nextblock-template/app/cms/blocks/editors/DynamicCustomBlockEditor.tsx +167 -167
- package/templates/nextblock-template/app/cms/components/ConnectGitHubButton.tsx +122 -122
- package/templates/nextblock-template/app/cms/components/CortexAiActiveContext.tsx +23 -23
- package/templates/nextblock-template/app/cms/components/SeoScoreBadge.tsx +3 -3
- package/templates/nextblock-template/app/cms/components/SystemAlertsBanner.tsx +112 -112
- package/templates/nextblock-template/app/cms/components/TablePagination.tsx +136 -136
- package/templates/nextblock-template/app/cms/components/TwoFactorReminderBanner.tsx +45 -45
- package/templates/nextblock-template/app/cms/components/github-connect-actions.ts +102 -102
- package/templates/nextblock-template/app/cms/components/system-alerts-actions.ts +31 -31
- package/templates/nextblock-template/app/cms/coupons/[id]/edit/page.tsx +16 -16
- package/templates/nextblock-template/app/cms/coupons/page.tsx +16 -16
- package/templates/nextblock-template/app/cms/custom-blocks/[id]/edit/page.tsx +66 -66
- package/templates/nextblock-template/app/cms/custom-blocks/actions.ts +519 -519
- package/templates/nextblock-template/app/cms/custom-blocks/components/BlocksLibraryTransferControls.tsx +256 -256
- package/templates/nextblock-template/app/cms/custom-blocks/components/DBRelationSelect.tsx +384 -384
- package/templates/nextblock-template/app/cms/custom-blocks/components/ImageR2Picker.tsx +221 -221
- package/templates/nextblock-template/app/cms/custom-blocks/new/page.tsx +12 -12
- package/templates/nextblock-template/app/cms/custom-blocks/page.tsx +438 -438
- package/templates/nextblock-template/app/cms/dashboard/components/DashboardComponents.tsx +200 -200
- package/templates/nextblock-template/app/cms/dashboard/components/DashboardOnboarding.tsx +130 -130
- package/templates/nextblock-template/app/cms/import-export/actions.ts +226 -226
- package/templates/nextblock-template/app/cms/pages/page.tsx +273 -273
- package/templates/nextblock-template/app/cms/posts/page.tsx +251 -251
- package/templates/nextblock-template/app/cms/products/categories/page.tsx +12 -12
- package/templates/nextblock-template/app/cms/products/new/page.tsx +135 -135
- package/templates/nextblock-template/app/cms/promotions/PromotionsWorkspace.tsx +456 -456
- package/templates/nextblock-template/app/cms/promotions/actions.ts +115 -115
- package/templates/nextblock-template/app/cms/promotions/page.tsx +31 -31
- package/templates/nextblock-template/app/cms/settings/backup-restore/BackupRestoreWorkspace.tsx +1004 -1004
- package/templates/nextblock-template/app/cms/settings/backup-restore/page.tsx +29 -29
- package/templates/nextblock-template/app/cms/settings/bot-protection/page.tsx +24 -24
- package/templates/nextblock-template/app/cms/settings/email/page.tsx +28 -28
- package/templates/nextblock-template/app/cms/settings/extra-translations/actions.ts +276 -276
- package/templates/nextblock-template/app/cms/settings/google-analytics/page.tsx +26 -26
- package/templates/nextblock-template/app/cms/settings/logos/components/DeleteLogoButton.tsx +21 -21
- package/templates/nextblock-template/app/cms/settings/logos/components/SetActiveLogoButton.tsx +42 -42
- package/templates/nextblock-template/app/cms/settings/logos/components/SiteSeoSettingsForm.tsx +133 -133
- package/templates/nextblock-template/app/cms/settings/privacy/page.tsx +27 -27
- package/templates/nextblock-template/app/cms/settings/registration/page.tsx +27 -27
- package/templates/nextblock-template/app/cms/settings/security/page.tsx +33 -33
- package/templates/nextblock-template/app/lib/site-settings.ts +105 -105
- package/templates/nextblock-template/app/lib/ucp/protocol.ts +190 -190
- package/templates/nextblock-template/app/lib/ucp/server.test.ts +56 -56
- package/templates/nextblock-template/app/setup/SetupWizard.tsx +678 -678
- package/templates/nextblock-template/app/setup/layout.tsx +13 -13
- package/templates/nextblock-template/app/setup/page.tsx +111 -111
- package/templates/nextblock-template/app/ucp/v1/carts/[id]/cancel/route.ts +38 -38
- package/templates/nextblock-template/app/ucp/v1/carts/[id]/route.ts +68 -68
- package/templates/nextblock-template/app/ucp/v1/carts/route.ts +35 -35
- package/templates/nextblock-template/app/ucp/v1/catalog/lookup/route.ts +35 -35
- package/templates/nextblock-template/app/ucp/v1/catalog/product/route.ts +35 -35
- package/templates/nextblock-template/app/ucp/v1/catalog/search/route.ts +34 -34
- package/templates/nextblock-template/components/CartTranslator.tsx +210 -210
- package/templates/nextblock-template/components/DeferredCartTranslator.tsx +51 -51
- package/templates/nextblock-template/components/DeferredGlobalSearch.tsx +68 -68
- package/templates/nextblock-template/components/DeferredGoogleAnalytics.tsx +70 -70
- package/templates/nextblock-template/components/FeatureImageHero.tsx +47 -47
- package/templates/nextblock-template/components/GlobalSearch.tsx +557 -557
- package/templates/nextblock-template/components/Header.tsx +38 -38
- package/templates/nextblock-template/components/PublicEnvBootstrap.tsx +30 -30
- package/templates/nextblock-template/components/ResponsiveNav.tsx +14 -14
- package/templates/nextblock-template/components/auth/AuthBotProtection.tsx +182 -182
- package/templates/nextblock-template/components/blocks/PostsGridClient.tsx +48 -48
- package/templates/nextblock-template/components/blocks/TestimonialBlock.tsx +9 -9
- package/templates/nextblock-template/components/blocks/publicRendererLoaders.ts +25 -25
- package/templates/nextblock-template/components/blocks/renderers/ButtonBlockRenderer.tsx +92 -92
- package/templates/nextblock-template/components/blocks/renderers/ClientTextBlockRenderer.tsx +11 -0
- package/templates/nextblock-template/components/blocks/renderers/PostsGridBlockRenderer.tsx +24 -24
- package/templates/nextblock-template/components/blocks/renderers/TestimonialBlockRenderer.tsx +57 -57
- package/templates/nextblock-template/components/blocks/renderers/inline/AlertWidgetRenderer.tsx +2 -2
- package/templates/nextblock-template/components/blocks/renderers/inline/CtaWidgetRenderer.tsx +2 -2
- package/templates/nextblock-template/components/media/YouTubeFacade.tsx +105 -105
- package/templates/nextblock-template/components/media/youtube-embed-replace.tsx +32 -32
- package/templates/nextblock-template/components/privacy/ConsentBanner.tsx +170 -170
- package/templates/nextblock-template/components/privacy/ConsentGatedAnalytics.tsx +70 -70
- package/templates/nextblock-template/components/renderers/CachedDynamicLayoutEngine.tsx +28 -28
- package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.test.tsx +166 -166
- package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.tsx +471 -471
- package/templates/nextblock-template/components/visual-editing/DeferredVisualEditing.tsx +21 -21
- package/templates/nextblock-template/context/language-rest-client.ts +32 -32
- package/templates/nextblock-template/docker/db/init/99-jwt.sql +6 -6
- package/templates/nextblock-template/docker/db/init/99-roles.sql +25 -25
- package/templates/nextblock-template/docker/kong/kong.yml +112 -112
- package/templates/nextblock-template/docs/02-ECOMMERCE-CAPABILITIES.md +364 -364
- package/templates/nextblock-template/docs/03-CMS-AND-EDITOR.md +1 -1
- package/templates/nextblock-template/docs/04-DATABASE-AND-AUTH.md +402 -282
- package/templates/nextblock-template/docs/05-DEVELOPER-GUIDE.md +15 -8
- package/templates/nextblock-template/docs/07-BLOCK-SDK-AND-EXTENSIBILITY.md +146 -146
- package/templates/nextblock-template/docs/08-NEXTBLOCK-CORTEX-AI-ARCHITECTURE.md +23 -4
- package/templates/nextblock-template/docs/10-CUSTOM-BLOCKS.md +222 -222
- package/templates/nextblock-template/docs/11-SELF-HOSTED-DOCKER.md +4 -1
- package/templates/nextblock-template/docs/13-STAYING-UP-TO-DATE.md +8 -0
- package/templates/nextblock-template/docs/14-MESSAGES-INBOX.md +2 -2
- package/templates/nextblock-template/docs/TECHNICAL_SPECIFICATION.md +95 -104
- package/templates/nextblock-template/lib/app-secrets.ts +39 -39
- package/templates/nextblock-template/lib/auth/cookies.ts +47 -47
- package/templates/nextblock-template/lib/auth/crypto.ts +45 -45
- package/templates/nextblock-template/lib/auth/trustedDevices.ts +92 -92
- package/templates/nextblock-template/lib/blocks/README.md +13 -13
- package/templates/nextblock-template/lib/botProtection/verify.ts +134 -134
- package/templates/nextblock-template/lib/cms/payments-reminder.test.ts +135 -135
- package/templates/nextblock-template/lib/cms/payments-reminder.ts +105 -105
- package/templates/nextblock-template/lib/cms-transfer/types.ts +145 -145
- package/templates/nextblock-template/lib/custom-block-definitions.ts +87 -87
- package/templates/nextblock-template/lib/custom-block-r2-upload-shared.ts +178 -178
- package/templates/nextblock-template/lib/custom-block-r2-upload.test.ts +140 -140
- package/templates/nextblock-template/lib/custom-block-r2-upload.ts +88 -88
- package/templates/nextblock-template/lib/custom-block-relations.test.ts +227 -227
- package/templates/nextblock-template/lib/custom-block-relations.ts +279 -279
- package/templates/nextblock-template/lib/custom-block-safelist.ts +14 -14
- package/templates/nextblock-template/lib/editor/dynamic-extension-core.test.ts +172 -172
- package/templates/nextblock-template/lib/editor/dynamic-extension-core.ts +213 -213
- package/templates/nextblock-template/lib/editor/dynamic-extension-loader.ts +22 -22
- package/templates/nextblock-template/lib/editor/dynamic-extensions.tsx +193 -193
- package/templates/nextblock-template/lib/email/branding-format.test.ts +133 -133
- package/templates/nextblock-template/lib/email/branding-format.ts +123 -123
- package/templates/nextblock-template/lib/email/branding.ts +76 -76
- package/templates/nextblock-template/lib/full-backup/manifest.test.ts +121 -121
- package/templates/nextblock-template/lib/full-backup/manifest.ts +206 -206
- package/templates/nextblock-template/lib/logos/active-logo.ts +53 -53
- package/templates/nextblock-template/lib/media/resolveMediaUrl.ts +56 -54
- package/templates/nextblock-template/lib/media/youtube.ts +99 -99
- package/templates/nextblock-template/lib/onboarding/actions.ts +31 -31
- package/templates/nextblock-template/lib/privacy/consent-client.ts +57 -57
- package/templates/nextblock-template/lib/privacy/contact-emails.ts +64 -64
- package/templates/nextblock-template/lib/privacy/settings.ts +115 -115
- package/templates/nextblock-template/lib/privacy/types.ts +69 -69
- package/templates/nextblock-template/lib/promotions/server.test.ts +74 -74
- package/templates/nextblock-template/lib/promotions/server.ts +741 -741
- package/templates/nextblock-template/lib/resolve-block-relations.test.ts +142 -142
- package/templates/nextblock-template/lib/resolve-block-relations.ts +255 -255
- package/templates/nextblock-template/lib/seo/page-document.ts +4 -4
- package/templates/nextblock-template/lib/seo/redirect-store.ts +3 -2
- package/templates/nextblock-template/lib/setup/actions.ts +460 -460
- package/templates/nextblock-template/lib/setup/env-status.ts +125 -125
- package/templates/nextblock-template/lib/setup/env-write.ts +111 -111
- package/templates/nextblock-template/lib/setup/migrations-bundle.ts +15 -175
- package/templates/nextblock-template/lib/setup/provisioning.ts +59 -59
- package/templates/nextblock-template/lib/setup/schema-apply.ts +408 -408
- package/templates/nextblock-template/lib/setup/system-config.ts +105 -105
- package/templates/nextblock-template/lib/setup/types.ts +18 -18
- package/templates/nextblock-template/lib/storage/provider.ts +66 -66
- package/templates/nextblock-template/lib/storage/supabase-storage.ts +103 -103
- package/templates/nextblock-template/lib/updates/github-device.ts +206 -206
- package/templates/nextblock-template/lib/updates/repo-identity.ts +56 -56
- package/templates/nextblock-template/lib/visual-editing/draft-content.test.ts +105 -105
- package/templates/nextblock-template/lib/visual-editing/draft-route.test.ts +42 -42
- package/templates/nextblock-template/lib/visual-editing/edit-info.test.ts +143 -143
- package/templates/nextblock-template/lib/visual-editing/edit-info.ts +94 -94
- package/templates/nextblock-template/lib/visual-editing/product-drafts.test.ts +81 -81
- package/templates/nextblock-template/lib/zod-config.ts +5 -5
- package/templates/nextblock-template/next-env.d.ts +1 -0
- package/templates/nextblock-template/package.json +1 -1
- package/templates/nextblock-template/public/images/cortex_post.webp +0 -0
- package/templates/nextblock-template/public/images/update_nextblock.webp +0 -0
- package/templates/nextblock-template/scripts/docker-setup.mjs +310 -310
- package/templates/nextblock-template/scripts/validate-editor-block-schema.ts +112 -112
- package/templates/nextblock-template/scripts/verify-cortex-ai-build-widget.tsx +98 -98
- package/templates/nextblock-template/scripts/verify-cortex-ai-generate-blocks.ts +62 -62
- package/templates/nextblock-template/scripts/verify-cortex-ai-global-tools.ts +537 -537
- package/templates/nextblock-template/scripts/verify-cortex-ai-routing.ts +58 -58
- package/templates/nextblock-template/scripts/verify-custom-block-definitions.ts +188 -188
- package/templates/nextblock-template/scripts/verify-dynamic-custom-block-extensions.ts +123 -123
- package/templates/nextblock-template/scripts/verify-dynamic-layout-engine.tsx +133 -133
- package/templates/nextblock-template/scripts/verify-milestone-2-custom-blocks.ts +65 -65
- package/templates/nextblock-template/tools/deploy-supabase.js +159 -159
- 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
|
-
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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/
|
|
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 `
|
|
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 `
|
|
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/
|
|
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`):
|