create-nextblock 0.13.10 → 0.13.12

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 (259) hide show
  1. package/docker-template/.dockerignore +23 -23
  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/libs/db/tsconfig.lib.json +3 -3
  8. package/libs/editor/tsconfig.lib.json +3 -3
  9. package/libs/ui/tsconfig.lib.json +3 -3
  10. package/libs/utils/tsconfig.json +3 -3
  11. package/package.json +1 -1
  12. package/project.json +19 -19
  13. package/templates/nextblock-template/.browserslistrc +11 -11
  14. package/templates/nextblock-template/.dockerignore +23 -23
  15. package/templates/nextblock-template/README.md +34 -34
  16. package/templates/nextblock-template/app/(auth-pages)/layout.tsx +9 -9
  17. package/templates/nextblock-template/app/(auth-pages)/post-sign-in/page.tsx +27 -27
  18. package/templates/nextblock-template/app/(auth-pages)/sign-up/page.tsx +46 -46
  19. package/templates/nextblock-template/app/(auth-pages)/two-factor/page.tsx +51 -51
  20. package/templates/nextblock-template/app/ToasterProvider.tsx +17 -17
  21. package/templates/nextblock-template/app/[slug]/pageClientActions.ts +7 -7
  22. package/templates/nextblock-template/app/actions/consent.ts +57 -57
  23. package/templates/nextblock-template/app/actions/postActions.ts +146 -146
  24. package/templates/nextblock-template/app/actions/productGridActions.ts +40 -40
  25. package/templates/nextblock-template/app/actions/twoFactorEmail.ts +22 -22
  26. package/templates/nextblock-template/app/api/ai/cortex/build-widget/route.ts +153 -153
  27. package/templates/nextblock-template/app/api/ai/generate-blocks/route.ts +96 -96
  28. package/templates/nextblock-template/app/api/brand/email-logo/route.ts +48 -48
  29. package/templates/nextblock-template/app/api/cms/check-updates/route.ts +44 -44
  30. package/templates/nextblock-template/app/api/cms/ecommerce/product-picker/route.ts +151 -151
  31. package/templates/nextblock-template/app/api/cms/full-backup/export/route.ts +33 -33
  32. package/templates/nextblock-template/app/api/cms/full-backup/restore/route.ts +63 -63
  33. package/templates/nextblock-template/app/api/cron/reset-sandbox/route.ts +3490 -3490
  34. package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +5749 -5609
  35. package/templates/nextblock-template/app/api/cron/sync-currencies/route.ts +39 -39
  36. package/templates/nextblock-template/app/api/custom-blocks/db-relations/route.ts +92 -92
  37. package/templates/nextblock-template/app/api/custom-blocks/editor-definitions/route.ts +43 -43
  38. package/templates/nextblock-template/app/api/media/library/route.ts +69 -69
  39. package/templates/nextblock-template/app/api/media/r2-presigned/route.ts +53 -53
  40. package/templates/nextblock-template/app/api/media/record/route.ts +160 -160
  41. package/templates/nextblock-template/app/api/search/route.ts +43 -43
  42. package/templates/nextblock-template/app/article/[slug]/PostClientContent.tsx +441 -441
  43. package/templates/nextblock-template/app/auth/callback/route.ts +31 -31
  44. package/templates/nextblock-template/app/cart/page.tsx +7 -7
  45. package/templates/nextblock-template/app/cms/blocks/components/CustomBlockEditorPreview.tsx +160 -160
  46. package/templates/nextblock-template/app/cms/blocks/components/MediaLibraryModal.tsx +149 -149
  47. package/templates/nextblock-template/app/cms/blocks/components/MultiEntityPicker.tsx +263 -263
  48. package/templates/nextblock-template/app/cms/blocks/editors/DynamicCustomBlockEditor.tsx +167 -167
  49. package/templates/nextblock-template/app/cms/blocks/editors/TextBlockEditor.tsx +90 -90
  50. package/templates/nextblock-template/app/cms/components/ConnectGitHubButton.tsx +122 -122
  51. package/templates/nextblock-template/app/cms/components/CortexAiPageContext.tsx +58 -58
  52. package/templates/nextblock-template/app/cms/components/EcommerceActiveContext.tsx +27 -27
  53. package/templates/nextblock-template/app/cms/components/FeedbackModal.tsx +36 -36
  54. package/templates/nextblock-template/app/cms/components/SystemAlertsBanner.tsx +112 -112
  55. package/templates/nextblock-template/app/cms/components/TwoFactorReminderBanner.tsx +45 -45
  56. package/templates/nextblock-template/app/cms/components/github-connect-actions.ts +102 -102
  57. package/templates/nextblock-template/app/cms/components/system-alerts-actions.ts +31 -31
  58. package/templates/nextblock-template/app/cms/custom-blocks/[id]/edit/page.tsx +66 -66
  59. package/templates/nextblock-template/app/cms/custom-blocks/actions.ts +519 -519
  60. package/templates/nextblock-template/app/cms/custom-blocks/components/BlocksLibraryTransferControls.tsx +256 -256
  61. package/templates/nextblock-template/app/cms/custom-blocks/components/DBRelationSelect.tsx +384 -384
  62. package/templates/nextblock-template/app/cms/custom-blocks/components/ImageR2Picker.tsx +221 -221
  63. package/templates/nextblock-template/app/cms/custom-blocks/new/page.tsx +12 -12
  64. package/templates/nextblock-template/app/cms/custom-blocks/page.tsx +438 -438
  65. package/templates/nextblock-template/app/cms/dashboard/actions.ts +228 -228
  66. package/templates/nextblock-template/app/cms/dashboard/components/DashboardOnboarding.tsx +130 -130
  67. package/templates/nextblock-template/app/cms/import-export/actions.ts +226 -226
  68. package/templates/nextblock-template/app/cms/interactions/EmailRecipientsInput.tsx +189 -189
  69. package/templates/nextblock-template/app/cms/layout.tsx +73 -73
  70. package/templates/nextblock-template/app/cms/media/components/FolderNavigator.tsx +273 -273
  71. package/templates/nextblock-template/app/cms/media/components/FolderTree.tsx +122 -122
  72. package/templates/nextblock-template/app/cms/media/components/MediaEditForm.tsx +26 -26
  73. package/templates/nextblock-template/app/cms/media/components/MediaGridClient.tsx +69 -69
  74. package/templates/nextblock-template/app/cms/navigation/components/NavigationMenuDnd.tsx +3 -3
  75. package/templates/nextblock-template/app/cms/products/attributes/page.tsx +12 -12
  76. package/templates/nextblock-template/app/cms/products/categories/page.tsx +12 -12
  77. package/templates/nextblock-template/app/cms/products/inventory/page.tsx +13 -13
  78. package/templates/nextblock-template/app/cms/products/new/page.tsx +135 -135
  79. package/templates/nextblock-template/app/cms/products/productFormData.ts +133 -133
  80. package/templates/nextblock-template/app/cms/products/settings/page.tsx +5 -5
  81. package/templates/nextblock-template/app/cms/promotions/PromotionsWorkspace.tsx +456 -456
  82. package/templates/nextblock-template/app/cms/promotions/actions.ts +115 -115
  83. package/templates/nextblock-template/app/cms/promotions/page.tsx +31 -31
  84. package/templates/nextblock-template/app/cms/revisions/service.ts +19 -19
  85. package/templates/nextblock-template/app/cms/revisions/utils.ts +132 -132
  86. package/templates/nextblock-template/app/cms/settings/backup-restore/BackupRestoreWorkspace.tsx +1004 -1004
  87. package/templates/nextblock-template/app/cms/settings/backup-restore/page.tsx +29 -29
  88. package/templates/nextblock-template/app/cms/settings/bot-protection/page.tsx +24 -24
  89. package/templates/nextblock-template/app/cms/settings/cortex-ai/SandboxCortexAiSettingsClient.tsx +497 -497
  90. package/templates/nextblock-template/app/cms/settings/currencies/actions.ts +331 -331
  91. package/templates/nextblock-template/app/cms/settings/currencies/page.tsx +494 -494
  92. package/templates/nextblock-template/app/cms/settings/email/page.tsx +28 -28
  93. package/templates/nextblock-template/app/cms/settings/extra-translations/ExtraTranslationsWorkspace.tsx +767 -767
  94. package/templates/nextblock-template/app/cms/settings/extra-translations/page.tsx +93 -93
  95. package/templates/nextblock-template/app/cms/settings/google-analytics/page.tsx +26 -26
  96. package/templates/nextblock-template/app/cms/settings/languages/components/LanguageDetectionPanel.tsx +188 -188
  97. package/templates/nextblock-template/app/cms/settings/logos/[id]/edit/page.tsx +7 -7
  98. package/templates/nextblock-template/app/cms/settings/logos/components/BrandingSettingsForm.tsx +339 -339
  99. package/templates/nextblock-template/app/cms/settings/logos/components/DeleteLogoButton.tsx +21 -21
  100. package/templates/nextblock-template/app/cms/settings/logos/components/LogoForm.tsx +20 -20
  101. package/templates/nextblock-template/app/cms/settings/logos/components/SetActiveLogoButton.tsx +42 -42
  102. package/templates/nextblock-template/app/cms/settings/logos/components/SiteSeoSettingsForm.tsx +133 -133
  103. package/templates/nextblock-template/app/cms/settings/logos/new/page.tsx +8 -8
  104. package/templates/nextblock-template/app/cms/settings/packages/package-card.tsx +122 -122
  105. package/templates/nextblock-template/app/cms/settings/privacy/page.tsx +27 -27
  106. package/templates/nextblock-template/app/cms/settings/registration/page.tsx +27 -27
  107. package/templates/nextblock-template/app/cms/settings/security/page.tsx +33 -33
  108. package/templates/nextblock-template/app/cms/settings/taxes/page.tsx +21 -21
  109. package/templates/nextblock-template/app/cms/shipping/page.tsx +20 -20
  110. package/templates/nextblock-template/app/cms/users/components/CreateUserForm.tsx +217 -217
  111. package/templates/nextblock-template/app/cms/users/components/DeleteUserButton.tsx +12 -12
  112. package/templates/nextblock-template/app/cms/users/new/page.tsx +44 -44
  113. package/templates/nextblock-template/app/lib/site-settings.ts +105 -105
  114. package/templates/nextblock-template/app/profile/ProfilePageHeader.tsx +16 -16
  115. package/templates/nextblock-template/app/profile/ProfilePageMissingState.tsx +9 -9
  116. package/templates/nextblock-template/app/profile/account-links.ts +22 -22
  117. package/templates/nextblock-template/app/profile/orders/CustomerOrdersPageClient.tsx +124 -124
  118. package/templates/nextblock-template/app/profile/orders/page.tsx +19 -19
  119. package/templates/nextblock-template/app/profile/password/PasswordSettingsPageClient.tsx +128 -128
  120. package/templates/nextblock-template/app/profile/password/actions.ts +59 -59
  121. package/templates/nextblock-template/app/profile/password/page.tsx +27 -27
  122. package/templates/nextblock-template/app/setup/SetupWizard.tsx +678 -678
  123. package/templates/nextblock-template/app/setup/layout.tsx +13 -13
  124. package/templates/nextblock-template/app/setup/page.tsx +111 -111
  125. package/templates/nextblock-template/app/sitemap.ts +130 -130
  126. package/templates/nextblock-template/components/BlockRenderer.tsx +4 -0
  127. package/templates/nextblock-template/components/CartDrawerLoader.tsx +7 -7
  128. package/templates/nextblock-template/components/DeferredCartDrawer.tsx +23 -23
  129. package/templates/nextblock-template/components/DeferredGoogleAnalytics.tsx +70 -70
  130. package/templates/nextblock-template/components/DeferredGoogleTagManager.tsx +70 -70
  131. package/templates/nextblock-template/components/DeferredSpeedInsights.tsx +69 -69
  132. package/templates/nextblock-template/components/FeatureImageHero.tsx +47 -47
  133. package/templates/nextblock-template/components/FooterNavigation.tsx +32 -32
  134. package/templates/nextblock-template/components/HtmlScriptExecutor.tsx +47 -47
  135. package/templates/nextblock-template/components/LanguageSwitcher.tsx +2 -2
  136. package/templates/nextblock-template/components/PublicEnvBootstrap.tsx +30 -30
  137. package/templates/nextblock-template/components/ResponsiveNav.tsx +14 -14
  138. package/templates/nextblock-template/components/auth/AuthBotProtection.tsx +182 -182
  139. package/templates/nextblock-template/components/blocks/PostCardSkeleton.tsx +12 -12
  140. package/templates/nextblock-template/components/blocks/PostsGridBlock.tsx +12 -12
  141. package/templates/nextblock-template/components/blocks/ProductGridClient.tsx +114 -114
  142. package/templates/nextblock-template/components/blocks/ecommerceRendererLoaders.ts +23 -23
  143. package/templates/nextblock-template/components/blocks/renderers/ClientTextBlockRenderer.tsx +8 -1
  144. package/templates/nextblock-template/components/blocks/renderers/FormBlockRenderer.tsx +249 -249
  145. package/templates/nextblock-template/components/blocks/renderers/SectionBlockRenderer.tsx +3 -0
  146. package/templates/nextblock-template/components/blocks/renderers/VideoEmbedBlockRenderer.tsx +33 -23
  147. package/templates/nextblock-template/components/blocks/types.ts +7 -7
  148. package/templates/nextblock-template/components/env-var-warning.tsx +3 -3
  149. package/templates/nextblock-template/components/form-message.tsx +32 -32
  150. package/templates/nextblock-template/components/media/YouTubeFacade.tsx +105 -0
  151. package/templates/nextblock-template/components/media/youtube-embed-replace.tsx +32 -0
  152. package/templates/nextblock-template/components/privacy/ConsentBanner.tsx +170 -170
  153. package/templates/nextblock-template/components/privacy/ConsentGatedAnalytics.tsx +70 -70
  154. package/templates/nextblock-template/components/renderers/CachedDynamicLayoutEngine.tsx +28 -28
  155. package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.test.tsx +166 -166
  156. package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.tsx +471 -464
  157. package/templates/nextblock-template/components/submit-button.tsx +23 -23
  158. package/templates/nextblock-template/components/theme-switcher.tsx +8 -8
  159. package/templates/nextblock-template/components/visual-editing/DeferredVisualEditing.tsx +21 -21
  160. package/templates/nextblock-template/context/AuthContext.tsx +23 -23
  161. package/templates/nextblock-template/context/language-rest-client.ts +32 -32
  162. package/templates/nextblock-template/docker/db/init/99-jwt.sql +6 -6
  163. package/templates/nextblock-template/docker/db/init/99-roles.sql +25 -25
  164. package/templates/nextblock-template/docker/kong/kong.yml +112 -112
  165. package/templates/nextblock-template/docs/01-PROJECT-OVERVIEW.md +94 -94
  166. package/templates/nextblock-template/docs/02-ECOMMERCE-CAPABILITIES.md +364 -364
  167. package/templates/nextblock-template/docs/03-CMS-AND-EDITOR.md +202 -202
  168. package/templates/nextblock-template/docs/04-DATABASE-AND-AUTH.md +246 -246
  169. package/templates/nextblock-template/docs/06-CLI-AND-SCAFFOLDING.md +176 -176
  170. package/templates/nextblock-template/docs/07-BLOCK-SDK-AND-EXTENSIBILITY.md +146 -146
  171. package/templates/nextblock-template/docs/10-CUSTOM-BLOCKS.md +222 -222
  172. package/templates/nextblock-template/docs/11-SELF-HOSTED-DOCKER.md +173 -173
  173. package/templates/nextblock-template/docs/12-VERCEL-DEPLOYMENT.md +170 -170
  174. package/templates/nextblock-template/docs/13-STAYING-UP-TO-DATE.md +151 -151
  175. package/templates/nextblock-template/docs/README.md +39 -39
  176. package/templates/nextblock-template/hooks/use-hotkeys.ts +21 -21
  177. package/templates/nextblock-template/hooks/useGlobalSearch.ts +101 -101
  178. package/templates/nextblock-template/index.d.ts +7 -7
  179. package/templates/nextblock-template/lib/app-secrets.ts +39 -39
  180. package/templates/nextblock-template/lib/auth/cookies.ts +47 -47
  181. package/templates/nextblock-template/lib/auth/crypto.ts +45 -45
  182. package/templates/nextblock-template/lib/auth/trustedDevices.ts +92 -92
  183. package/templates/nextblock-template/lib/auth-redirects.ts +46 -46
  184. package/templates/nextblock-template/lib/blocks/ProductGridBlock.tsx +78 -78
  185. package/templates/nextblock-template/lib/blocks/README.md +13 -13
  186. package/templates/nextblock-template/lib/blocks/product-grid-data.ts +210 -210
  187. package/templates/nextblock-template/lib/botProtection/verify.ts +134 -134
  188. package/templates/nextblock-template/lib/cms-transfer/server.ts +2243 -2243
  189. package/templates/nextblock-template/lib/cms-transfer/types.ts +145 -145
  190. package/templates/nextblock-template/lib/custom-block-definitions.ts +87 -87
  191. package/templates/nextblock-template/lib/custom-block-r2-upload-shared.ts +178 -178
  192. package/templates/nextblock-template/lib/custom-block-r2-upload.test.ts +140 -140
  193. package/templates/nextblock-template/lib/custom-block-r2-upload.ts +88 -88
  194. package/templates/nextblock-template/lib/custom-block-relations.test.ts +227 -227
  195. package/templates/nextblock-template/lib/custom-block-relations.ts +279 -279
  196. package/templates/nextblock-template/lib/custom-block-safelist.ts +14 -14
  197. package/templates/nextblock-template/lib/editor/dynamic-extension-core.test.ts +172 -172
  198. package/templates/nextblock-template/lib/editor/dynamic-extension-core.ts +213 -213
  199. package/templates/nextblock-template/lib/editor/dynamic-extension-loader.ts +22 -22
  200. package/templates/nextblock-template/lib/editor/dynamic-extensions.tsx +193 -193
  201. package/templates/nextblock-template/lib/email/branding-format.test.ts +133 -133
  202. package/templates/nextblock-template/lib/email/branding-format.ts +123 -123
  203. package/templates/nextblock-template/lib/email/branding.ts +76 -76
  204. package/templates/nextblock-template/lib/full-backup/manifest.test.ts +121 -121
  205. package/templates/nextblock-template/lib/full-backup/manifest.ts +206 -206
  206. package/templates/nextblock-template/lib/full-backup/server.ts +743 -743
  207. package/templates/nextblock-template/lib/i18n/country-languages.ts +247 -247
  208. package/templates/nextblock-template/lib/i18n/detection.test.ts +197 -197
  209. package/templates/nextblock-template/lib/i18n/detection.ts +192 -192
  210. package/templates/nextblock-template/lib/logos/active-logo.ts +53 -53
  211. package/templates/nextblock-template/lib/media/resolveMediaUrl.ts +54 -54
  212. package/templates/nextblock-template/lib/media/youtube.ts +99 -0
  213. package/templates/nextblock-template/lib/onboarding/actions.ts +31 -31
  214. package/templates/nextblock-template/lib/onboarding/status.ts +222 -222
  215. package/templates/nextblock-template/lib/posts/readTime.ts +60 -60
  216. package/templates/nextblock-template/lib/privacy/consent-client.ts +57 -57
  217. package/templates/nextblock-template/lib/privacy/contact-emails.ts +64 -64
  218. package/templates/nextblock-template/lib/privacy/settings.ts +115 -115
  219. package/templates/nextblock-template/lib/privacy/types.ts +69 -69
  220. package/templates/nextblock-template/lib/promotions/server.test.ts +74 -74
  221. package/templates/nextblock-template/lib/promotions/server.ts +741 -741
  222. package/templates/nextblock-template/lib/resolve-block-relations.test.ts +142 -142
  223. package/templates/nextblock-template/lib/resolve-block-relations.ts +255 -255
  224. package/templates/nextblock-template/lib/search/types.ts +27 -27
  225. package/templates/nextblock-template/lib/setup/actions.ts +460 -460
  226. package/templates/nextblock-template/lib/setup/env-status.ts +125 -125
  227. package/templates/nextblock-template/lib/setup/env-write.ts +111 -111
  228. package/templates/nextblock-template/lib/setup/migrations-bundle.ts +87 -82
  229. package/templates/nextblock-template/lib/setup/provisioning.ts +59 -59
  230. package/templates/nextblock-template/lib/setup/schema-apply.ts +408 -408
  231. package/templates/nextblock-template/lib/setup/system-config.ts +105 -105
  232. package/templates/nextblock-template/lib/setup/types.ts +18 -18
  233. package/templates/nextblock-template/lib/site-url.ts +48 -48
  234. package/templates/nextblock-template/lib/storage/provider.ts +66 -66
  235. package/templates/nextblock-template/lib/storage/supabase-storage.ts +103 -103
  236. package/templates/nextblock-template/lib/updates/check-upstream.ts +441 -441
  237. package/templates/nextblock-template/lib/updates/github-device.ts +206 -206
  238. package/templates/nextblock-template/lib/updates/repo-identity.ts +56 -56
  239. package/templates/nextblock-template/next-env.d.ts +1 -1
  240. package/templates/nextblock-template/next.config.js +6 -0
  241. package/templates/nextblock-template/package.json +1 -1
  242. package/templates/nextblock-template/postcss.config.js +6 -6
  243. package/templates/nextblock-template/scripts/backup.js +115 -115
  244. package/templates/nextblock-template/scripts/docker-setup.mjs +310 -310
  245. package/templates/nextblock-template/scripts/restore.js +385 -385
  246. package/templates/nextblock-template/scripts/verify-cortex-ai-build-widget.tsx +98 -98
  247. package/templates/nextblock-template/scripts/verify-cortex-ai-generate-blocks.ts +62 -62
  248. package/templates/nextblock-template/scripts/verify-cortex-ai-global-tools.ts +537 -537
  249. package/templates/nextblock-template/scripts/verify-cortex-ai-routing.ts +58 -58
  250. package/templates/nextblock-template/scripts/verify-custom-block-definitions.ts +188 -188
  251. package/templates/nextblock-template/scripts/verify-dynamic-custom-block-extensions.ts +123 -123
  252. package/templates/nextblock-template/scripts/verify-dynamic-layout-engine.tsx +133 -133
  253. package/templates/nextblock-template/scripts/verify-milestone-2-custom-blocks.ts +65 -65
  254. package/templates/nextblock-template/tailwind.config.js +25 -25
  255. package/templates/nextblock-template/tools/build-migrate.mjs +209 -209
  256. package/templates/nextblock-template/tools/configure-supabase-auth.js +282 -282
  257. package/templates/nextblock-template/tsconfig.tsbuildinfo +1 -1
  258. package/templates/nextblock-template/types/jsdom.d.ts +6 -6
  259. package/tsconfig.base.json +3 -3
