create-nextblock 0.11.1 → 0.11.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.
- package/package.json +1 -1
- package/templates/nextblock-template/app/actions/interactions.test.ts +301 -0
- package/templates/nextblock-template/app/actions/interactions.ts +372 -0
- package/templates/nextblock-template/app/api/ai/cortex/build-widget/route.ts +4 -4
- package/templates/nextblock-template/app/api/ai/generate-blocks/route.ts +2 -2
- package/templates/nextblock-template/app/api/ai/global-agent/route.ts +56 -57
- package/templates/nextblock-template/app/api/cron/reset-sandbox/route.ts +1 -1
- package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +837 -0
- package/templates/nextblock-template/app/article/[slug]/PostClientContent.tsx +6 -0
- package/templates/nextblock-template/app/cms/CmsClientLayout.tsx +4 -0
- package/templates/nextblock-template/app/cms/components/ConnectGitHubButton.tsx +7 -2
- package/templates/nextblock-template/app/cms/components/github-connect-actions.ts +4 -0
- package/templates/nextblock-template/app/cms/interactions/InteractionsModerationClient.tsx +408 -0
- package/templates/nextblock-template/app/cms/interactions/page.tsx +51 -0
- package/templates/nextblock-template/app/cms/settings/cortex-ai/SandboxCortexAiSettingsClient.tsx +4 -3
- package/templates/nextblock-template/app/cms/settings/cortex-ai/StoredCortexAiSettingsClient.tsx +1 -1
- package/templates/nextblock-template/app/cms/settings/cortex-ai/actions.ts +3 -5
- package/templates/nextblock-template/app/cms/settings/cortex-ai/page.tsx +1 -1
- package/templates/nextblock-template/app/page.tsx +2 -2
- package/templates/nextblock-template/app/product/[slug]/page.tsx +2 -0
- package/templates/nextblock-template/components/AppShell.tsx +1 -1
- package/templates/nextblock-template/components/PostCommentsSection.tsx +369 -0
- package/templates/nextblock-template/components/ProductReviewsSection.tsx +419 -0
- package/templates/nextblock-template/components/blocks/renderers/ProductDetailsBlockRenderer.tsx +2 -0
- package/templates/nextblock-template/components/privacy/ConsentBanner.tsx +62 -19
- package/templates/nextblock-template/docs/08-NEXTBLOCK-CORTEX-AI-ARCHITECTURE.md +19 -19
- package/templates/nextblock-template/docs/10-CUSTOM-BLOCKS.md +4 -4
- package/templates/nextblock-template/lib/blocks/ProductGridBlock.tsx +2 -0
- package/templates/nextblock-template/lib/setup/actions.ts +3 -1
- package/templates/nextblock-template/lib/setup/migrations-bundle.ts +30 -0
- package/templates/nextblock-template/lib/updates/check-upstream.ts +38 -4
- package/templates/nextblock-template/package.json +2 -1
- package/templates/nextblock-template/scripts/verify-cortex-ai-build-widget.tsx +2 -4
- package/templates/nextblock-template/scripts/verify-cortex-ai-generate-blocks.ts +1 -1
- package/templates/nextblock-template/scripts/verify-cortex-ai-global-tools.ts +1 -1
- package/templates/nextblock-template/scripts/verify-cortex-ai-routing.ts +1 -1
- package/templates/nextblock-template/tsconfig.tsbuildinfo +1 -1
- package/templates/nextblock-template/lib/ai-block-generation.ts +0 -339
- package/templates/nextblock-template/lib/ai-client.ts +0 -247
- package/templates/nextblock-template/lib/ai-config.ts +0 -98
- package/templates/nextblock-template/lib/ai-cortex-widget-builder.ts +0 -125
- package/templates/nextblock-template/lib/ai-global-agent-custom-block-tools.ts +0 -363
- package/templates/nextblock-template/lib/ai-global-agent-db-tools.test.ts +0 -405
- package/templates/nextblock-template/lib/ai-global-agent-db-tools.ts +0 -1228
- package/templates/nextblock-template/lib/ai-global-agent-ecommerce.ts +0 -5
- package/templates/nextblock-template/lib/ai-global-agent-tools-stats.test.ts +0 -223
- package/templates/nextblock-template/lib/ai-global-agent-tools.test.ts +0 -2183
- package/templates/nextblock-template/lib/ai-global-agent-tools.ts +0 -4807
- package/templates/nextblock-template/lib/ai-key-crypto.test.ts +0 -70
- package/templates/nextblock-template/lib/ai-key-crypto.ts +0 -132
- package/templates/nextblock-template/lib/ai-model-catalog.test.ts +0 -49
- package/templates/nextblock-template/lib/ai-model-catalog.ts +0 -41
- package/templates/nextblock-template/lib/ai-model-registry.test.ts +0 -231
- package/templates/nextblock-template/lib/ai-model-registry.ts +0 -522
- package/templates/nextblock-template/lib/cortex-widget-registry.test.ts +0 -199
- package/templates/nextblock-template/lib/cortex-widget-registry.ts +0 -88
- package/templates/nextblock-template/lib/cortex-widget-schema.test.tsx +0 -237
- package/templates/nextblock-template/lib/cortex-widget-schema.ts +0 -393
|
@@ -8255,6 +8255,843 @@ grant select, update on public.system_alerts to authenticated;
|
|
|
8255
8255
|
grant all on public.system_alerts to service_role;
|
|
8256
8256
|
|
|
8257
8257
|
|
|
8258
|
+
-- >>> FROM: 00000000000037_refresh_setup_article_install_paths.sql <<<
|
|
8259
|
+
-- Rewrite the seeded "How to Setup NextBlock" tutorial (EN + FR) around the four
|
|
8260
|
+
-- current installation paths:
|
|
8261
|
+
-- 1. One-click Deploy on Vercel (Supabase Marketplace integration, zero env vars),
|
|
8262
|
+
-- 2. npm create nextblock (standalone app, browser /setup wizard on :3000),
|
|
8263
|
+
-- 3. git clone -> npm install -> npx nx serve nextblock (browser /setup wizard on :4200),
|
|
8264
|
+
-- 4. git clone -> npm install -> npm run docker:setup (fully local, non-interactive).
|
|
8265
|
+
--
|
|
8266
|
+
-- Also sets the posts' meta_title / meta_description (previously unset — SEO title fell
|
|
8267
|
+
-- back to posts.title and the description to posts.subtitle) and refreshes
|
|
8268
|
+
-- title / subtitle / excerpt for both languages. Slugs are intentionally unchanged:
|
|
8269
|
+
-- 'how-to-setup-nextblock' and 'comment-configurer-nextblock' are public URLs and are
|
|
8270
|
+
-- also mapped to the tutorial presentation (post-article--tutorial) by slug.
|
|
8271
|
+
--
|
|
8272
|
+
-- Forward-only and idempotent: it updates the two posts rows and replaces their single
|
|
8273
|
+
-- text block (same pattern as 00000000000029). Safe to re-run; a no-op if the posts
|
|
8274
|
+
-- do not exist.
|
|
8275
|
+
|
|
8276
|
+
-- EN post metadata
|
|
8277
|
+
UPDATE public.posts
|
|
8278
|
+
SET
|
|
8279
|
+
title = 'How to Install NextBlock: Every Setup Option Explained',
|
|
8280
|
+
subtitle = 'Four ways to launch NextBlock: a one-click Vercel deploy, npm create nextblock, git clone with the browser setup wizard, or a fully local Docker stack.',
|
|
8281
|
+
excerpt = 'Every way to install NextBlock — one-click cloud deploy, CLI scaffold, git clone, or self-hosted Docker — with copy-paste steps for each.',
|
|
8282
|
+
meta_title = 'How to Install NextBlock CMS — Vercel, CLI, Git or Docker',
|
|
8283
|
+
meta_description = 'Install NextBlock in minutes — one-click Vercel deploy, npm create nextblock, git clone, or self-hosted Docker. No config files, no manual SQL.'
|
|
8284
|
+
WHERE slug = 'how-to-setup-nextblock';
|
|
8285
|
+
|
|
8286
|
+
-- FR post metadata
|
|
8287
|
+
UPDATE public.posts
|
|
8288
|
+
SET
|
|
8289
|
+
title = $meta$Installer NextBlock : toutes les options expliquées$meta$,
|
|
8290
|
+
subtitle = $meta$Quatre façons de lancer NextBlock : déploiement Vercel en un clic, npm create nextblock, git clone avec l'assistant dans le navigateur, ou une pile Docker 100 % locale.$meta$,
|
|
8291
|
+
excerpt = $meta$Toutes les façons d'installer NextBlock — cloud en un clic, CLI, git clone ou Docker auto-hébergé — avec les étapes à copier-coller.$meta$,
|
|
8292
|
+
meta_title = $meta$Installer NextBlock — Vercel, CLI, Git ou Docker$meta$,
|
|
8293
|
+
meta_description = $meta$Installez NextBlock en quelques minutes : déploiement Vercel en un clic, npm create nextblock, git clone ou Docker auto-hébergé. Sans config ni SQL.$meta$
|
|
8294
|
+
WHERE slug = 'comment-configurer-nextblock';
|
|
8295
|
+
|
|
8296
|
+
WITH target_posts AS (
|
|
8297
|
+
SELECT id, language_id, slug
|
|
8298
|
+
FROM public.posts
|
|
8299
|
+
WHERE slug IN ('how-to-setup-nextblock', 'comment-configurer-nextblock')
|
|
8300
|
+
),
|
|
8301
|
+
purged AS (
|
|
8302
|
+
DELETE FROM public.blocks
|
|
8303
|
+
WHERE post_id IN (SELECT id FROM target_posts)
|
|
8304
|
+
)
|
|
8305
|
+
INSERT INTO public.blocks (post_id, language_id, block_type, content, "order")
|
|
8306
|
+
|
|
8307
|
+
-- EN: How to Install NextBlock
|
|
8308
|
+
SELECT tp.id, tp.language_id, 'text', jsonb_build_object('html_content',
|
|
8309
|
+
$$<p class='text-lg leading-8 text-slate-700 dark:text-slate-300'>NextBlock is an open-source, AI-native Next.js CMS built on Supabase — and installing it no longer involves config files, terminal wizards, or manual SQL. There are four ways to get running, and they all end in the same place: a browser <strong>setup wizard</strong> that connects your database, configures media storage, and creates your admin account for you. Pick the path that fits, follow the steps, and you will be publishing in minutes.</p>
|
|
8310
|
+
|
|
8311
|
+
<div class='grid gap-5 md:grid-cols-2 my-10'>
|
|
8312
|
+
<a href='#one-click-vercel' class='block rounded-[1.75rem] border border-blue-200 bg-blue-50/70 p-6 no-underline transition-shadow hover:shadow-lg dark:border-blue-500/20 dark:bg-blue-500/10'>
|
|
8313
|
+
<p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-blue-700 dark:text-blue-200'>Fastest · about 3 minutes</p>
|
|
8314
|
+
<h3 class='mt-3 mb-2 text-xl font-semibold text-slate-900 dark:text-white'>One-click deploy on Vercel</h3>
|
|
8315
|
+
<p class='mb-0 text-sm leading-6 text-slate-600 dark:text-slate-300'>A live production site with a managed database. No terminal, no environment variables, nothing to copy.</p>
|
|
8316
|
+
</a>
|
|
8317
|
+
<a href='#npm-create' class='block rounded-[1.75rem] border border-violet-200 bg-violet-50/70 p-6 no-underline transition-shadow hover:shadow-lg dark:border-violet-500/20 dark:bg-violet-500/10'>
|
|
8318
|
+
<p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200'>Recommended for new projects</p>
|
|
8319
|
+
<h3 class='mt-3 mb-2 text-xl font-semibold text-slate-900 dark:text-white'>npm create nextblock</h3>
|
|
8320
|
+
<p class='mb-0 text-sm leading-6 text-slate-600 dark:text-slate-300'>Scaffold a standalone Next.js app with NextBlock built in, then finish setup in your browser.</p>
|
|
8321
|
+
</a>
|
|
8322
|
+
<a href='#git-clone' class='block rounded-[1.75rem] border border-emerald-200 bg-emerald-50/70 p-6 no-underline transition-shadow hover:shadow-lg dark:border-emerald-500/20 dark:bg-emerald-500/10'>
|
|
8323
|
+
<p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200'>Full source code</p>
|
|
8324
|
+
<h3 class='mt-3 mb-2 text-xl font-semibold text-slate-900 dark:text-white'>Clone the repository</h3>
|
|
8325
|
+
<p class='mb-0 text-sm leading-6 text-slate-600 dark:text-slate-300'>Run the complete monorepo — the CMS, every package, and the docs. Made for contributors and platform teams.</p>
|
|
8326
|
+
</a>
|
|
8327
|
+
<a href='#docker' class='block rounded-[1.75rem] border border-amber-200 bg-amber-50/70 p-6 no-underline transition-shadow hover:shadow-lg dark:border-amber-500/20 dark:bg-amber-500/10'>
|
|
8328
|
+
<p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-amber-700 dark:text-amber-200'>100% local · no accounts</p>
|
|
8329
|
+
<h3 class='mt-3 mb-2 text-xl font-semibold text-slate-900 dark:text-white'>Self-hosted with Docker</h3>
|
|
8330
|
+
<p class='mb-0 text-sm leading-6 text-slate-600 dark:text-slate-300'>One command boots the entire stack on your machine — database, auth, storage, and the CMS. No cloud services at all.</p>
|
|
8331
|
+
</a>
|
|
8332
|
+
</div>
|
|
8333
|
+
|
|
8334
|
+
<p class='text-sm text-slate-500 dark:text-slate-400'>Not sure which to pick? If you want a live website with the least effort, choose <a href='#one-click-vercel'>Vercel</a>. If you want a local project to build on, choose <a href='#npm-create'>npm create nextblock</a>.</p>
|
|
8335
|
+
|
|
8336
|
+
<figure class='my-12 overflow-hidden rounded-[2rem] border border-slate-200/80 bg-slate-950 shadow-2xl dark:border-white/10'>
|
|
8337
|
+
<img src='/images/included.webp' alt='NextBlock CMS platform overview showing the block editor, CMS dashboard, and integrations included with every installation' class='w-full h-auto object-cover' />
|
|
8338
|
+
<figcaption class='border-t border-white/10 px-6 py-4 text-sm text-slate-300'>Whichever path you choose, you get the same block editor, the same CMS, and the same database schema.</figcaption>
|
|
8339
|
+
</figure>
|
|
8340
|
+
|
|
8341
|
+
<h2 id='one-click-vercel'>Option 1: One-Click Deploy on Vercel</h2>
|
|
8342
|
+
<p>The fastest way to get a production NextBlock site. One button creates your own copy of NextBlock on GitHub, provisions a managed Supabase database, and deploys the site — you never open a terminal or copy a single key.</p>
|
|
8343
|
+
<ol class='space-y-2'>
|
|
8344
|
+
<li><strong>Click Deploy to Vercel</strong> and sign in — Vercel clones NextBlock into a new repository you own.</li>
|
|
8345
|
+
<li><strong>Create the Supabase database</strong> when prompted: pick a name and a region. Vercel connects it to the project and injects the keys before the first build.</li>
|
|
8346
|
+
<li><strong>Open your new site</strong> once the build finishes. Every fresh instance takes you straight to the setup wizard.</li>
|
|
8347
|
+
<li><strong>Create your administrator account.</strong> It is confirmed instantly — no verification email — and you land in the CMS dashboard.</li>
|
|
8348
|
+
</ol>
|
|
8349
|
+
<div class='my-8'>
|
|
8350
|
+
<a href='https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fnextblock-cms%2Fnextblock&project-name=nextblock&repository-name=nextblock&stores=%5B%7B%22type%22%3A%22integration%22%2C%22integrationSlug%22%3A%22supabase%22%2C%22productSlug%22%3A%22supabase%22%7D%5D' target='_blank' rel='noopener' class='inline-flex items-center rounded-full bg-slate-900 px-6 py-3 text-sm font-semibold text-white no-underline shadow-lg hover:bg-slate-700 dark:bg-white dark:text-slate-900 dark:hover:bg-slate-200'>Deploy to Vercel →</a>
|
|
8351
|
+
</div>
|
|
8352
|
+
<div class='rounded-3xl border border-blue-200 bg-blue-50/80 p-6 my-8 dark:border-blue-500/20 dark:bg-blue-500/10'>
|
|
8353
|
+
<p class='mt-0 text-xs font-semibold uppercase tracking-[0.22em] text-blue-700 dark:text-blue-200'>Zero configuration</p>
|
|
8354
|
+
<p class='mt-3 mb-0 text-sm text-slate-700 dark:text-slate-200'>There are no environment variables to fill in. Media storage automatically uses your connected Supabase project, security secrets are derived for you, and database migrations run automatically on every production build. Adding a custom domain later? Set <code>NEXT_PUBLIC_URL</code> in your Vercel project and redeploy.</p>
|
|
8355
|
+
</div>
|
|
8356
|
+
<p>Your site also keeps itself current: the dashboard checklist includes a one-click <strong>Connect GitHub</strong> step that installs a daily workflow syncing your copy with the latest NextBlock release.</p>
|
|
8357
|
+
|
|
8358
|
+
<h2 id='npm-create'>Option 2: Scaffold a Project with npm create nextblock</h2>
|
|
8359
|
+
<p>The best starting point for building your own site. The CLI scaffolds a standalone Next.js application with NextBlock already wired in — no monorepo, no workspace tooling — and hands everything else to the browser wizard.</p>
|
|
8360
|
+
<p>Before you start, install <a href='https://nodejs.org' target='_blank' rel='noopener'>Node.js 20 or newer</a> (it includes npm), then create a free project at <a href='https://supabase.com' target='_blank' rel='noopener'>supabase.com</a> (or pick the CLI's Docker mode during creation and skip cloud accounts entirely).</p>
|
|
8361
|
+
<pre><code>npm create nextblock@latest my-site
|
|
8362
|
+
cd my-site
|
|
8363
|
+
npm run dev</code></pre>
|
|
8364
|
+
<p>Open <code>http://localhost:3000/setup</code> and let the wizard take over:</p>
|
|
8365
|
+
<ol class='space-y-2'>
|
|
8366
|
+
<li><strong>Connect Supabase</strong> — paste your project URL, publishable (anon) key, secret (service role) key, and a personal access token so the wizard can apply the database schema for you.</li>
|
|
8367
|
+
<li><strong>Choose media storage</strong> — plug in a Cloudflare R2 bucket for images and files, or leave it blank to use your connected Supabase project's storage.</li>
|
|
8368
|
+
<li><strong>Create your administrator</strong> — the wizard applies every migration, generates the app secrets, writes <code>.env.local</code>, creates your confirmed admin account, and signs you in. Restart <code>npm run dev</code> once afterwards so the fresh environment is baked into the app.</li>
|
|
8369
|
+
</ol>
|
|
8370
|
+
<div class='rounded-3xl border border-violet-200 bg-violet-50/80 p-6 my-8 dark:border-violet-500/20 dark:bg-violet-500/10'>
|
|
8371
|
+
<p class='mt-0 text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200'>Premium modules</p>
|
|
8372
|
+
<p class='mt-3 mb-0 text-sm text-slate-700 dark:text-slate-200'>Need a store? One command adds products, checkout, orders, and coupons — license-gated and ready when you are: <code>npx create-nextblock activate ecommerce</code></p>
|
|
8373
|
+
</div>
|
|
8374
|
+
|
|
8375
|
+
<h2 id='git-clone'>Option 3: Clone the Repository</h2>
|
|
8376
|
+
<p>Run the full Nx monorepo: the CMS application, every shared package, the CLI source, and the documentation. This is the path for contributors, plugin authors, and teams that customize the platform itself.</p>
|
|
8377
|
+
<pre><code>git clone https://github.com/nextblock-cms/nextblock.git
|
|
8378
|
+
cd nextblock
|
|
8379
|
+
npm install
|
|
8380
|
+
npx nx serve nextblock</code></pre>
|
|
8381
|
+
<p>Open <code>http://localhost:4200</code> — a fresh install redirects every page to <code>/setup</code>, where the same three-step wizard connects Supabase, configures storage, and creates your admin. It validates your keys, writes <code>.env.local</code> with generated secrets, and applies all migrations over the Supabase Management API — no Supabase CLI required.</p>
|
|
8382
|
+
<div class='rounded-3xl border border-emerald-200 bg-emerald-50/80 p-6 my-8 dark:border-emerald-500/20 dark:bg-emerald-500/10'>
|
|
8383
|
+
<p class='mt-0 text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200'>No terminal setup</p>
|
|
8384
|
+
<p class='mt-3 mb-0 text-sm text-slate-700 dark:text-slate-200'>Configuration moved entirely to the browser — there is no interactive terminal step anymore. When the wizard finishes you are signed in as the administrator; restart the dev server once afterwards so the fresh environment is baked into the app bundle.</p>
|
|
8385
|
+
</div>
|
|
8386
|
+
|
|
8387
|
+
<h2 id='docker'>Option 4: Self-Hosted with Docker</h2>
|
|
8388
|
+
<p>Everything runs on your machine: Supabase's Postgres and auth engines, a PostgREST API behind a Kong gateway, S3-compatible MinIO storage, and the CMS itself. No Supabase account, no Vercel, no email service — ideal for evaluations, air-gapped environments, and anyone who wants a fully self-hosted CMS with complete data ownership.</p>
|
|
8389
|
+
<p>With <a href='https://www.docker.com/products/docker-desktop/' target='_blank' rel='noopener'>Docker Desktop</a> installed and running:</p>
|
|
8390
|
+
<pre><code>git clone https://github.com/nextblock-cms/nextblock.git
|
|
8391
|
+
cd nextblock
|
|
8392
|
+
npm install
|
|
8393
|
+
npm run docker:setup</code></pre>
|
|
8394
|
+
<p>The command asks nothing: it generates secure keys, builds the stack, applies every migration, and starts the services. When it finishes, open <code>http://localhost:3000</code> — the setup wizard already has the database and MinIO storage wired up, so the only step left is creating your administrator (confirmed instantly, no email required).</p>
|
|
8395
|
+
<div class='rounded-3xl border border-amber-200 bg-amber-50/80 p-6 my-8 dark:border-amber-500/20 dark:bg-amber-500/10'>
|
|
8396
|
+
<p class='mt-0 text-xs font-semibold uppercase tracking-[0.22em] text-amber-700 dark:text-amber-200'>Day-2 commands</p>
|
|
8397
|
+
<pre class='mt-4 mb-0'><code># rebuild and restart the stack
|
|
8398
|
+
npm run docker:up
|
|
8399
|
+
|
|
8400
|
+
# stop the stack (your data persists in Docker volumes)
|
|
8401
|
+
npm run docker:down
|
|
8402
|
+
|
|
8403
|
+
# follow the application logs
|
|
8404
|
+
npm run docker:logs</code></pre>
|
|
8405
|
+
</div>
|
|
8406
|
+
|
|
8407
|
+
<h2 id='after-install'>After You Install: Your First 10 Minutes</h2>
|
|
8408
|
+
<p>Every path drops you at <code>/cms/dashboard</code>, signed in as the first administrator. A built-in onboarding checklist walks you through the rest:</p>
|
|
8409
|
+
<ul class='space-y-2'>
|
|
8410
|
+
<li><strong>Add your branding</strong> — upload your logo and set the site title.</li>
|
|
8411
|
+
<li><strong>Set your footer</strong> — copyright line and footer navigation.</li>
|
|
8412
|
+
<li><strong>Configure email (SMTP)</strong> — under Settings, so password resets and invitations can send.</li>
|
|
8413
|
+
<li><strong>Optional extras</strong> — connect analytics, enable bot protection, and (on Vercel) turn on automatic updates.</li>
|
|
8414
|
+
</ul>
|
|
8415
|
+
<p>From there, see how the platform fits together in <a href='/article/how-nextblock-works'>How NextBlock Works</a>, add a storefront with the <a href='/article/nextblock-commerce-guide'>Commerce guide</a>, or meet your AI copilot in the <a href='/article/nextblock-cortex-ai-guide'>Cortex AI guide</a>.</p>
|
|
8416
|
+
|
|
8417
|
+
<h2 id='faq'>Installation FAQ</h2>
|
|
8418
|
+
<h3>What do I need installed?</h3>
|
|
8419
|
+
<p>Nothing for the Vercel path — it runs entirely in the browser. For <code>npm create nextblock</code>: <a href='https://nodejs.org' target='_blank' rel='noopener'>Node.js 20+</a> (which includes npm). For the cloned repository: Node.js 20+ and git. For Docker: those plus Docker Desktop.</p>
|
|
8420
|
+
<h3>Is NextBlock free?</h3>
|
|
8421
|
+
<p>Yes — the core of NextBlock is a 100% free, open-source CMS (AGPL). Premium packages such as e-commerce and Cortex AI are optional and activate with a license key. Both Vercel and Supabase offer free tiers, so a starter site can run at no cost.</p>
|
|
8422
|
+
<h3>Do I need a Supabase account?</h3>
|
|
8423
|
+
<p>On Vercel, the database is created for you during the deploy. For <code>npm create nextblock</code> and the cloned repository you bring a free Supabase project. With Docker you need no cloud accounts at all.</p>
|
|
8424
|
+
<h3>Do I have to run migrations or SQL by hand?</h3>
|
|
8425
|
+
<p>No. The setup wizard, the Vercel build, and the Docker stack all apply the database schema automatically — and re-running is always safe.</p>
|
|
8426
|
+
<h3>Can I switch paths later?</h3>
|
|
8427
|
+
<p>Yes. Every path runs the same application and the same database schema, so you can prototype locally with Docker today and deploy to Vercel tomorrow. NextBlock deploys like any standard Next.js app.</p>
|
|
8428
|
+
<h3>How do I update NextBlock?</h3>
|
|
8429
|
+
<p>On Vercel, the Connect GitHub onboarding step enables a daily automatic sync with upstream. On a cloned repository, <code>git pull</code>, run <code>npm run db:migrate</code>, then restart (on production builds, pending migrations apply automatically). With Docker, pull the latest code and run <code>npm run docker:up</code>.</p>
|
|
8430
|
+
|
|
8431
|
+
<div class='rounded-[2rem] border border-slate-200/80 bg-slate-50 p-8 my-12 text-center dark:border-white/10 dark:bg-white/5'>
|
|
8432
|
+
<p class='mt-0 text-2xl font-semibold text-slate-900 dark:text-white'>Ready to launch?</p>
|
|
8433
|
+
<p class='text-sm text-slate-600 dark:text-slate-300'>Pick your path above, or jump straight to the fastest one.</p>
|
|
8434
|
+
<div class='mt-5 flex flex-wrap justify-center gap-3'>
|
|
8435
|
+
<a href='https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fnextblock-cms%2Fnextblock&project-name=nextblock&repository-name=nextblock&stores=%5B%7B%22type%22%3A%22integration%22%2C%22integrationSlug%22%3A%22supabase%22%2C%22productSlug%22%3A%22supabase%22%7D%5D' target='_blank' rel='noopener' class='inline-flex items-center rounded-full bg-slate-900 px-6 py-3 text-sm font-semibold text-white no-underline shadow-lg hover:bg-slate-700 dark:bg-white dark:text-slate-900 dark:hover:bg-slate-200'>Deploy on Vercel</a>
|
|
8436
|
+
<a href='https://github.com/nextblock-cms/nextblock' target='_blank' rel='noopener' class='inline-flex items-center rounded-full border border-slate-300 px-6 py-3 text-sm font-semibold text-slate-700 no-underline hover:border-slate-500 dark:border-white/20 dark:text-slate-200 dark:hover:border-white/50'>View on GitHub</a>
|
|
8437
|
+
</div>
|
|
8438
|
+
</div>$$
|
|
8439
|
+
), 0 FROM target_posts tp WHERE tp.slug = 'how-to-setup-nextblock'
|
|
8440
|
+
|
|
8441
|
+
UNION ALL
|
|
8442
|
+
|
|
8443
|
+
-- FR: Installer NextBlock
|
|
8444
|
+
SELECT tp.id, tp.language_id, 'text', jsonb_build_object('html_content',
|
|
8445
|
+
$$<p class='text-lg leading-8 text-slate-700 dark:text-slate-300'>NextBlock est un CMS open source et natif IA, construit sur Next.js et Supabase — et son installation ne passe plus par des fichiers de configuration, des assistants en ligne de commande ou du SQL manuel. Il existe quatre façons de démarrer, et elles aboutissent toutes au même endroit : un <strong>assistant de configuration</strong> dans le navigateur qui connecte votre base de données, configure le stockage des médias et crée votre compte administrateur. Choisissez le chemin qui vous convient, suivez les étapes, et vous publierez en quelques minutes.</p>
|
|
8446
|
+
|
|
8447
|
+
<div class='grid gap-5 md:grid-cols-2 my-10'>
|
|
8448
|
+
<a href='#one-click-vercel' class='block rounded-[1.75rem] border border-blue-200 bg-blue-50/70 p-6 no-underline transition-shadow hover:shadow-lg dark:border-blue-500/20 dark:bg-blue-500/10'>
|
|
8449
|
+
<p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-blue-700 dark:text-blue-200'>Le plus rapide · environ 3 minutes</p>
|
|
8450
|
+
<h3 class='mt-3 mb-2 text-xl font-semibold text-slate-900 dark:text-white'>Déploiement Vercel en un clic</h3>
|
|
8451
|
+
<p class='mb-0 text-sm leading-6 text-slate-600 dark:text-slate-300'>Un site de production en ligne avec une base de données gérée. Pas de terminal, pas de variables d'environnement, rien à copier.</p>
|
|
8452
|
+
</a>
|
|
8453
|
+
<a href='#npm-create' class='block rounded-[1.75rem] border border-violet-200 bg-violet-50/70 p-6 no-underline transition-shadow hover:shadow-lg dark:border-violet-500/20 dark:bg-violet-500/10'>
|
|
8454
|
+
<p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200'>Recommandé pour les nouveaux projets</p>
|
|
8455
|
+
<h3 class='mt-3 mb-2 text-xl font-semibold text-slate-900 dark:text-white'>npm create nextblock</h3>
|
|
8456
|
+
<p class='mb-0 text-sm leading-6 text-slate-600 dark:text-slate-300'>Générez une app Next.js autonome avec NextBlock intégré, puis terminez la configuration dans votre navigateur.</p>
|
|
8457
|
+
</a>
|
|
8458
|
+
<a href='#git-clone' class='block rounded-[1.75rem] border border-emerald-200 bg-emerald-50/70 p-6 no-underline transition-shadow hover:shadow-lg dark:border-emerald-500/20 dark:bg-emerald-500/10'>
|
|
8459
|
+
<p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200'>Code source complet</p>
|
|
8460
|
+
<h3 class='mt-3 mb-2 text-xl font-semibold text-slate-900 dark:text-white'>Cloner le dépôt</h3>
|
|
8461
|
+
<p class='mb-0 text-sm leading-6 text-slate-600 dark:text-slate-300'>Faites tourner le monorepo complet — le CMS, tous les packages et la documentation. Conçu pour les contributeurs et les équipes plateforme.</p>
|
|
8462
|
+
</a>
|
|
8463
|
+
<a href='#docker' class='block rounded-[1.75rem] border border-amber-200 bg-amber-50/70 p-6 no-underline transition-shadow hover:shadow-lg dark:border-amber-500/20 dark:bg-amber-500/10'>
|
|
8464
|
+
<p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-amber-700 dark:text-amber-200'>100 % local · aucun compte</p>
|
|
8465
|
+
<h3 class='mt-3 mb-2 text-xl font-semibold text-slate-900 dark:text-white'>Auto-hébergé avec Docker</h3>
|
|
8466
|
+
<p class='mb-0 text-sm leading-6 text-slate-600 dark:text-slate-300'>Une seule commande démarre toute la pile sur votre machine — base de données, auth, stockage et le CMS. Aucun service cloud.</p>
|
|
8467
|
+
</a>
|
|
8468
|
+
</div>
|
|
8469
|
+
|
|
8470
|
+
<p class='text-sm text-slate-500 dark:text-slate-400'>Vous hésitez ? Pour un site en ligne avec le minimum d'effort, choisissez <a href='#one-click-vercel'>Vercel</a>. Pour un projet local à personnaliser, choisissez <a href='#npm-create'>npm create nextblock</a>.</p>
|
|
8471
|
+
|
|
8472
|
+
<figure class='my-12 overflow-hidden rounded-[2rem] border border-slate-200/80 bg-slate-950 shadow-2xl dark:border-white/10'>
|
|
8473
|
+
<img src='/images/included.webp' alt='Aperçu de la plateforme NextBlock : éditeur de blocs, tableau de bord CMS et intégrations incluses dans chaque installation' class='w-full h-auto object-cover' />
|
|
8474
|
+
<figcaption class='border-t border-white/10 px-6 py-4 text-sm text-slate-300'>Quel que soit le chemin choisi, vous obtenez le même éditeur de blocs, le même CMS et le même schéma de base de données.</figcaption>
|
|
8475
|
+
</figure>
|
|
8476
|
+
|
|
8477
|
+
<h2 id='one-click-vercel'>Option 1 : Déploiement Vercel en un clic</h2>
|
|
8478
|
+
<p>Le moyen le plus rapide d'obtenir un site NextBlock en production. Un seul bouton crée votre propre copie de NextBlock sur GitHub, provisionne une base de données Supabase gérée et déploie le site — sans jamais ouvrir un terminal ni copier la moindre clé.</p>
|
|
8479
|
+
<ol class='space-y-2'>
|
|
8480
|
+
<li><strong>Cliquez sur Deploy to Vercel</strong> et connectez-vous — Vercel clone NextBlock dans un nouveau dépôt qui vous appartient.</li>
|
|
8481
|
+
<li><strong>Créez la base de données Supabase</strong> quand on vous le demande : choisissez un nom et une région. Vercel la connecte au projet et injecte les clés avant le premier build.</li>
|
|
8482
|
+
<li><strong>Ouvrez votre nouveau site</strong> une fois le build terminé. Toute nouvelle instance vous amène directement à l'assistant de configuration.</li>
|
|
8483
|
+
<li><strong>Créez votre compte administrateur.</strong> Il est confirmé instantanément — aucun email de vérification — et vous arrivez dans le tableau de bord du CMS.</li>
|
|
8484
|
+
</ol>
|
|
8485
|
+
<div class='my-8'>
|
|
8486
|
+
<a href='https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fnextblock-cms%2Fnextblock&project-name=nextblock&repository-name=nextblock&stores=%5B%7B%22type%22%3A%22integration%22%2C%22integrationSlug%22%3A%22supabase%22%2C%22productSlug%22%3A%22supabase%22%7D%5D' target='_blank' rel='noopener' class='inline-flex items-center rounded-full bg-slate-900 px-6 py-3 text-sm font-semibold text-white no-underline shadow-lg hover:bg-slate-700 dark:bg-white dark:text-slate-900 dark:hover:bg-slate-200'>Déployer sur Vercel →</a>
|
|
8487
|
+
</div>
|
|
8488
|
+
<div class='rounded-3xl border border-blue-200 bg-blue-50/80 p-6 my-8 dark:border-blue-500/20 dark:bg-blue-500/10'>
|
|
8489
|
+
<p class='mt-0 text-xs font-semibold uppercase tracking-[0.22em] text-blue-700 dark:text-blue-200'>Zéro configuration</p>
|
|
8490
|
+
<p class='mt-3 mb-0 text-sm text-slate-700 dark:text-slate-200'>Aucune variable d'environnement à remplir. Le stockage des médias utilise automatiquement votre projet Supabase connecté, les secrets de sécurité sont dérivés pour vous, et les migrations de base de données s'exécutent automatiquement à chaque build de production. Un domaine personnalisé plus tard ? Définissez <code>NEXT_PUBLIC_URL</code> dans votre projet Vercel et redéployez.</p>
|
|
8491
|
+
</div>
|
|
8492
|
+
<p>Par ailleurs, votre site reste à jour tout seul : la checklist du tableau de bord inclut une étape <strong>Connect GitHub</strong> en un clic qui installe un workflow quotidien synchronisant votre copie avec la dernière version de NextBlock.</p>
|
|
8493
|
+
|
|
8494
|
+
<h2 id='npm-create'>Option 2 : Créer un projet avec npm create nextblock</h2>
|
|
8495
|
+
<p>Le meilleur point de départ pour construire votre propre site. Le CLI génère une application Next.js autonome avec NextBlock déjà intégré — sans monorepo ni outillage de workspace — et confie tout le reste à l'assistant dans le navigateur.</p>
|
|
8496
|
+
<p>Avant de commencer, installez <a href='https://nodejs.org' target='_blank' rel='noopener'>Node.js 20 ou plus récent</a> (npm inclus), puis créez un projet gratuit sur <a href='https://supabase.com' target='_blank' rel='noopener'>supabase.com</a> (ou choisissez le mode Docker du CLI pendant la création et passez-vous entièrement de comptes cloud).</p>
|
|
8497
|
+
<pre><code>npm create nextblock@latest mon-site
|
|
8498
|
+
cd mon-site
|
|
8499
|
+
npm run dev</code></pre>
|
|
8500
|
+
<p>Ouvrez <code>http://localhost:3000/setup</code> et laissez l'assistant faire le travail :</p>
|
|
8501
|
+
<ol class='space-y-2'>
|
|
8502
|
+
<li><strong>Connectez Supabase</strong> — collez l'URL du projet, la clé publiable (anon), la clé secrète (service role) et un jeton d'accès personnel pour que l'assistant applique le schéma de base de données à votre place.</li>
|
|
8503
|
+
<li><strong>Choisissez le stockage des médias</strong> — branchez un bucket Cloudflare R2 pour les images et les fichiers, ou laissez les champs vides pour utiliser le stockage de votre projet Supabase.</li>
|
|
8504
|
+
<li><strong>Créez votre administrateur</strong> — l'assistant applique toutes les migrations, génère les secrets de l'application, écrit <code>.env.local</code>, crée votre compte admin confirmé et vous connecte. Redémarrez ensuite <code>npm run dev</code> une fois pour que le nouvel environnement soit intégré à l'application.</li>
|
|
8505
|
+
</ol>
|
|
8506
|
+
<div class='rounded-3xl border border-violet-200 bg-violet-50/80 p-6 my-8 dark:border-violet-500/20 dark:bg-violet-500/10'>
|
|
8507
|
+
<p class='mt-0 text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200'>Modules premium</p>
|
|
8508
|
+
<p class='mt-3 mb-0 text-sm text-slate-700 dark:text-slate-200'>Besoin d'une boutique ? Une seule commande ajoute produits, paiement, commandes et coupons — activés par clé de licence, prêts quand vous l'êtes : <code>npx create-nextblock activate ecommerce</code></p>
|
|
8509
|
+
</div>
|
|
8510
|
+
|
|
8511
|
+
<h2 id='git-clone'>Option 3 : Cloner le dépôt</h2>
|
|
8512
|
+
<p>Faites tourner le monorepo Nx complet : l'application CMS, tous les packages partagés, le code du CLI et la documentation. C'est le chemin des contributeurs, des auteurs de plugins et des équipes qui personnalisent la plateforme elle-même.</p>
|
|
8513
|
+
<pre><code>git clone https://github.com/nextblock-cms/nextblock.git
|
|
8514
|
+
cd nextblock
|
|
8515
|
+
npm install
|
|
8516
|
+
npx nx serve nextblock</code></pre>
|
|
8517
|
+
<p>Ouvrez <code>http://localhost:4200</code> — une nouvelle installation redirige chaque page vers <code>/setup</code>, où le même assistant en trois étapes connecte Supabase, configure le stockage et crée votre admin. Il valide vos clés, écrit <code>.env.local</code> avec des secrets générés, et applique toutes les migrations via l'API de management Supabase — sans CLI Supabase.</p>
|
|
8518
|
+
<div class='rounded-3xl border border-emerald-200 bg-emerald-50/80 p-6 my-8 dark:border-emerald-500/20 dark:bg-emerald-500/10'>
|
|
8519
|
+
<p class='mt-0 text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200'>Zéro configuration dans le terminal</p>
|
|
8520
|
+
<p class='mt-3 mb-0 text-sm text-slate-700 dark:text-slate-200'>La configuration se fait entièrement dans le navigateur — il n'y a plus d'étape interactive en ligne de commande. Quand l'assistant termine, vous êtes connecté en administrateur ; redémarrez ensuite le serveur de développement une fois pour que le nouvel environnement soit intégré au bundle de l'application.</p>
|
|
8521
|
+
</div>
|
|
8522
|
+
|
|
8523
|
+
<h2 id='docker'>Option 4 : Auto-hébergé avec Docker</h2>
|
|
8524
|
+
<p>Tout tourne sur votre machine : les moteurs Postgres et auth de Supabase, une API PostgREST derrière une passerelle Kong, un stockage MinIO compatible S3 et le CMS lui-même. Pas de compte Supabase, pas de Vercel, pas de service d'email — idéal pour les évaluations, les environnements isolés et la pleine propriété de vos données.</p>
|
|
8525
|
+
<p>Avec <a href='https://www.docker.com/products/docker-desktop/' target='_blank' rel='noopener'>Docker Desktop</a> installé et démarré :</p>
|
|
8526
|
+
<pre><code>git clone https://github.com/nextblock-cms/nextblock.git
|
|
8527
|
+
cd nextblock
|
|
8528
|
+
npm install
|
|
8529
|
+
npm run docker:setup</code></pre>
|
|
8530
|
+
<p>La commande ne pose aucune question : elle génère des clés sécurisées, construit la pile, applique toutes les migrations et démarre les services. Quand elle se termine, ouvrez <code>http://localhost:3000</code> — la base de données et le stockage MinIO sont déjà connectés dans l'assistant de configuration, il ne reste qu'à créer votre administrateur (confirmé instantanément, sans email).</p>
|
|
8531
|
+
<div class='rounded-3xl border border-amber-200 bg-amber-50/80 p-6 my-8 dark:border-amber-500/20 dark:bg-amber-500/10'>
|
|
8532
|
+
<p class='mt-0 text-xs font-semibold uppercase tracking-[0.22em] text-amber-700 dark:text-amber-200'>Commandes du quotidien</p>
|
|
8533
|
+
<pre class='mt-4 mb-0'><code># reconstruire et redémarrer la pile
|
|
8534
|
+
npm run docker:up
|
|
8535
|
+
|
|
8536
|
+
# arrêter la pile (vos données persistent dans les volumes Docker)
|
|
8537
|
+
npm run docker:down
|
|
8538
|
+
|
|
8539
|
+
# suivre les logs de l'application
|
|
8540
|
+
npm run docker:logs</code></pre>
|
|
8541
|
+
</div>
|
|
8542
|
+
|
|
8543
|
+
<h2 id='after-install'>Après l'installation : vos 10 premières minutes</h2>
|
|
8544
|
+
<p>Chaque chemin vous dépose sur <code>/cms/dashboard</code>, connecté en tant que premier administrateur. Une checklist de démarrage intégrée vous guide pour la suite :</p>
|
|
8545
|
+
<ul class='space-y-2'>
|
|
8546
|
+
<li><strong>Ajoutez votre identité visuelle</strong> — téléversez votre logo et définissez le titre du site.</li>
|
|
8547
|
+
<li><strong>Réglez votre pied de page</strong> — mention de copyright et navigation du pied de page.</li>
|
|
8548
|
+
<li><strong>Configurez l'email (SMTP)</strong> — dans les réglages, pour que les réinitialisations de mot de passe et les invitations partent bien.</li>
|
|
8549
|
+
<li><strong>Extras optionnels</strong> — connectez vos outils d'analytics, activez la protection anti-bots et (sur Vercel) les mises à jour automatiques.</li>
|
|
8550
|
+
</ul>
|
|
8551
|
+
<p>Ensuite, découvrez comment la plateforme s'articule dans <a href='/article/comment-nextblock-fonctionne'>Comment NextBlock fonctionne</a>, ou ajoutez une boutique avec le <a href='/article/guide-commerce-nextblock'>guide Commerce</a>.</p>
|
|
8552
|
+
|
|
8553
|
+
<h2 id='faq'>FAQ d'installation</h2>
|
|
8554
|
+
<h3>Que dois-je installer ?</h3>
|
|
8555
|
+
<p>Rien pour le chemin Vercel — tout se passe dans le navigateur. Pour <code>npm create nextblock</code> : <a href='https://nodejs.org' target='_blank' rel='noopener'>Node.js 20+</a> (npm inclus). Pour le dépôt cloné : Node.js 20+ et git. Pour Docker : ajoutez Docker Desktop.</p>
|
|
8556
|
+
<h3>NextBlock est-il gratuit ?</h3>
|
|
8557
|
+
<p>Oui — le cœur du CMS est 100 % gratuit et open source (AGPL). Les packages premium comme l'e-commerce et Cortex AI sont optionnels et s'activent avec une clé de licence. Vercel et Supabase proposent chacun une offre gratuite : un site de départ peut donc tourner sans frais.</p>
|
|
8558
|
+
<h3>Ai-je besoin d'un compte Supabase ?</h3>
|
|
8559
|
+
<p>Sur Vercel, la base de données est créée pour vous pendant le déploiement. Pour <code>npm create nextblock</code> et le dépôt cloné, il vous faut un projet Supabase gratuit. Avec Docker, aucun compte cloud n'est nécessaire.</p>
|
|
8560
|
+
<h3>Dois-je exécuter des migrations ou du SQL à la main ?</h3>
|
|
8561
|
+
<p>Non. L'assistant de configuration, le build Vercel et la pile Docker appliquent tous le schéma de base de données automatiquement — et relancer l'opération est toujours sans risque.</p>
|
|
8562
|
+
<h3>Puis-je changer de chemin plus tard ?</h3>
|
|
8563
|
+
<p>Oui. Chaque chemin exécute la même application et le même schéma de base de données : vous pouvez prototyper en local avec Docker aujourd'hui et déployer sur Vercel demain. NextBlock se déploie comme n'importe quelle app Next.js.</p>
|
|
8564
|
+
<h3>Comment mettre à jour NextBlock ?</h3>
|
|
8565
|
+
<p>Sur Vercel, l'étape Connect GitHub de la checklist active une synchronisation quotidienne automatique. Sur un dépôt cloné, <code>git pull</code>, lancez <code>npm run db:migrate</code>, puis redémarrez (lors des builds de production, les migrations en attente s'appliquent automatiquement). Avec Docker, récupérez le dernier code et lancez <code>npm run docker:up</code>.</p>
|
|
8566
|
+
|
|
8567
|
+
<div class='rounded-[2rem] border border-slate-200/80 bg-slate-50 p-8 my-12 text-center dark:border-white/10 dark:bg-white/5'>
|
|
8568
|
+
<p class='mt-0 text-2xl font-semibold text-slate-900 dark:text-white'>Prêt à vous lancer ?</p>
|
|
8569
|
+
<p class='text-sm text-slate-600 dark:text-slate-300'>Choisissez votre chemin ci-dessus, ou passez directement au plus rapide.</p>
|
|
8570
|
+
<div class='mt-5 flex flex-wrap justify-center gap-3'>
|
|
8571
|
+
<a href='https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fnextblock-cms%2Fnextblock&project-name=nextblock&repository-name=nextblock&stores=%5B%7B%22type%22%3A%22integration%22%2C%22integrationSlug%22%3A%22supabase%22%2C%22productSlug%22%3A%22supabase%22%7D%5D' target='_blank' rel='noopener' class='inline-flex items-center rounded-full bg-slate-900 px-6 py-3 text-sm font-semibold text-white no-underline shadow-lg hover:bg-slate-700 dark:bg-white dark:text-slate-900 dark:hover:bg-slate-200'>Déployer sur Vercel</a>
|
|
8572
|
+
<a href='https://github.com/nextblock-cms/nextblock' target='_blank' rel='noopener' class='inline-flex items-center rounded-full border border-slate-300 px-6 py-3 text-sm font-semibold text-slate-700 no-underline hover:border-slate-500 dark:border-white/20 dark:text-slate-200 dark:hover:border-white/50'>Voir sur GitHub</a>
|
|
8573
|
+
</div>
|
|
8574
|
+
</div>$$
|
|
8575
|
+
), 0 FROM target_posts tp WHERE tp.slug = 'comment-configurer-nextblock';
|
|
8576
|
+
|
|
8577
|
+
|
|
8578
|
+
-- >>> FROM: 00000000000038_seed_consent_banner_translations.sql <<<
|
|
8579
|
+
-- 00000000000038_seed_consent_banner_translations.sql
|
|
8580
|
+
-- Consent banner UI copy (EN + FR). Forward-only and idempotent.
|
|
8581
|
+
|
|
8582
|
+
INSERT INTO public.translations (key, translations)
|
|
8583
|
+
VALUES
|
|
8584
|
+
(
|
|
8585
|
+
'privacy.consent.aria_label',
|
|
8586
|
+
jsonb_build_object(
|
|
8587
|
+
'en', 'Privacy consent',
|
|
8588
|
+
'fr', 'Consentement à la confidentialité'
|
|
8589
|
+
)
|
|
8590
|
+
),
|
|
8591
|
+
(
|
|
8592
|
+
'privacy.consent.title',
|
|
8593
|
+
jsonb_build_object(
|
|
8594
|
+
'en', 'We value your privacy',
|
|
8595
|
+
'fr', 'Nous respectons votre vie privée'
|
|
8596
|
+
)
|
|
8597
|
+
),
|
|
8598
|
+
(
|
|
8599
|
+
'privacy.consent.description_before_policy_link',
|
|
8600
|
+
jsonb_build_object(
|
|
8601
|
+
'en', 'We use only essential cookies by default. With your consent we also use analytics to improve the site. See our',
|
|
8602
|
+
'fr', 'Nous utilisons seulement les témoins essentiels par défaut. Avec votre consentement, nous utilisons aussi l''analytique pour améliorer le site. Consultez notre'
|
|
8603
|
+
)
|
|
8604
|
+
),
|
|
8605
|
+
(
|
|
8606
|
+
'privacy.consent.privacy_policy_link',
|
|
8607
|
+
jsonb_build_object(
|
|
8608
|
+
'en', 'Privacy Policy',
|
|
8609
|
+
'fr', 'politique de confidentialité'
|
|
8610
|
+
)
|
|
8611
|
+
),
|
|
8612
|
+
(
|
|
8613
|
+
'privacy.consent.description_after_policy_link',
|
|
8614
|
+
jsonb_build_object(
|
|
8615
|
+
'en', '.',
|
|
8616
|
+
'fr', '.'
|
|
8617
|
+
)
|
|
8618
|
+
),
|
|
8619
|
+
(
|
|
8620
|
+
'privacy.consent.privacy_policy_href',
|
|
8621
|
+
jsonb_build_object(
|
|
8622
|
+
'en', '/privacy-policy',
|
|
8623
|
+
'fr', '/politique-de-confidentialite'
|
|
8624
|
+
)
|
|
8625
|
+
),
|
|
8626
|
+
(
|
|
8627
|
+
'privacy.consent.necessary_label',
|
|
8628
|
+
jsonb_build_object(
|
|
8629
|
+
'en', 'Necessary',
|
|
8630
|
+
'fr', 'Nécessaires'
|
|
8631
|
+
)
|
|
8632
|
+
),
|
|
8633
|
+
(
|
|
8634
|
+
'privacy.consent.necessary_help',
|
|
8635
|
+
jsonb_build_object(
|
|
8636
|
+
'en', 'Always on',
|
|
8637
|
+
'fr', 'Toujours actifs'
|
|
8638
|
+
)
|
|
8639
|
+
),
|
|
8640
|
+
(
|
|
8641
|
+
'privacy.consent.analytics_label',
|
|
8642
|
+
jsonb_build_object(
|
|
8643
|
+
'en', 'Analytics',
|
|
8644
|
+
'fr', 'Analytique'
|
|
8645
|
+
)
|
|
8646
|
+
),
|
|
8647
|
+
(
|
|
8648
|
+
'privacy.consent.analytics_help',
|
|
8649
|
+
jsonb_build_object(
|
|
8650
|
+
'en', 'Usage insights',
|
|
8651
|
+
'fr', 'Statistiques d''utilisation'
|
|
8652
|
+
)
|
|
8653
|
+
),
|
|
8654
|
+
(
|
|
8655
|
+
'privacy.consent.marketing_label',
|
|
8656
|
+
jsonb_build_object(
|
|
8657
|
+
'en', 'Marketing',
|
|
8658
|
+
'fr', 'Marketing'
|
|
8659
|
+
)
|
|
8660
|
+
),
|
|
8661
|
+
(
|
|
8662
|
+
'privacy.consent.marketing_help',
|
|
8663
|
+
jsonb_build_object(
|
|
8664
|
+
'en', 'Personalized content',
|
|
8665
|
+
'fr', 'Contenu personnalisé'
|
|
8666
|
+
)
|
|
8667
|
+
),
|
|
8668
|
+
(
|
|
8669
|
+
'privacy.consent.save_choices',
|
|
8670
|
+
jsonb_build_object(
|
|
8671
|
+
'en', 'Save choices',
|
|
8672
|
+
'fr', 'Enregistrer mes choix'
|
|
8673
|
+
)
|
|
8674
|
+
),
|
|
8675
|
+
(
|
|
8676
|
+
'privacy.consent.accept_all',
|
|
8677
|
+
jsonb_build_object(
|
|
8678
|
+
'en', 'Accept all',
|
|
8679
|
+
'fr', 'Tout accepter'
|
|
8680
|
+
)
|
|
8681
|
+
),
|
|
8682
|
+
(
|
|
8683
|
+
'privacy.consent.reject_all',
|
|
8684
|
+
jsonb_build_object(
|
|
8685
|
+
'en', 'Reject all',
|
|
8686
|
+
'fr', 'Tout refuser'
|
|
8687
|
+
)
|
|
8688
|
+
),
|
|
8689
|
+
(
|
|
8690
|
+
'privacy.consent.hide_options',
|
|
8691
|
+
jsonb_build_object(
|
|
8692
|
+
'en', 'Hide options',
|
|
8693
|
+
'fr', 'Masquer les options'
|
|
8694
|
+
)
|
|
8695
|
+
),
|
|
8696
|
+
(
|
|
8697
|
+
'privacy.consent.manage_options',
|
|
8698
|
+
jsonb_build_object(
|
|
8699
|
+
'en', 'Manage options',
|
|
8700
|
+
'fr', 'Gérer les options'
|
|
8701
|
+
)
|
|
8702
|
+
)
|
|
8703
|
+
ON CONFLICT (key) DO UPDATE
|
|
8704
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
8705
|
+
|
|
8706
|
+
|
|
8707
|
+
-- >>> FROM: 00000000000039_setup_interactions.sql <<<
|
|
8708
|
+
-- 00000000000039_setup_interactions.sql
|
|
8709
|
+
-- Migration establishing Product Reviews and Post Comments schema.
|
|
8710
|
+
|
|
8711
|
+
-- 1. Create Enums
|
|
8712
|
+
CREATE TYPE public.interaction_type AS ENUM ('review', 'comment');
|
|
8713
|
+
CREATE TYPE public.approval_status AS ENUM ('pending', 'approved', 'denied');
|
|
8714
|
+
|
|
8715
|
+
-- 2. Alter Products Table to support aggregations
|
|
8716
|
+
ALTER TABLE public.products
|
|
8717
|
+
ADD COLUMN average_rating numeric(3,2) NOT NULL DEFAULT 0.00,
|
|
8718
|
+
ADD COLUMN total_reviews integer NOT NULL DEFAULT 0;
|
|
8719
|
+
|
|
8720
|
+
COMMENT ON COLUMN public.products.average_rating IS 'Aggregated average 1-5 rating of approved reviews.';
|
|
8721
|
+
COMMENT ON COLUMN public.products.total_reviews IS 'Total count of approved reviews for this product.';
|
|
8722
|
+
|
|
8723
|
+
-- 3. Create Interactions Table
|
|
8724
|
+
CREATE TABLE public.cms_interactions (
|
|
8725
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
8726
|
+
type public.interaction_type NOT NULL,
|
|
8727
|
+
status public.approval_status NOT NULL DEFAULT 'pending',
|
|
8728
|
+
content text NOT NULL,
|
|
8729
|
+
rating integer,
|
|
8730
|
+
user_id uuid NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
8731
|
+
product_id uuid REFERENCES public.products(id) ON DELETE CASCADE,
|
|
8732
|
+
post_id bigint REFERENCES public.posts(id) ON DELETE CASCADE,
|
|
8733
|
+
reactions jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
8734
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
8735
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
8736
|
+
|
|
8737
|
+
-- Ensure polymorphism is respected (either product or post)
|
|
8738
|
+
CONSTRAINT check_product_or_post CHECK (
|
|
8739
|
+
(product_id IS NOT NULL AND post_id IS NULL)
|
|
8740
|
+
OR (post_id IS NOT NULL AND product_id IS NULL)
|
|
8741
|
+
),
|
|
8742
|
+
|
|
8743
|
+
-- Ensure rating matches business rules
|
|
8744
|
+
CONSTRAINT check_rating_only_for_review CHECK (
|
|
8745
|
+
(type = 'review' AND rating IS NOT NULL AND rating >= 1 AND rating <= 5)
|
|
8746
|
+
OR (type = 'comment' AND rating IS NULL)
|
|
8747
|
+
)
|
|
8748
|
+
);
|
|
8749
|
+
|
|
8750
|
+
COMMENT ON TABLE public.cms_interactions IS 'Stores user-submitted product reviews and blog post comments.';
|
|
8751
|
+
COMMENT ON COLUMN public.cms_interactions.rating IS 'Star rating 1-5, only populated for product reviews.';
|
|
8752
|
+
COMMENT ON COLUMN public.cms_interactions.reactions IS 'JSONB structure tracking counts of reactions (likes, etc.).';
|
|
8753
|
+
|
|
8754
|
+
-- 4. Create rating aggregation trigger function
|
|
8755
|
+
CREATE OR REPLACE FUNCTION public.update_product_ratings()
|
|
8756
|
+
RETURNS TRIGGER AS $$
|
|
8757
|
+
DECLARE
|
|
8758
|
+
v_product_id uuid;
|
|
8759
|
+
v_avg numeric(3,2);
|
|
8760
|
+
v_count integer;
|
|
8761
|
+
BEGIN
|
|
8762
|
+
-- Determine which product_id we need to update
|
|
8763
|
+
IF TG_OP = 'DELETE' THEN
|
|
8764
|
+
v_product_id := OLD.product_id;
|
|
8765
|
+
ELSE
|
|
8766
|
+
v_product_id := NEW.product_id;
|
|
8767
|
+
END IF;
|
|
8768
|
+
|
|
8769
|
+
IF v_product_id IS NOT NULL THEN
|
|
8770
|
+
-- Calculate average and count of approved reviews for this product
|
|
8771
|
+
SELECT COALESCE(avg(rating), 0.00), count(*)
|
|
8772
|
+
INTO v_avg, v_count
|
|
8773
|
+
FROM public.cms_interactions
|
|
8774
|
+
WHERE product_id = v_product_id
|
|
8775
|
+
AND type = 'review'
|
|
8776
|
+
AND status = 'approved';
|
|
8777
|
+
|
|
8778
|
+
-- Update products table
|
|
8779
|
+
UPDATE public.products
|
|
8780
|
+
SET average_rating = ROUND(COALESCE(v_avg, 0.00), 2),
|
|
8781
|
+
total_reviews = v_count
|
|
8782
|
+
WHERE id = v_product_id;
|
|
8783
|
+
END IF;
|
|
8784
|
+
|
|
8785
|
+
-- Handle old product_id if it changed on UPDATE (e.g. transfer of reviews)
|
|
8786
|
+
IF TG_OP = 'UPDATE' AND OLD.product_id IS NOT NULL AND OLD.product_id <> NEW.product_id THEN
|
|
8787
|
+
SELECT COALESCE(avg(rating), 0.00), count(*)
|
|
8788
|
+
INTO v_avg, v_count
|
|
8789
|
+
FROM public.cms_interactions
|
|
8790
|
+
WHERE product_id = OLD.product_id
|
|
8791
|
+
AND type = 'review'
|
|
8792
|
+
AND status = 'approved';
|
|
8793
|
+
|
|
8794
|
+
UPDATE public.products
|
|
8795
|
+
SET average_rating = ROUND(COALESCE(v_avg, 0.00), 2),
|
|
8796
|
+
total_reviews = v_count
|
|
8797
|
+
WHERE id = OLD.product_id;
|
|
8798
|
+
END IF;
|
|
8799
|
+
|
|
8800
|
+
RETURN NULL;
|
|
8801
|
+
END;
|
|
8802
|
+
$$ LANGUAGE plpgsql SECURITY DEFINER SET search_path = public;
|
|
8803
|
+
|
|
8804
|
+
-- 5. Attach trigger to interactions table
|
|
8805
|
+
CREATE TRIGGER trigger_update_product_ratings
|
|
8806
|
+
AFTER INSERT OR UPDATE OR DELETE
|
|
8807
|
+
ON public.cms_interactions
|
|
8808
|
+
FOR EACH ROW
|
|
8809
|
+
EXECUTE FUNCTION public.update_product_ratings();
|
|
8810
|
+
|
|
8811
|
+
-- 6. Attach update_at timestamp trigger
|
|
8812
|
+
CREATE TRIGGER set_updated_at
|
|
8813
|
+
BEFORE UPDATE ON public.cms_interactions
|
|
8814
|
+
FOR EACH ROW
|
|
8815
|
+
EXECUTE FUNCTION public.set_current_timestamp_updated_at();
|
|
8816
|
+
|
|
8817
|
+
-- 7. Enable RLS and define policies
|
|
8818
|
+
ALTER TABLE public.cms_interactions ENABLE ROW LEVEL SECURITY;
|
|
8819
|
+
|
|
8820
|
+
CREATE POLICY cms_interactions_read_policy
|
|
8821
|
+
ON public.cms_interactions
|
|
8822
|
+
FOR SELECT
|
|
8823
|
+
TO public
|
|
8824
|
+
USING (
|
|
8825
|
+
status = 'approved'
|
|
8826
|
+
OR ((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'))
|
|
8827
|
+
);
|
|
8828
|
+
|
|
8829
|
+
CREATE POLICY cms_interactions_insert_policy
|
|
8830
|
+
ON public.cms_interactions
|
|
8831
|
+
FOR INSERT
|
|
8832
|
+
TO authenticated
|
|
8833
|
+
WITH CHECK (
|
|
8834
|
+
auth.uid() = user_id
|
|
8835
|
+
AND (status = 'pending' OR (SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'))
|
|
8836
|
+
);
|
|
8837
|
+
|
|
8838
|
+
CREATE POLICY cms_interactions_update_policy
|
|
8839
|
+
ON public.cms_interactions
|
|
8840
|
+
FOR UPDATE
|
|
8841
|
+
TO authenticated
|
|
8842
|
+
USING (
|
|
8843
|
+
((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'))
|
|
8844
|
+
)
|
|
8845
|
+
WITH CHECK (
|
|
8846
|
+
((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'))
|
|
8847
|
+
);
|
|
8848
|
+
|
|
8849
|
+
CREATE POLICY cms_interactions_delete_policy
|
|
8850
|
+
ON public.cms_interactions
|
|
8851
|
+
FOR DELETE
|
|
8852
|
+
TO authenticated
|
|
8853
|
+
USING (
|
|
8854
|
+
((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'))
|
|
8855
|
+
);
|
|
8856
|
+
|
|
8857
|
+
-- 8. Grant Table Permissions
|
|
8858
|
+
GRANT SELECT ON public.cms_interactions TO anon;
|
|
8859
|
+
GRANT ALL ON public.cms_interactions TO authenticated;
|
|
8860
|
+
GRANT ALL ON public.cms_interactions TO service_role;
|
|
8861
|
+
|
|
8862
|
+
|
|
8863
|
+
-- >>> FROM: 00000000000040_add_profiles_fk_to_interactions.sql <<<
|
|
8864
|
+
-- 00000000000040_add_profiles_fk_to_interactions.sql
|
|
8865
|
+
-- Alter cms_interactions.user_id to reference public.profiles directly for PostgREST joins.
|
|
8866
|
+
|
|
8867
|
+
ALTER TABLE public.cms_interactions
|
|
8868
|
+
DROP CONSTRAINT IF EXISTS cms_interactions_user_id_fkey,
|
|
8869
|
+
ADD CONSTRAINT cms_interactions_user_id_profiles_fkey FOREIGN KEY (user_id) REFERENCES public.profiles(id) ON DELETE CASCADE;
|
|
8870
|
+
|
|
8871
|
+
COMMENT ON COLUMN public.cms_interactions.user_id IS 'References public.profiles.id';
|
|
8872
|
+
|
|
8873
|
+
|
|
8874
|
+
-- >>> FROM: 00000000000041_seed_interactions_translations.sql <<<
|
|
8875
|
+
-- 00000000000041_seed_interactions_translations.sql
|
|
8876
|
+
-- Adds translation strings for Product Reviews and Post Comments storefront modules.
|
|
8877
|
+
|
|
8878
|
+
|
|
8879
|
+
INSERT INTO public.translations (key, translations)
|
|
8880
|
+
VALUES
|
|
8881
|
+
(
|
|
8882
|
+
'reviews.customer_reviews',
|
|
8883
|
+
'{"en": "Customer Reviews", "fr": "Avis clients"}'::jsonb
|
|
8884
|
+
),
|
|
8885
|
+
(
|
|
8886
|
+
'reviews.share_thoughts',
|
|
8887
|
+
'{"en": "Share your thoughts and experience with this product.", "fr": "Partagez vos impressions et votre expérience avec ce produit."}'::jsonb
|
|
8888
|
+
),
|
|
8889
|
+
(
|
|
8890
|
+
'reviews.write_review',
|
|
8891
|
+
'{"en": "Write a Review", "fr": "Rédiger un avis"}'::jsonb
|
|
8892
|
+
),
|
|
8893
|
+
(
|
|
8894
|
+
'reviews.cancel_review',
|
|
8895
|
+
'{"en": "Cancel Review", "fr": "Annuler l''avis"}'::jsonb
|
|
8896
|
+
),
|
|
8897
|
+
(
|
|
8898
|
+
'reviews.login_to_write',
|
|
8899
|
+
'{"en": "Please log in to write a review.", "fr": "Veuillez vous connecter pour rédiger un avis."}'::jsonb
|
|
8900
|
+
),
|
|
8901
|
+
(
|
|
8902
|
+
'reviews.write_your_review',
|
|
8903
|
+
'{"en": "Write your review", "fr": "Rédigez votre avis"}'::jsonb
|
|
8904
|
+
),
|
|
8905
|
+
(
|
|
8906
|
+
'reviews.rating',
|
|
8907
|
+
'{"en": "Rating", "fr": "Note"}'::jsonb
|
|
8908
|
+
),
|
|
8909
|
+
(
|
|
8910
|
+
'reviews.description',
|
|
8911
|
+
'{"en": "Review Description", "fr": "Description de l''avis"}'::jsonb
|
|
8912
|
+
),
|
|
8913
|
+
(
|
|
8914
|
+
'reviews.description_placeholder',
|
|
8915
|
+
'{"en": "What did you like or dislike? How does it perform?", "fr": "Qu''avez-vous aimé ou déploré ? Comment se comporte-t-il ?"}'::jsonb
|
|
8916
|
+
),
|
|
8917
|
+
(
|
|
8918
|
+
'reviews.submit_review',
|
|
8919
|
+
'{"en": "Submit Review", "fr": "Soumettre l''avis"}'::jsonb
|
|
8920
|
+
),
|
|
8921
|
+
(
|
|
8922
|
+
'reviews.submitting',
|
|
8923
|
+
'{"en": "Submitting...", "fr": "Envoi en cours..."}'::jsonb
|
|
8924
|
+
),
|
|
8925
|
+
(
|
|
8926
|
+
'reviews.success_pending',
|
|
8927
|
+
'{"en": "Your review has been submitted successfully and is pending moderation.", "fr": "Votre avis a été soumis avec succès et est en attente de modération."}'::jsonb
|
|
8928
|
+
),
|
|
8929
|
+
(
|
|
8930
|
+
'reviews.cancel',
|
|
8931
|
+
'{"en": "Cancel", "fr": "Annuler"}'::jsonb
|
|
8932
|
+
),
|
|
8933
|
+
(
|
|
8934
|
+
'reviews.helpful',
|
|
8935
|
+
'{"en": "Helpful", "fr": "Utile"}'::jsonb
|
|
8936
|
+
),
|
|
8937
|
+
(
|
|
8938
|
+
'reviews.no_reviews',
|
|
8939
|
+
'{"en": "No reviews yet", "fr": "Aucun avis pour le moment"}'::jsonb
|
|
8940
|
+
),
|
|
8941
|
+
(
|
|
8942
|
+
'reviews.be_the_first',
|
|
8943
|
+
'{"en": "There are no reviews for this product yet. Be the first to write one!", "fr": "Il n''y a pas encore d''avis sur ce produit. Soyez le premier à en rédiger un !"}'::jsonb
|
|
8944
|
+
),
|
|
8945
|
+
(
|
|
8946
|
+
'reviews.load_more',
|
|
8947
|
+
'{"en": "Load More Reviews", "fr": "Charger plus d''avis"}'::jsonb
|
|
8948
|
+
),
|
|
8949
|
+
(
|
|
8950
|
+
'reviews.review_count_one',
|
|
8951
|
+
'{"en": "{count} review", "fr": "{count} avis"}'::jsonb
|
|
8952
|
+
),
|
|
8953
|
+
(
|
|
8954
|
+
'reviews.review_count_other',
|
|
8955
|
+
'{"en": "{count} reviews", "fr": "{count} avis"}'::jsonb
|
|
8956
|
+
),
|
|
8957
|
+
(
|
|
8958
|
+
'comments.discussion',
|
|
8959
|
+
'{"en": "Discussion & Comments", "fr": "Discussion & Commentaires"}'::jsonb
|
|
8960
|
+
),
|
|
8961
|
+
(
|
|
8962
|
+
'comments.join_conversation',
|
|
8963
|
+
'{"en": "Join the conversation and express your thoughts.", "fr": "Rejoignez la conversation et exprimez vos pensées."}'::jsonb
|
|
8964
|
+
),
|
|
8965
|
+
(
|
|
8966
|
+
'comments.write_comment',
|
|
8967
|
+
'{"en": "Write a Comment", "fr": "Écrire un commentaire"}'::jsonb
|
|
8968
|
+
),
|
|
8969
|
+
(
|
|
8970
|
+
'comments.cancel_comment',
|
|
8971
|
+
'{"en": "Cancel Comment", "fr": "Annuler le commentaire"}'::jsonb
|
|
8972
|
+
),
|
|
8973
|
+
(
|
|
8974
|
+
'comments.login_to_write',
|
|
8975
|
+
'{"en": "Please log in to write a comment.", "fr": "Veuillez vous connecter pour écrire un commentaire."}'::jsonb
|
|
8976
|
+
),
|
|
8977
|
+
(
|
|
8978
|
+
'comments.join_discussion',
|
|
8979
|
+
'{"en": "Join the Discussion", "fr": "Rejoindre la discussion"}'::jsonb
|
|
8980
|
+
),
|
|
8981
|
+
(
|
|
8982
|
+
'comments.your_message',
|
|
8983
|
+
'{"en": "Your Message", "fr": "Votre message"}'::jsonb
|
|
8984
|
+
),
|
|
8985
|
+
(
|
|
8986
|
+
'comments.message_placeholder',
|
|
8987
|
+
'{"en": "What are your thoughts on this article?", "fr": "Quelles sont vos pensées sur cet article ?"}'::jsonb
|
|
8988
|
+
),
|
|
8989
|
+
(
|
|
8990
|
+
'comments.post_comment',
|
|
8991
|
+
'{"en": "Post Comment", "fr": "Publier le commentaire"}'::jsonb
|
|
8992
|
+
),
|
|
8993
|
+
(
|
|
8994
|
+
'comments.success_pending',
|
|
8995
|
+
'{"en": "Your comment has been submitted successfully and is pending moderation.", "fr": "Votre commentaire a été soumis avec succès et est en attente de modération."}'::jsonb
|
|
8996
|
+
),
|
|
8997
|
+
(
|
|
8998
|
+
'comments.like',
|
|
8999
|
+
'{"en": "Like", "fr": "J''aime"}'::jsonb
|
|
9000
|
+
),
|
|
9001
|
+
(
|
|
9002
|
+
'comments.no_comments',
|
|
9003
|
+
'{"en": "No comments yet", "fr": "Aucun commentaire pour le moment"}'::jsonb
|
|
9004
|
+
),
|
|
9005
|
+
(
|
|
9006
|
+
'comments.be_the_first',
|
|
9007
|
+
'{"en": "Be the first to share your thoughts!", "fr": "Soyez le premier à partager vos pensées !"}'::jsonb
|
|
9008
|
+
),
|
|
9009
|
+
(
|
|
9010
|
+
'comments.load_more',
|
|
9011
|
+
'{"en": "Load More Comments", "fr": "Charger plus de commentaires"}'::jsonb
|
|
9012
|
+
)
|
|
9013
|
+
ON CONFLICT (key) DO UPDATE
|
|
9014
|
+
SET
|
|
9015
|
+
translations = EXCLUDED.translations,
|
|
9016
|
+
updated_at = now();
|
|
9017
|
+
|
|
9018
|
+
|
|
9019
|
+
|
|
9020
|
+
-- >>> FROM: 00000000000042_seed_deploy_to_vercel_ctas.sql <<<
|
|
9021
|
+
-- Promote the one-click "Deploy to Vercel" button as a CTA in the seeded homepage.
|
|
9022
|
+
--
|
|
9023
|
+
-- Two placements per language, both rendered through the normal 'button' block
|
|
9024
|
+
-- (ButtonBlockRenderer), so external URLs open in a new tab with rel=noopener:
|
|
9025
|
+
-- 1. Home HERO — replace the secondary "View on GitHub" / "Voir sur GitHub"
|
|
9026
|
+
-- outline button with a "Deploy on Vercel" / "Déployer sur Vercel" button
|
|
9027
|
+
-- (same variant/size/position; the primary "Get Started" button is untouched,
|
|
9028
|
+
-- and GitHub is still linked from the hero social row + the community section).
|
|
9029
|
+
-- 2. Home CLOSING CTA band ("Have Questions?" / "Des questions ?") — append a
|
|
9030
|
+
-- secondary (outline) "Deploy on Vercel" button after the contact button so
|
|
9031
|
+
-- the page also ends on the deploy action, styled to match the hero's Deploy
|
|
9032
|
+
-- button and keep the filled "Get in Touch" button as the band's primary.
|
|
9033
|
+
--
|
|
9034
|
+
-- The canonical deploy URL is the exact href from the README's Deploy button
|
|
9035
|
+
-- (native Supabase Marketplace \`stores\` flow). It is stored as a raw button \`url\`
|
|
9036
|
+
-- value (literal '&', not '&') because the renderer uses it directly as an href.
|
|
9037
|
+
--
|
|
9038
|
+
-- Forward-only and idempotent:
|
|
9039
|
+
-- * The hero swap matches the old button label, so a second run is a no-op
|
|
9040
|
+
-- (the label no longer exists) and it silently skips any install where the
|
|
9041
|
+
-- button was already customized or removed.
|
|
9042
|
+
-- * The closing-band append is guarded by NOT LIKE '%Deploy on Vercel%' /
|
|
9043
|
+
-- '%Déployer sur Vercel%', so it never appends twice.
|
|
9044
|
+
-- Scoping is by unique block text, so exactly the home hero / closing band match.
|
|
9045
|
+
|
|
9046
|
+
-- ---------------------------------------------------------------------------
|
|
9047
|
+
-- 1a. EN home hero: "View on GitHub" -> "Deploy on Vercel"
|
|
9048
|
+
-- ---------------------------------------------------------------------------
|
|
9049
|
+
UPDATE public.blocks
|
|
9050
|
+
SET content = replace(
|
|
9051
|
+
replace(content::text, '"View on GitHub"', '"Deploy on Vercel"'),
|
|
9052
|
+
'"https://github.com/nextblock-cms/nextblock"',
|
|
9053
|
+
'"https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fnextblock-cms%2Fnextblock&project-name=nextblock&repository-name=nextblock&stores=%5B%7B%22type%22%3A%22integration%22%2C%22integrationSlug%22%3A%22supabase%22%2C%22productSlug%22%3A%22supabase%22%7D%5D"'
|
|
9054
|
+
)::jsonb
|
|
9055
|
+
WHERE content::text LIKE '%"View on GitHub"%';
|
|
9056
|
+
|
|
9057
|
+
-- ---------------------------------------------------------------------------
|
|
9058
|
+
-- 1b. FR home hero: "Voir sur GitHub" -> "Déployer sur Vercel"
|
|
9059
|
+
-- ---------------------------------------------------------------------------
|
|
9060
|
+
UPDATE public.blocks
|
|
9061
|
+
SET content = replace(
|
|
9062
|
+
replace(content::text, '"Voir sur GitHub"', '"Déployer sur Vercel"'),
|
|
9063
|
+
'"https://github.com/nextblock-cms/nextblock"',
|
|
9064
|
+
'"https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fnextblock-cms%2Fnextblock&project-name=nextblock&repository-name=nextblock&stores=%5B%7B%22type%22%3A%22integration%22%2C%22integrationSlug%22%3A%22supabase%22%2C%22productSlug%22%3A%22supabase%22%7D%5D"'
|
|
9065
|
+
)::jsonb
|
|
9066
|
+
WHERE content::text LIKE '%"Voir sur GitHub"%';
|
|
9067
|
+
|
|
9068
|
+
-- ---------------------------------------------------------------------------
|
|
9069
|
+
-- 2a. EN home closing band ("Have Questions?"): append a Deploy on Vercel button
|
|
9070
|
+
-- ---------------------------------------------------------------------------
|
|
9071
|
+
UPDATE public.blocks
|
|
9072
|
+
SET content = jsonb_set(
|
|
9073
|
+
content,
|
|
9074
|
+
'{column_blocks,0}',
|
|
9075
|
+
(content #> '{column_blocks,0}') ||
|
|
9076
|
+
'[{"block_type":"button","content":{"text":"Deploy on Vercel","url":"https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fnextblock-cms%2Fnextblock&project-name=nextblock&repository-name=nextblock&stores=%5B%7B%22type%22%3A%22integration%22%2C%22integrationSlug%22%3A%22supabase%22%2C%22productSlug%22%3A%22supabase%22%7D%5D","variant":"outline","size":"lg","position":"center"}}]'::jsonb
|
|
9077
|
+
)
|
|
9078
|
+
WHERE content::text LIKE '%Have Questions?%'
|
|
9079
|
+
AND content::text NOT LIKE '%Deploy on Vercel%';
|
|
9080
|
+
|
|
9081
|
+
-- ---------------------------------------------------------------------------
|
|
9082
|
+
-- 2b. FR home closing band ("Des questions ?"): append a Déployer sur Vercel button
|
|
9083
|
+
-- ---------------------------------------------------------------------------
|
|
9084
|
+
UPDATE public.blocks
|
|
9085
|
+
SET content = jsonb_set(
|
|
9086
|
+
content,
|
|
9087
|
+
'{column_blocks,0}',
|
|
9088
|
+
(content #> '{column_blocks,0}') ||
|
|
9089
|
+
'[{"block_type":"button","content":{"text":"Déployer sur Vercel","url":"https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fnextblock-cms%2Fnextblock&project-name=nextblock&repository-name=nextblock&stores=%5B%7B%22type%22%3A%22integration%22%2C%22integrationSlug%22%3A%22supabase%22%2C%22productSlug%22%3A%22supabase%22%7D%5D","variant":"outline","size":"lg","position":"center"}}]'::jsonb
|
|
9090
|
+
)
|
|
9091
|
+
WHERE content::text LIKE '%Des questions ?%'
|
|
9092
|
+
AND content::text NOT LIKE '%Déployer sur Vercel%';
|
|
9093
|
+
|
|
9094
|
+
|
|
8258
9095
|
-- Step D: Anchor preserved profiles
|
|
8259
9096
|
INSERT INTO public.profiles (id, updated_at, full_name, avatar_url, website, role)
|
|
8260
9097
|
SELECT preserved_user.id, NULL, NULL, NULL, NULL, 'ADMIN'
|