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