@@ -1,170 +1,170 @@
1
- # 12 · Cloud Deployment (Deploy to Vercel)
2
-
3
- NextBlock ships a one-click **Deploy to Vercel** button (see the README) that brings
4
- up a production instance already connected to a managed Supabase project. From there,
5
- the in-app **First-Boot Setup Wizard** (`/setup`) finishes configuration in the
6
- browser — there is no terminal step.
7
-
8
- ## How the button works
9
-
10
- The badge links to `https://vercel.com/new/clone` with these query parameters:
11
-
12
- | Parameter | Purpose |
13
- | :--- | :--- |
14
- | `repository-url` | The NextBlock repo to clone into the user's Git provider. |
15
- | `project-name` / `repository-name` | Pre-fill the new Vercel project and Git repo names. |
16
- | `stores=[{"type":"integration","integrationSlug":"supabase","productSlug":"supabase"}]` | Vercel's **native Supabase Marketplace integration**. During import you're prompted to **create a Supabase database** (name + region); Vercel **provisions it, connects it to the project, and injects the env vars before the first build**. |
17
-
18
- There is deliberately **no `env=` parameter** — the deploy prompts for **zero** values you
19
- have to type (see "No environment variables required" below). The only interaction is the
20
- Supabase integration's "create database" step, which can't be skipped because provisioning
21
- a Postgres DB requires choosing a region/plan.
22
-
23
- > **Why `stores`, not `integration-ids`?** The legacy `integration-ids=oac_…` parameter
24
- > triggers an OAuth integration that *creates* a Supabase project but leaves it
25
- > **disconnected** — it injects **no** environment variables into the Vercel project, so
26
- > the app boots unconfigured and you have to wire the keys up by hand. The modern `stores`
27
- > parameter is the native Marketplace path that actually **connects the store and injects
28
- > credentials before the build**. ([Vercel Deploy Button docs](https://vercel.com/docs/deploy-button/source))
29
-
30
- ## Connect the database (Supabase integration)
31
-
32
- The `stores` parameter makes Vercel prompt you to create a Supabase database during import.
33
- Pick a **name** and **region**, and Vercel **automatically injects** the integration's
34
- environment variables into the project — you never copy a value. The native integration
35
- injects the **new-style** Supabase key names, e.g.:
36
-
37
- `NEXT_PUBLIC_SUPABASE_URL` / `SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY` /
38
- `SUPABASE_PUBLISHABLE_KEY` (the anon-equivalent), `SUPABASE_SECRET_KEY` (the
39
- service-role-equivalent), and `POSTGRES_URL` (+ the other `POSTGRES_*` parts).
40
-
41
- NextBlock reads **all** of these aliases (see `apps/nextblock/lib/setup/env-status.ts`):
42
- it accepts `NEXT_PUBLIC_SUPABASE_URL` *or* `SUPABASE_URL`; anon *or* `PUBLISHABLE_KEY`;
43
- `SUPABASE_SERVICE_ROLE_KEY` *or* `SUPABASE_SECRET_KEY`. So the wizard's connection step
44
- auto-skips no matter which copy the integration set, and the browser client gets the
45
- publishable key bridged in as the anon key at build time.
46
-
47
- > If the database step still appears after a deploy that connected the store, the env vars
48
- > landed **after** that build — **Redeploy** once (Vercel binds env vars at deploy time).
49
- > With the `stores` flow they're injected *before* the first build, so this is rarely needed.
50
-
51
- On that deploy the wizard skips the database-connection step, **auto-applies the schema**
52
- (the migrations are embedded in the build — see `lib/setup/migrations-bundle.ts` — and run
53
- via the injected `POSTGRES_URL`), uses the connected Supabase project for media storage,
54
- and goes straight to creating the first administrator.
55
-
56
- > Until the schema is applied and the first admin exists, **every route redirects to
57
- > `/setup`** (the homepage does *not* 404). The middleware treats a "schema not applied yet"
58
- > database error as *unprovisioned* and funnels traffic to the wizard.
59
-
60
- ## Build configuration (Nx monorepo)
61
-
62
- NextBlock is an Nx monorepo — the Next.js app lives at `apps/nextblock`, not the repo
63
- root — so a bare `next build` at the root fails with *"Couldn't find any `pages` or
64
- `app` directory."* The root [`vercel.json`](../vercel.json) pins the correct build, so
65
- the one-click deploy needs **no manual dashboard configuration**:
66
-
67
- ```json
68
- {
69
- "buildCommand": "npx nx build nextblock --prod",
70
- "outputDirectory": "apps/nextblock/.next",
71
- "framework": "nextjs"
72
- }
73
- ```
74
-
75
- - **`buildCommand`** runs the Nx target from the repo root, which resolves the
76
- workspace libraries (`@nextblock-cms/*` via the TS path aliases) and builds the app.
77
- - **`outputDirectory`** points at the app's `.next`. This `@nx/next` version emits it
78
- to `apps/nextblock/.next` — **not** `dist/apps/nextblock/.next` (which only receives
79
- the deploy wrapper: `package.json`, `next.config.js`, `public/`). Verify with
80
- `npx nx build nextblock --prod` then check `apps/nextblock/.next/BUILD_ID`.
81
- - **`framework: nextjs`** keeps Vercel's first-class Next.js runtime (SSR/ISR
82
- functions, image optimization, the `proxy.ts` middleware).
83
-
84
- Leave the Vercel project's **Root Directory unset** (the repo root) — the build command
85
- already targets the app. Do **not** set Root Directory to `apps/nextblock`: the app
86
- imports the workspace libraries one level up, which a custom Root Directory would hide
87
- (Vercel forbids `..` above a custom root).
88
-
89
- ## No environment variables required
90
-
91
- A Deploy-Button URL can only carry variable **names**, never values — so secrets can
92
- never be pre-filled through it. Rather than make you paste random strings, NextBlock
93
- resolves everything in-app, and the button prompts for nothing:
94
-
95
- - **`NEXT_PUBLIC_URL`** — optional. When unset the app falls back to Vercel's
96
- production URL (`VERCEL_PROJECT_PRODUCTION_URL` server-side /
97
- `NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL` in the browser), i.e. your
98
- `*.vercel.app` domain. Sitemap, robots, and canonical links use it automatically.
99
- Add a custom domain later, set `NEXT_PUBLIC_URL=https://yourdomain.com` in the
100
- Vercel project, and redeploy (it is inlined at build time).
101
- - **`DRAFT_MODE_SECRET`** and **`REVALIDATE_SECRET_TOKEN`** — optional. When unset they
102
- are derived deterministically from the Supabase service-role key (HMAC-SHA256), so
103
- Draft Mode and on-demand revalidation work out of the box. Setting either env var
104
- overrides the derived value — do this if you want a fixed `REVALIDATE_SECRET_TOKEN`
105
- to paste into a Supabase revalidation webhook. (See `apps/nextblock/lib/app-secrets.ts`.)
106
- - **`CRON_SECRET`** — optional. The cron endpoints enforce the `Authorization: Bearer`
107
- header **only when it is set**. Leave it unset for a frictionless deploy, or set it
108
- in the Vercel project to lock the cron endpoints down. The destructive
109
- `/api/cron/reset-sandbox` job is independently gated to sandbox-mode only (404
110
- otherwise), so it never runs on a normal deploy.
111
-
112
- ## What the wizard does on Vercel
113
-
114
- 1. **Database** — already connected (integration-injected). The wizard verifies a
115
- first admin doesn't exist yet, otherwise it redirects to `/cms/dashboard`. The
116
- connection step is **auto-skipped**.
117
- 2. **Schema** — applied **automatically**. The Supabase integration creates the project
118
- but does **not** run NextBlock's migrations, so the wizard applies them itself on the
119
- final step: it runs the build-embedded migration bundle over the injected
120
- `POSTGRES_URL` (no CLI, no manual SQL). Idempotent — a re-run is a no-op. See
121
- [docs/04](./04-DATABASE-AND-AUTH.md) and [docs/05](./05-DEVELOPER-GUIDE.md).
122
- 3. **Storage** — **skipped on Vercel; nothing to configure.** Media uses **native
123
- Supabase Storage** through the already-connected project: the injected
124
- `SUPABASE_SECRET_KEY` authenticates uploads/downloads/deletes via the Supabase client
125
- (no S3 access keys required), a public `media` bucket is auto-created, and images are
126
- served from `<project>/storage/v1/object/public/media/…`. The storage backend is
127
- selected automatically (`apps/nextblock/lib/storage/provider.ts`): if S3/R2 keys are
128
- present it uses them; otherwise it falls back to native Supabase Storage. (Cloudflare
129
- R2 remains the default for non-Vercel installs — it has a more generous free storage
130
- tier; set the `R2_*` env vars to use it on Vercel instead.)
131
-
132
- > **Upload size:** the CMS media uploader proxies the file through a serverless
133
- > function (`/api/upload/proxy`), which is subject to Vercel's ~4.5 MB request-body
134
- > limit — larger single images fail on the Hobby/Pro serverless runtime regardless of
135
- > storage backend. This is a platform constraint, not a NextBlock one.
136
- 4. **Email / Bot protection / Sign-ups** — optional steps; bot-protection and the
137
- sign-up policy persist to the database and work immediately. SMTP, if used, is set
138
- as Vercel environment variables.
139
- 5. **Administrator** — create the first admin. The account is created already
140
- confirmed (`email_confirm: true`), so no verification email is required.
141
-
142
- > Filesystem is read-only on Vercel, so the wizard never writes `.env.local` there —
143
- > all configuration is environment variables (platform-managed) plus the database.
144
-
145
- ## Cron jobs and the Hobby plan
146
-
147
- `vercel.json` declares two crons (`/api/cron/reset-sandbox` at 03:00 and
148
- `/api/cron/sync-currencies` at 18:00). Vercel's **Hobby (free) tier allows up to 100
149
- cron jobs, each running at most once per day** — both jobs are daily, so they deploy
150
- fine on the free tier. (Hobby timing is approximate, ±59 min, which is irrelevant for
151
- daily jobs; only sub-daily schedules like `0 * * * *` are rejected on Hobby.)
152
-
153
- `reset-sandbox` only does work in sandbox mode — it returns 404 otherwise — so on a
154
- normal deploy it is a harmless no-op. Delete it from `vercel.json` if you'd rather not
155
- see it scheduled.
156
-
157
- ## After deploy
158
-
159
- Visit the deployment URL — it redirects to `/setup` until the first admin exists.
160
- Complete the wizard, then sign in at `/cms/dashboard`.
161
-
162
- **Automatic updates.** The 1-click deploy creates a **new repository you own** (a copy —
163
- *not* a GitHub fork) and ships a daily upstream-sync GitHub Action. Because it's your own
164
- repo, **Actions are enabled by default — there's nothing to turn on**; the workflow runs
165
- once it's on your **default branch**, and the dashboard onboarding step completes
166
- automatically when GitHub registers it. We recommend keeping the repo **public** (fully
167
- zero-config); a **private** repo additionally needs a `NEXTBLOCK_GITHUB_TOKEN` env var for
168
- the in-CMS conflict banner. (Only a *manually-created GitHub fork* has Actions disabled
169
- until you enable them on the Actions tab.) Full details — both tracks, conflict handling,
170
- and build-time migrations — are in [docs/13](./13-STAYING-UP-TO-DATE.md).
1
+ # 12 · Cloud Deployment (Deploy to Vercel)
2
+
3
+ NextBlock ships a one-click **Deploy to Vercel** button (see the README) that brings
4
+ up a production instance already connected to a managed Supabase project. From there,
5
+ the in-app **First-Boot Setup Wizard** (`/setup`) finishes configuration in the
6
+ browser — there is no terminal step.
7
+
8
+ ## How the button works
9
+
10
+ The badge links to `https://vercel.com/new/clone` with these query parameters:
11
+
12
+ | Parameter | Purpose |
13
+ | :--- | :--- |
14
+ | `repository-url` | The NextBlock repo to clone into the user's Git provider. |
15
+ | `project-name` / `repository-name` | Pre-fill the new Vercel project and Git repo names. |
16
+ | `stores=[{"type":"integration","integrationSlug":"supabase","productSlug":"supabase"}]` | Vercel's **native Supabase Marketplace integration**. During import you're prompted to **create a Supabase database** (name + region); Vercel **provisions it, connects it to the project, and injects the env vars before the first build**. |
17
+
18
+ There is deliberately **no `env=` parameter** — the deploy prompts for **zero** values you
19
+ have to type (see "No environment variables required" below). The only interaction is the
20
+ Supabase integration's "create database" step, which can't be skipped because provisioning
21
+ a Postgres DB requires choosing a region/plan.
22
+
23
+ > **Why `stores`, not `integration-ids`?** The legacy `integration-ids=oac_…` parameter
24
+ > triggers an OAuth integration that *creates* a Supabase project but leaves it
25
+ > **disconnected** — it injects **no** environment variables into the Vercel project, so
26
+ > the app boots unconfigured and you have to wire the keys up by hand. The modern `stores`
27
+ > parameter is the native Marketplace path that actually **connects the store and injects
28
+ > credentials before the build**. ([Vercel Deploy Button docs](https://vercel.com/docs/deploy-button/source))
29
+
30
+ ## Connect the database (Supabase integration)
31
+
32
+ The `stores` parameter makes Vercel prompt you to create a Supabase database during import.
33
+ Pick a **name** and **region**, and Vercel **automatically injects** the integration's
34
+ environment variables into the project — you never copy a value. The native integration
35
+ injects the **new-style** Supabase key names, e.g.:
36
+
37
+ `NEXT_PUBLIC_SUPABASE_URL` / `SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY` /
38
+ `SUPABASE_PUBLISHABLE_KEY` (the anon-equivalent), `SUPABASE_SECRET_KEY` (the
39
+ service-role-equivalent), and `POSTGRES_URL` (+ the other `POSTGRES_*` parts).
40
+
41
+ NextBlock reads **all** of these aliases (see `apps/nextblock/lib/setup/env-status.ts`):
42
+ it accepts `NEXT_PUBLIC_SUPABASE_URL` *or* `SUPABASE_URL`; anon *or* `PUBLISHABLE_KEY`;
43
+ `SUPABASE_SERVICE_ROLE_KEY` *or* `SUPABASE_SECRET_KEY`. So the wizard's connection step
44
+ auto-skips no matter which copy the integration set, and the browser client gets the
45
+ publishable key bridged in as the anon key at build time.
46
+
47
+ > If the database step still appears after a deploy that connected the store, the env vars
48
+ > landed **after** that build — **Redeploy** once (Vercel binds env vars at deploy time).
49
+ > With the `stores` flow they're injected *before* the first build, so this is rarely needed.
50
+
51
+ On that deploy the wizard skips the database-connection step, **auto-applies the schema**
52
+ (the migrations are embedded in the build — see `lib/setup/migrations-bundle.ts` — and run
53
+ via the injected `POSTGRES_URL`), uses the connected Supabase project for media storage,
54
+ and goes straight to creating the first administrator.
55
+
56
+ > Until the schema is applied and the first admin exists, **every route redirects to
57
+ > `/setup`** (the homepage does *not* 404). The middleware treats a "schema not applied yet"
58
+ > database error as *unprovisioned* and funnels traffic to the wizard.
59
+
60
+ ## Build configuration (Nx monorepo)
61
+
62
+ NextBlock is an Nx monorepo — the Next.js app lives at `apps/nextblock`, not the repo
63
+ root — so a bare `next build` at the root fails with *"Couldn't find any `pages` or
64
+ `app` directory."* The root [`vercel.json`](../vercel.json) pins the correct build, so
65
+ the one-click deploy needs **no manual dashboard configuration**:
66
+
67
+ ```json
68
+ {
69
+ "buildCommand": "npx nx build nextblock --prod",
70
+ "outputDirectory": "apps/nextblock/.next",
71
+ "framework": "nextjs"
72
+ }
73
+ ```
74
+
75
+ - **`buildCommand`** runs the Nx target from the repo root, which resolves the
76
+ workspace libraries (`@nextblock-cms/*` via the TS path aliases) and builds the app.
77
+ - **`outputDirectory`** points at the app's `.next`. This `@nx/next` version emits it
78
+ to `apps/nextblock/.next` — **not** `dist/apps/nextblock/.next` (which only receives
79
+ the deploy wrapper: `package.json`, `next.config.js`, `public/`). Verify with
80
+ `npx nx build nextblock --prod` then check `apps/nextblock/.next/BUILD_ID`.
81
+ - **`framework: nextjs`** keeps Vercel's first-class Next.js runtime (SSR/ISR
82
+ functions, image optimization, the `proxy.ts` middleware).
83
+
84
+ Leave the Vercel project's **Root Directory unset** (the repo root) — the build command
85
+ already targets the app. Do **not** set Root Directory to `apps/nextblock`: the app
86
+ imports the workspace libraries one level up, which a custom Root Directory would hide
87
+ (Vercel forbids `..` above a custom root).
88
+
89
+ ## No environment variables required
90
+
91
+ A Deploy-Button URL can only carry variable **names**, never values — so secrets can
92
+ never be pre-filled through it. Rather than make you paste random strings, NextBlock
93
+ resolves everything in-app, and the button prompts for nothing:
94
+
95
+ - **`NEXT_PUBLIC_URL`** — optional. When unset the app falls back to Vercel's
96
+ production URL (`VERCEL_PROJECT_PRODUCTION_URL` server-side /
97
+ `NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL` in the browser), i.e. your
98
+ `*.vercel.app` domain. Sitemap, robots, and canonical links use it automatically.
99
+ Add a custom domain later, set `NEXT_PUBLIC_URL=https://yourdomain.com` in the
100
+ Vercel project, and redeploy (it is inlined at build time).
101
+ - **`DRAFT_MODE_SECRET`** and **`REVALIDATE_SECRET_TOKEN`** — optional. When unset they
102
+ are derived deterministically from the Supabase service-role key (HMAC-SHA256), so
103
+ Draft Mode and on-demand revalidation work out of the box. Setting either env var
104
+ overrides the derived value — do this if you want a fixed `REVALIDATE_SECRET_TOKEN`
105
+ to paste into a Supabase revalidation webhook. (See `apps/nextblock/lib/app-secrets.ts`.)
106
+ - **`CRON_SECRET`** — optional. The cron endpoints enforce the `Authorization: Bearer`
107
+ header **only when it is set**. Leave it unset for a frictionless deploy, or set it
108
+ in the Vercel project to lock the cron endpoints down. The destructive
109
+ `/api/cron/reset-sandbox` job is independently gated to sandbox-mode only (404
110
+ otherwise), so it never runs on a normal deploy.
111
+
112
+ ## What the wizard does on Vercel
113
+
114
+ 1. **Database** — already connected (integration-injected). The wizard verifies a
115
+ first admin doesn't exist yet, otherwise it redirects to `/cms/dashboard`. The
116
+ connection step is **auto-skipped**.
117
+ 2. **Schema** — applied **automatically**. The Supabase integration creates the project
118
+ but does **not** run NextBlock's migrations, so the wizard applies them itself on the
119
+ final step: it runs the build-embedded migration bundle over the injected
120
+ `POSTGRES_URL` (no CLI, no manual SQL). Idempotent — a re-run is a no-op. See
121
+ [docs/04](./04-DATABASE-AND-AUTH.md) and [docs/05](./05-DEVELOPER-GUIDE.md).
122
+ 3. **Storage** — **skipped on Vercel; nothing to configure.** Media uses **native
123
+ Supabase Storage** through the already-connected project: the injected
124
+ `SUPABASE_SECRET_KEY` authenticates uploads/downloads/deletes via the Supabase client
125
+ (no S3 access keys required), a public `media` bucket is auto-created, and images are
126
+ served from `<project>/storage/v1/object/public/media/…`. The storage backend is
127
+ selected automatically (`apps/nextblock/lib/storage/provider.ts`): if S3/R2 keys are
128
+ present it uses them; otherwise it falls back to native Supabase Storage. (Cloudflare
129
+ R2 remains the default for non-Vercel installs — it has a more generous free storage
130
+ tier; set the `R2_*` env vars to use it on Vercel instead.)
131
+
132
+ > **Upload size:** the CMS media uploader proxies the file through a serverless
133
+ > function (`/api/upload/proxy`), which is subject to Vercel's ~4.5 MB request-body
134
+ > limit — larger single images fail on the Hobby/Pro serverless runtime regardless of
135
+ > storage backend. This is a platform constraint, not a NextBlock one.
136
+ 4. **Email / Bot protection / Sign-ups** — optional steps; bot-protection and the
137
+ sign-up policy persist to the database and work immediately. SMTP, if used, is set
138
+ as Vercel environment variables.
139
+ 5. **Administrator** — create the first admin. The account is created already
140
+ confirmed (`email_confirm: true`), so no verification email is required.
141
+
142
+ > Filesystem is read-only on Vercel, so the wizard never writes `.env.local` there —
143
+ > all configuration is environment variables (platform-managed) plus the database.
144
+
145
+ ## Cron jobs and the Hobby plan
146
+
147
+ `vercel.json` declares two crons (`/api/cron/reset-sandbox` at 03:00 and
148
+ `/api/cron/sync-currencies` at 18:00). Vercel's **Hobby (free) tier allows up to 100
149
+ cron jobs, each running at most once per day** — both jobs are daily, so they deploy
150
+ fine on the free tier. (Hobby timing is approximate, ±59 min, which is irrelevant for
151
+ daily jobs; only sub-daily schedules like `0 * * * *` are rejected on Hobby.)
152
+
153
+ `reset-sandbox` only does work in sandbox mode — it returns 404 otherwise — so on a
154
+ normal deploy it is a harmless no-op. Delete it from `vercel.json` if you'd rather not
155
+ see it scheduled.
156
+
157
+ ## After deploy
158
+
159
+ Visit the deployment URL — it redirects to `/setup` until the first admin exists.
160
+ Complete the wizard, then sign in at `/cms/dashboard`.
161
+
162
+ **Automatic updates.** The 1-click deploy creates a **new repository you own** (a copy —
163
+ *not* a GitHub fork) and ships a daily upstream-sync GitHub Action. Because it's your own
164
+ repo, **Actions are enabled by default — there's nothing to turn on**; the workflow runs
165
+ once it's on your **default branch**, and the dashboard onboarding step completes
166
+ automatically when GitHub registers it. We recommend keeping the repo **public** (fully
167
+ zero-config); a **private** repo additionally needs a `NEXTBLOCK_GITHUB_TOKEN` env var for
168
+ the in-CMS conflict banner. (Only a *manually-created GitHub fork* has Actions disabled
169
+ until you enable them on the Actions tab.) Full details — both tracks, conflict handling,
170
+ and build-time migrations — are in [docs/13](./13-STAYING-UP-TO-DATE.md).