create-nextblock 0.14.1 → 0.14.2

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 (241) 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/twoFactorEmail.ts +22 -22
  25. package/templates/nextblock-template/app/api/ai/cortex/build-widget/route.ts +153 -153
  26. package/templates/nextblock-template/app/api/ai/generate-blocks/route.ts +96 -96
  27. package/templates/nextblock-template/app/api/brand/email-logo/route.ts +48 -48
  28. package/templates/nextblock-template/app/api/cms/check-updates/route.ts +44 -44
  29. package/templates/nextblock-template/app/api/cms/full-backup/export/route.ts +33 -33
  30. package/templates/nextblock-template/app/api/cms/full-backup/restore/route.ts +63 -63
  31. package/templates/nextblock-template/app/api/cron/reset-sandbox/route.ts +3490 -3490
  32. package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +5749 -5749
  33. package/templates/nextblock-template/app/api/cron/sync-currencies/route.ts +39 -39
  34. package/templates/nextblock-template/app/api/custom-blocks/db-relations/route.ts +92 -92
  35. package/templates/nextblock-template/app/api/custom-blocks/editor-definitions/route.ts +43 -43
  36. package/templates/nextblock-template/app/api/media/library/route.ts +69 -69
  37. package/templates/nextblock-template/app/api/media/r2-presigned/route.ts +53 -53
  38. package/templates/nextblock-template/app/api/media/record/route.ts +160 -160
  39. package/templates/nextblock-template/app/api/search/route.ts +43 -43
  40. package/templates/nextblock-template/app/article/[slug]/PostClientContent.tsx +441 -441
  41. package/templates/nextblock-template/app/auth/callback/route.ts +31 -31
  42. package/templates/nextblock-template/app/cart/page.tsx +7 -7
  43. package/templates/nextblock-template/app/cms/blocks/components/CustomBlockEditorPreview.tsx +160 -160
  44. package/templates/nextblock-template/app/cms/blocks/components/MediaLibraryModal.tsx +149 -149
  45. package/templates/nextblock-template/app/cms/blocks/editors/DynamicCustomBlockEditor.tsx +167 -167
  46. package/templates/nextblock-template/app/cms/blocks/editors/ImageBlockEditor.tsx +4 -2
  47. package/templates/nextblock-template/app/cms/blocks/editors/TextBlockEditor.tsx +90 -90
  48. package/templates/nextblock-template/app/cms/components/ConnectGitHubButton.tsx +122 -122
  49. package/templates/nextblock-template/app/cms/components/CortexAiPageContext.tsx +58 -58
  50. package/templates/nextblock-template/app/cms/components/FeedbackModal.tsx +36 -36
  51. package/templates/nextblock-template/app/cms/components/SystemAlertsBanner.tsx +112 -112
  52. package/templates/nextblock-template/app/cms/components/TwoFactorReminderBanner.tsx +45 -45
  53. package/templates/nextblock-template/app/cms/components/github-connect-actions.ts +102 -102
  54. package/templates/nextblock-template/app/cms/components/system-alerts-actions.ts +31 -31
  55. package/templates/nextblock-template/app/cms/custom-blocks/[id]/edit/page.tsx +66 -66
  56. package/templates/nextblock-template/app/cms/custom-blocks/actions.ts +519 -519
  57. package/templates/nextblock-template/app/cms/custom-blocks/components/BlocksLibraryTransferControls.tsx +256 -256
  58. package/templates/nextblock-template/app/cms/custom-blocks/components/DBRelationSelect.tsx +384 -384
  59. package/templates/nextblock-template/app/cms/custom-blocks/components/ImageR2Picker.tsx +221 -221
  60. package/templates/nextblock-template/app/cms/custom-blocks/new/page.tsx +12 -12
  61. package/templates/nextblock-template/app/cms/custom-blocks/page.tsx +438 -438
  62. package/templates/nextblock-template/app/cms/dashboard/actions.ts +228 -228
  63. package/templates/nextblock-template/app/cms/dashboard/components/DashboardOnboarding.tsx +130 -130
  64. package/templates/nextblock-template/app/cms/import-export/actions.ts +226 -226
  65. package/templates/nextblock-template/app/cms/layout.tsx +73 -73
  66. package/templates/nextblock-template/app/cms/media/components/FolderNavigator.tsx +273 -273
  67. package/templates/nextblock-template/app/cms/media/components/FolderTree.tsx +122 -122
  68. package/templates/nextblock-template/app/cms/media/components/MediaEditForm.tsx +26 -26
  69. package/templates/nextblock-template/app/cms/media/components/MediaGridClient.tsx +69 -69
  70. package/templates/nextblock-template/app/cms/navigation/components/NavigationMenuDnd.tsx +3 -3
  71. package/templates/nextblock-template/app/cms/products/attributes/page.tsx +12 -12
  72. package/templates/nextblock-template/app/cms/products/categories/page.tsx +12 -12
  73. package/templates/nextblock-template/app/cms/products/inventory/page.tsx +13 -13
  74. package/templates/nextblock-template/app/cms/products/new/page.tsx +135 -135
  75. package/templates/nextblock-template/app/cms/products/productFormData.ts +133 -133
  76. package/templates/nextblock-template/app/cms/products/settings/page.tsx +5 -5
  77. package/templates/nextblock-template/app/cms/promotions/PromotionsWorkspace.tsx +456 -456
  78. package/templates/nextblock-template/app/cms/promotions/actions.ts +115 -115
  79. package/templates/nextblock-template/app/cms/promotions/page.tsx +31 -31
  80. package/templates/nextblock-template/app/cms/revisions/service.ts +19 -19
  81. package/templates/nextblock-template/app/cms/revisions/utils.ts +132 -132
  82. package/templates/nextblock-template/app/cms/settings/backup-restore/BackupRestoreWorkspace.tsx +1004 -1004
  83. package/templates/nextblock-template/app/cms/settings/backup-restore/page.tsx +29 -29
  84. package/templates/nextblock-template/app/cms/settings/bot-protection/page.tsx +24 -24
  85. package/templates/nextblock-template/app/cms/settings/cortex-ai/SandboxCortexAiSettingsClient.tsx +688 -688
  86. package/templates/nextblock-template/app/cms/settings/currencies/actions.ts +331 -331
  87. package/templates/nextblock-template/app/cms/settings/currencies/page.tsx +494 -494
  88. package/templates/nextblock-template/app/cms/settings/email/page.tsx +28 -28
  89. package/templates/nextblock-template/app/cms/settings/extra-translations/ExtraTranslationsWorkspace.tsx +767 -767
  90. package/templates/nextblock-template/app/cms/settings/extra-translations/page.tsx +93 -93
  91. package/templates/nextblock-template/app/cms/settings/google-analytics/page.tsx +26 -26
  92. package/templates/nextblock-template/app/cms/settings/logos/[id]/edit/page.tsx +7 -7
  93. package/templates/nextblock-template/app/cms/settings/logos/components/BrandingSettingsForm.tsx +339 -339
  94. package/templates/nextblock-template/app/cms/settings/logos/components/DeleteLogoButton.tsx +21 -21
  95. package/templates/nextblock-template/app/cms/settings/logos/components/LogoForm.tsx +23 -21
  96. package/templates/nextblock-template/app/cms/settings/logos/components/SetActiveLogoButton.tsx +42 -42
  97. package/templates/nextblock-template/app/cms/settings/logos/components/SiteSeoSettingsForm.tsx +133 -133
  98. package/templates/nextblock-template/app/cms/settings/logos/new/page.tsx +8 -8
  99. package/templates/nextblock-template/app/cms/settings/packages/package-card.tsx +122 -122
  100. package/templates/nextblock-template/app/cms/settings/privacy/page.tsx +27 -27
  101. package/templates/nextblock-template/app/cms/settings/registration/page.tsx +27 -27
  102. package/templates/nextblock-template/app/cms/settings/security/components/SecurityPanel.tsx +9 -7
  103. package/templates/nextblock-template/app/cms/settings/security/page.tsx +33 -33
  104. package/templates/nextblock-template/app/cms/settings/taxes/page.tsx +21 -21
  105. package/templates/nextblock-template/app/cms/shipping/page.tsx +20 -20
  106. package/templates/nextblock-template/app/cms/users/components/DeleteUserButton.tsx +12 -12
  107. package/templates/nextblock-template/app/lib/site-settings.ts +105 -105
  108. package/templates/nextblock-template/app/profile/ProfilePageHeader.tsx +16 -16
  109. package/templates/nextblock-template/app/profile/ProfilePageMissingState.tsx +9 -9
  110. package/templates/nextblock-template/app/profile/account-links.ts +22 -22
  111. package/templates/nextblock-template/app/profile/orders/CustomerOrdersPageClient.tsx +124 -124
  112. package/templates/nextblock-template/app/profile/orders/page.tsx +19 -19
  113. package/templates/nextblock-template/app/profile/password/PasswordSettingsPageClient.tsx +128 -128
  114. package/templates/nextblock-template/app/profile/password/actions.ts +59 -59
  115. package/templates/nextblock-template/app/profile/password/page.tsx +27 -27
  116. package/templates/nextblock-template/app/setup/SetupWizard.tsx +678 -678
  117. package/templates/nextblock-template/app/setup/layout.tsx +13 -13
  118. package/templates/nextblock-template/app/setup/page.tsx +111 -111
  119. package/templates/nextblock-template/app/sitemap.ts +130 -130
  120. package/templates/nextblock-template/components/CartDrawerLoader.tsx +7 -7
  121. package/templates/nextblock-template/components/DeferredCartDrawer.tsx +23 -23
  122. package/templates/nextblock-template/components/DeferredGoogleAnalytics.tsx +70 -70
  123. package/templates/nextblock-template/components/DeferredGoogleTagManager.tsx +70 -70
  124. package/templates/nextblock-template/components/DeferredSpeedInsights.tsx +69 -69
  125. package/templates/nextblock-template/components/FeatureImageHero.tsx +47 -47
  126. package/templates/nextblock-template/components/FooterNavigation.tsx +32 -32
  127. package/templates/nextblock-template/components/HtmlScriptExecutor.tsx +47 -47
  128. package/templates/nextblock-template/components/LanguageSwitcher.tsx +2 -2
  129. package/templates/nextblock-template/components/PublicEnvBootstrap.tsx +30 -30
  130. package/templates/nextblock-template/components/ResponsiveNav.tsx +14 -14
  131. package/templates/nextblock-template/components/auth/AuthBotProtection.tsx +182 -182
  132. package/templates/nextblock-template/components/blocks/PostCardSkeleton.tsx +12 -12
  133. package/templates/nextblock-template/components/blocks/PostsGridBlock.tsx +12 -12
  134. package/templates/nextblock-template/components/blocks/ecommerceRendererLoaders.ts +23 -23
  135. package/templates/nextblock-template/components/blocks/renderers/FormBlockRenderer.tsx +249 -249
  136. package/templates/nextblock-template/components/blocks/types.ts +7 -7
  137. package/templates/nextblock-template/components/env-var-warning.tsx +3 -3
  138. package/templates/nextblock-template/components/form-message.tsx +32 -32
  139. package/templates/nextblock-template/components/media/YouTubeFacade.tsx +105 -105
  140. package/templates/nextblock-template/components/media/youtube-embed-replace.tsx +32 -32
  141. package/templates/nextblock-template/components/privacy/ConsentBanner.tsx +170 -170
  142. package/templates/nextblock-template/components/privacy/ConsentGatedAnalytics.tsx +70 -70
  143. package/templates/nextblock-template/components/renderers/CachedDynamicLayoutEngine.tsx +28 -28
  144. package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.test.tsx +166 -166
  145. package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.tsx +471 -471
  146. package/templates/nextblock-template/components/submit-button.tsx +23 -23
  147. package/templates/nextblock-template/components/theme-switcher.tsx +8 -8
  148. package/templates/nextblock-template/components/visual-editing/DeferredVisualEditing.tsx +21 -21
  149. package/templates/nextblock-template/context/AuthContext.tsx +23 -23
  150. package/templates/nextblock-template/context/language-rest-client.ts +32 -32
  151. package/templates/nextblock-template/docker/db/init/99-jwt.sql +6 -6
  152. package/templates/nextblock-template/docker/db/init/99-roles.sql +25 -25
  153. package/templates/nextblock-template/docker/kong/kong.yml +112 -112
  154. package/templates/nextblock-template/docs/01-PROJECT-OVERVIEW.md +94 -94
  155. package/templates/nextblock-template/docs/02-ECOMMERCE-CAPABILITIES.md +364 -364
  156. package/templates/nextblock-template/docs/03-CMS-AND-EDITOR.md +202 -202
  157. package/templates/nextblock-template/docs/04-DATABASE-AND-AUTH.md +246 -246
  158. package/templates/nextblock-template/docs/06-CLI-AND-SCAFFOLDING.md +176 -176
  159. package/templates/nextblock-template/docs/07-BLOCK-SDK-AND-EXTENSIBILITY.md +146 -146
  160. package/templates/nextblock-template/docs/10-CUSTOM-BLOCKS.md +222 -222
  161. package/templates/nextblock-template/docs/11-SELF-HOSTED-DOCKER.md +173 -173
  162. package/templates/nextblock-template/docs/12-VERCEL-DEPLOYMENT.md +170 -170
  163. package/templates/nextblock-template/docs/13-STAYING-UP-TO-DATE.md +151 -151
  164. package/templates/nextblock-template/docs/README.md +39 -39
  165. package/templates/nextblock-template/hooks/use-hotkeys.ts +21 -21
  166. package/templates/nextblock-template/hooks/useGlobalSearch.ts +101 -101
  167. package/templates/nextblock-template/index.d.ts +7 -7
  168. package/templates/nextblock-template/lib/app-secrets.ts +39 -39
  169. package/templates/nextblock-template/lib/auth/cookies.ts +47 -47
  170. package/templates/nextblock-template/lib/auth/crypto.ts +45 -45
  171. package/templates/nextblock-template/lib/auth/trustedDevices.ts +92 -92
  172. package/templates/nextblock-template/lib/auth-redirects.ts +46 -46
  173. package/templates/nextblock-template/lib/blocks/README.md +13 -13
  174. package/templates/nextblock-template/lib/botProtection/verify.ts +134 -134
  175. package/templates/nextblock-template/lib/cms-transfer/server.ts +2243 -2243
  176. package/templates/nextblock-template/lib/cms-transfer/types.ts +145 -145
  177. package/templates/nextblock-template/lib/custom-block-definitions.ts +87 -87
  178. package/templates/nextblock-template/lib/custom-block-r2-upload-shared.ts +178 -178
  179. package/templates/nextblock-template/lib/custom-block-r2-upload.test.ts +140 -140
  180. package/templates/nextblock-template/lib/custom-block-r2-upload.ts +88 -88
  181. package/templates/nextblock-template/lib/custom-block-relations.test.ts +227 -227
  182. package/templates/nextblock-template/lib/custom-block-relations.ts +279 -279
  183. package/templates/nextblock-template/lib/custom-block-safelist.ts +14 -14
  184. package/templates/nextblock-template/lib/editor/dynamic-extension-core.test.ts +172 -172
  185. package/templates/nextblock-template/lib/editor/dynamic-extension-core.ts +213 -213
  186. package/templates/nextblock-template/lib/editor/dynamic-extension-loader.ts +22 -22
  187. package/templates/nextblock-template/lib/editor/dynamic-extensions.tsx +193 -193
  188. package/templates/nextblock-template/lib/email/branding-format.test.ts +133 -133
  189. package/templates/nextblock-template/lib/email/branding-format.ts +123 -123
  190. package/templates/nextblock-template/lib/email/branding.ts +76 -76
  191. package/templates/nextblock-template/lib/full-backup/manifest.test.ts +121 -121
  192. package/templates/nextblock-template/lib/full-backup/manifest.ts +206 -206
  193. package/templates/nextblock-template/lib/full-backup/server.ts +743 -743
  194. package/templates/nextblock-template/lib/logos/active-logo.ts +53 -53
  195. package/templates/nextblock-template/lib/media/resolveMediaUrl.ts +54 -54
  196. package/templates/nextblock-template/lib/media/youtube.ts +99 -99
  197. package/templates/nextblock-template/lib/onboarding/actions.ts +31 -31
  198. package/templates/nextblock-template/lib/onboarding/status.ts +222 -222
  199. package/templates/nextblock-template/lib/posts/readTime.ts +60 -60
  200. package/templates/nextblock-template/lib/privacy/consent-client.ts +57 -57
  201. package/templates/nextblock-template/lib/privacy/contact-emails.ts +64 -64
  202. package/templates/nextblock-template/lib/privacy/settings.ts +115 -115
  203. package/templates/nextblock-template/lib/privacy/types.ts +69 -69
  204. package/templates/nextblock-template/lib/promotions/server.test.ts +74 -74
  205. package/templates/nextblock-template/lib/promotions/server.ts +741 -741
  206. package/templates/nextblock-template/lib/resolve-block-relations.test.ts +142 -142
  207. package/templates/nextblock-template/lib/resolve-block-relations.ts +255 -255
  208. package/templates/nextblock-template/lib/search/types.ts +27 -27
  209. package/templates/nextblock-template/lib/setup/actions.ts +460 -460
  210. package/templates/nextblock-template/lib/setup/env-status.ts +125 -125
  211. package/templates/nextblock-template/lib/setup/env-write.ts +111 -111
  212. package/templates/nextblock-template/lib/setup/migrations-bundle.ts +87 -87
  213. package/templates/nextblock-template/lib/setup/provisioning.ts +59 -59
  214. package/templates/nextblock-template/lib/setup/schema-apply.ts +408 -408
  215. package/templates/nextblock-template/lib/setup/system-config.ts +105 -105
  216. package/templates/nextblock-template/lib/setup/types.ts +18 -18
  217. package/templates/nextblock-template/lib/site-url.ts +48 -48
  218. package/templates/nextblock-template/lib/storage/provider.ts +66 -66
  219. package/templates/nextblock-template/lib/storage/supabase-storage.ts +103 -103
  220. package/templates/nextblock-template/lib/updates/check-upstream.ts +441 -441
  221. package/templates/nextblock-template/lib/updates/github-device.ts +206 -206
  222. package/templates/nextblock-template/lib/updates/repo-identity.ts +56 -56
  223. package/templates/nextblock-template/package.json +1 -1
  224. package/templates/nextblock-template/postcss.config.js +6 -6
  225. package/templates/nextblock-template/scripts/backup.js +115 -115
  226. package/templates/nextblock-template/scripts/docker-setup.mjs +310 -310
  227. package/templates/nextblock-template/scripts/restore.js +385 -385
  228. package/templates/nextblock-template/scripts/verify-cortex-ai-build-widget.tsx +98 -98
  229. package/templates/nextblock-template/scripts/verify-cortex-ai-generate-blocks.ts +62 -62
  230. package/templates/nextblock-template/scripts/verify-cortex-ai-global-tools.ts +537 -537
  231. package/templates/nextblock-template/scripts/verify-cortex-ai-routing.ts +58 -58
  232. package/templates/nextblock-template/scripts/verify-custom-block-definitions.ts +188 -188
  233. package/templates/nextblock-template/scripts/verify-dynamic-custom-block-extensions.ts +123 -123
  234. package/templates/nextblock-template/scripts/verify-dynamic-layout-engine.tsx +133 -133
  235. package/templates/nextblock-template/scripts/verify-milestone-2-custom-blocks.ts +65 -65
  236. package/templates/nextblock-template/tailwind.config.js +25 -25
  237. package/templates/nextblock-template/tools/build-migrate.mjs +209 -209
  238. package/templates/nextblock-template/tools/configure-supabase-auth.js +282 -282
  239. package/templates/nextblock-template/tsconfig.tsbuildinfo +1 -1
  240. package/templates/nextblock-template/types/jsdom.d.ts +6 -6
  241. 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).