create-nextblock 0.16.2 → 0.16.4

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.
@@ -1,37 +1,37 @@
1
- // AUTO-GENERATED FILE. Do not edit this file directly.
2
- // Regenerate it from repo root with: npm run generate:sandbox
3
- // Source of truth: tools/scripts/generate-sandbox-reset.ts and libs/db/src/supabase/migrations/*.sql
4
-
5
- export const SANDBOX_RESET_SQL = `
6
- -- AUTO-GENERATED: Sandbox Reset Script. Do Not Edit Manually.
7
- -- Generated by tools/scripts/generate-sandbox-reset.ts
8
-
9
- -- Step A: Erase all non-demo users
10
- DELETE FROM auth.users
11
- WHERE id NOT IN (
12
- '63a8aa07-ef6e-4cc7-bafa-ece023c74366'::uuid,
13
- 'e3a2c121-70a4-4239-a9df-f70ce717f5a1'::uuid
14
- );
15
-
16
- -- Step B: Wipe public schema and truncate migrations
17
- DROP SCHEMA public CASCADE;
18
- CREATE SCHEMA public;
19
-
20
- -- Restore default public schema privileges so the standard migrations succeed
21
- GRANT USAGE ON SCHEMA public TO postgres, anon, authenticated, service_role;
22
- GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO postgres, anon, authenticated, service_role;
23
- GRANT ALL PRIVILEGES ON ALL ROUTINES IN SCHEMA public TO postgres, anon, authenticated, service_role;
24
- GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO postgres, anon, authenticated, service_role;
25
- ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO postgres, anon, authenticated, service_role;
26
- ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON ROUTINES TO postgres, anon, authenticated, service_role;
27
- ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres, anon, authenticated, service_role;
28
-
29
- TRUNCATE TABLE supabase_migrations.schema_migrations;
30
-
31
- -- Step C: Execute full schema & seed from production migrations
32
-
33
-
34
- -- >>> FROM: 00000000000000_baseline_schema.sql <<<
1
+ // AUTO-GENERATED FILE. Do not edit this file directly.
2
+ // Regenerate it from repo root with: npm run generate:sandbox
3
+ // Source of truth: tools/scripts/generate-sandbox-reset.ts and libs/db/src/supabase/migrations/*.sql
4
+
5
+ export const SANDBOX_RESET_SQL = `
6
+ -- AUTO-GENERATED: Sandbox Reset Script. Do Not Edit Manually.
7
+ -- Generated by tools/scripts/generate-sandbox-reset.ts
8
+
9
+ -- Step A: Erase all non-demo users
10
+ DELETE FROM auth.users
11
+ WHERE id NOT IN (
12
+ '63a8aa07-ef6e-4cc7-bafa-ece023c74366'::uuid,
13
+ 'e3a2c121-70a4-4239-a9df-f70ce717f5a1'::uuid
14
+ );
15
+
16
+ -- Step B: Wipe public schema and truncate migrations
17
+ DROP SCHEMA public CASCADE;
18
+ CREATE SCHEMA public;
19
+
20
+ -- Restore default public schema privileges so the standard migrations succeed
21
+ GRANT USAGE ON SCHEMA public TO postgres, anon, authenticated, service_role;
22
+ GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO postgres, anon, authenticated, service_role;
23
+ GRANT ALL PRIVILEGES ON ALL ROUTINES IN SCHEMA public TO postgres, anon, authenticated, service_role;
24
+ GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO postgres, anon, authenticated, service_role;
25
+ ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO postgres, anon, authenticated, service_role;
26
+ ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON ROUTINES TO postgres, anon, authenticated, service_role;
27
+ ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres, anon, authenticated, service_role;
28
+
29
+ TRUNCATE TABLE supabase_migrations.schema_migrations;
30
+
31
+ -- Step C: Execute full schema & seed from production migrations
32
+
33
+
34
+ -- >>> FROM: 00000000000000_baseline_schema.sql <<<
35
35
  -- AUTO-GENERATED baseline (re-baseline of migrations 000..044). Idempotent; safe to replay.
36
36
  -- 00 · schema: enums, functions, tables, sequences, defaults
37
37
  -- Regenerate via tools/scripts/rebaseline-transform.mjs. Do not hand-edit.
@@ -2486,9 +2486,9 @@ CREATE TABLE IF NOT EXISTS public.variant_attribute_mapping (
2486
2486
  variant_id uuid NOT NULL,
2487
2487
  attribute_term_id uuid NOT NULL
2488
2488
  );
2489
-
2490
-
2491
- -- >>> FROM: 00000000000001_baseline_constraints_and_indexes.sql <<<
2489
+
2490
+
2491
+ -- >>> FROM: 00000000000001_baseline_constraints_and_indexes.sql <<<
2492
2492
  -- AUTO-GENERATED baseline (re-baseline of migrations 000..044). Idempotent; safe to replay.
2493
2493
  -- 01 · constraints (PK / unique / check / FK) + indexes
2494
2494
  -- Regenerate via tools/scripts/rebaseline-transform.mjs. Do not hand-edit.
@@ -3560,9 +3560,9 @@ DO $rb$ BEGIN
3560
3560
  ADD CONSTRAINT variant_attribute_mapping_variant_id_fkey FOREIGN KEY (variant_id) REFERENCES public.product_variants(id) ON DELETE CASCADE;
3561
3561
  END IF;
3562
3562
  END $rb$;
3563
-
3564
-
3565
- -- >>> FROM: 00000000000002_baseline_security_and_grants.sql <<<
3563
+
3564
+
3565
+ -- >>> FROM: 00000000000002_baseline_security_and_grants.sql <<<
3566
3566
  -- AUTO-GENERATED baseline (re-baseline of migrations 000..044). Idempotent; safe to replay.
3567
3567
  -- 02 · row-level security, policies, triggers, grants
3568
3568
  -- Regenerate via tools/scripts/rebaseline-transform.mjs. Do not hand-edit.
@@ -4898,9 +4898,9 @@ CREATE TRIGGER on_auth_user_created
4898
4898
  FOR EACH ROW
4899
4899
  EXECUTE FUNCTION public.handle_new_user();
4900
4900
  REVOKE EXECUTE ON FUNCTION public.handle_new_user() FROM PUBLIC, anon, authenticated;
4901
-
4902
-
4903
- -- >>> FROM: 00000000000003_baseline_seed.sql <<<
4901
+
4902
+
4903
+ -- >>> FROM: 00000000000003_baseline_seed.sql <<<
4904
4904
  -- AUTO-GENERATED baseline (re-baseline of migrations 000..044). Idempotent; safe to replay.
4905
4905
  -- 03 · seed: canonical NextBlock demo content (no users, no secrets)
4906
4906
  -- Regenerate via tools/scripts/rebaseline-transform.mjs. Do not hand-edit.
@@ -5369,9 +5369,9 @@ SELECT pg_catalog.setval('public.languages_id_seq', COALESCE((SELECT MAX(id) FRO
5369
5369
  SELECT pg_catalog.setval('public.navigation_items_id_seq', COALESCE((SELECT MAX(id) FROM public.navigation_items), 1), true);
5370
5370
  SELECT pg_catalog.setval('public.pages_id_seq', COALESCE((SELECT MAX(id) FROM public.pages), 1), true);
5371
5371
  SELECT pg_catalog.setval('public.posts_id_seq', COALESCE((SELECT MAX(id) FROM public.posts), 1), true);
5372
-
5373
-
5374
- -- >>> FROM: 00000000000004_default_logo_email_safe.sql <<<
5372
+
5373
+
5374
+ -- >>> FROM: 00000000000004_default_logo_email_safe.sql <<<
5375
5375
  -- Swap the seeded DEFAULT site logo from the WebP asset to a bundled PNG.
5376
5376
  --
5377
5377
  -- WebP (and AVIF) don't render in Outlook and several other email clients, so the default
@@ -5396,9 +5396,9 @@ UPDATE public.logos
5396
5396
  SET media_id = 'a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d'
5397
5397
  WHERE id = 'd45ef03d-27fc-4099-8b46-1cdf82d658d2'
5398
5398
  AND media_id = 'ea6fdaf5-f8de-416c-9f2b-b689b7a4ed38';
5399
-
5400
-
5401
- -- >>> FROM: 00000000000005_add_custom_canonical.sql <<<
5399
+
5400
+
5401
+ -- >>> FROM: 00000000000005_add_custom_canonical.sql <<<
5402
5402
  -- Add a nullable \`custom_canonical\` column to pages, posts and products.
5403
5403
  --
5404
5404
  -- This is the per-content manual canonical override used by each route's
@@ -5412,9 +5412,9 @@ WHERE id = 'd45ef03d-27fc-4099-8b46-1cdf82d658d2'
5412
5412
  ALTER TABLE public.pages ADD COLUMN IF NOT EXISTS custom_canonical text;
5413
5413
  ALTER TABLE public.posts ADD COLUMN IF NOT EXISTS custom_canonical text;
5414
5414
  ALTER TABLE public.products ADD COLUMN IF NOT EXISTS custom_canonical text;
5415
-
5416
-
5417
- -- >>> FROM: 00000000000006_home_live_demo_promo.sql <<<
5415
+
5416
+
5417
+ -- >>> FROM: 00000000000006_home_live_demo_promo.sql <<<
5418
5418
  -- 00000000000006_home_sandbox_promo.sql
5419
5419
  -- Adds a "Live Demo" promo section to the English (slug 'home') and French
5420
5420
  -- (slug 'accueil') home pages that drives visitors to the public sandbox at
@@ -5482,9 +5482,9 @@ $fr$::jsonb, 1);
5482
5482
  END IF;
5483
5483
  END
5484
5484
  $body$;
5485
-
5486
-
5487
- -- >>> FROM: 00000000000007_home_live_demo_promo_copy_fix.sql <<<
5485
+
5486
+
5487
+ -- >>> FROM: 00000000000007_home_live_demo_promo_copy_fix.sql <<<
5488
5488
  -- 00000000000007_home_live_demo_promo_copy_fix.sql
5489
5489
  -- Corrects the "Live Demo" promo that migration 006 seeded on the EN (slug 'home')
5490
5490
  -- and FR (slug 'accueil') home pages. 006 was already applied to production and the
@@ -5534,9 +5534,9 @@ $fr$::jsonb,
5534
5534
  AND content::text LIKE '%nb-sandbox-promo%';
5535
5535
  END
5536
5536
  $body$;
5537
-
5538
-
5539
- -- >>> FROM: 00000000000008_setup_article_reorder.sql <<<
5537
+
5538
+
5539
+ -- >>> FROM: 00000000000008_setup_article_reorder.sql <<<
5540
5540
  -- 00000000000008_setup_article_reorder.sql
5541
5541
  -- Reorders and rewrites the "How to Install NextBlock" setup guide on BOTH language
5542
5542
  -- twins: EN (post slug 'how-to-setup-nextblock', post_id=3 / block id=40) and FR
@@ -5567,9 +5567,9 @@ $nbfr$::jsonb,
5567
5567
  updated_at = now()
5568
5568
  WHERE post_id = 4
5569
5569
  AND block_type = 'text';
5570
-
5571
-
5572
- -- >>> FROM: 00000000000009_home_live_demo_promo_contrast.sql <<<
5570
+
5571
+
5572
+ -- >>> FROM: 00000000000009_home_live_demo_promo_contrast.sql <<<
5573
5573
  -- 00000000000009_home_live_demo_promo_contrast.sql
5574
5574
  -- Restyles the "Live Demo" promo that migrations 006/007 seeded on the EN (slug 'home')
5575
5575
  -- and FR (slug 'accueil') home pages. 006/007 gave it a fixed dark-navy GRADIENT section
@@ -5622,9 +5622,9 @@ $fr$::jsonb,
5622
5622
  AND content::text LIKE '%nb-sandbox-promo%';
5623
5623
  END
5624
5624
  $body$;
5625
-
5626
-
5627
- -- >>> FROM: 00000000000010_drop_github_username.sql <<<
5625
+
5626
+
5627
+ -- >>> FROM: 00000000000010_drop_github_username.sql <<<
5628
5628
  -- Drop the github_username profile column and remove the GitHub-auth artifacts.
5629
5629
  --
5630
5630
  -- GitHub OAuth sign-in / account-linking was removed from the app: it cannot be
@@ -5704,9 +5704,9 @@ WHERE key IN (
5704
5704
  'github_link_failed',
5705
5705
  'github_connected'
5706
5706
  );
5707
-
5708
-
5709
- -- >>> FROM: 00000000000011_language_detection_admin_only.sql <<<
5707
+
5708
+
5709
+ -- >>> FROM: 00000000000011_language_detection_admin_only.sql <<<
5710
5710
  -- Restrict writes to the language-detection settings row to ADMIN only.
5711
5711
  --
5712
5712
  -- \`site_settings.language_detection_settings\` is a non-sensitive, anon-READABLE
@@ -5728,9 +5728,9 @@ CREATE POLICY site_settings_update_policy ON public.site_settings FOR UPDATE TO
5728
5728
 
5729
5729
  DROP POLICY IF EXISTS site_settings_delete_policy ON public.site_settings;
5730
5730
  CREATE POLICY site_settings_delete_policy ON public.site_settings FOR DELETE TO authenticated USING ((((key <> ALL (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = ANY (ARRAY['ADMIN'::public.user_role, 'WRITER'::public.user_role]))) OR ((key = ANY (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = 'ADMIN'::public.user_role))));
5731
-
5732
-
5733
- -- >>> FROM: 00000000000012_cortex_ai_stock_photo_settings.sql <<<
5731
+
5732
+
5733
+ -- >>> FROM: 00000000000012_cortex_ai_stock_photo_settings.sql <<<
5734
5734
  -- Protect the Cortex AI stock-photo provider API keys stored in site_settings.
5735
5735
  --
5736
5736
  -- The stock-photo search tool (search_stock_photos) can read a Pexels or Unsplash
@@ -5756,9 +5756,9 @@ CREATE POLICY site_settings_update_policy ON public.site_settings FOR UPDATE TO
5756
5756
 
5757
5757
  DROP POLICY IF EXISTS site_settings_delete_policy ON public.site_settings;
5758
5758
  CREATE POLICY site_settings_delete_policy ON public.site_settings FOR DELETE TO authenticated USING ((((key <> ALL (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = ANY (ARRAY['ADMIN'::public.user_role, 'WRITER'::public.user_role]))) OR ((key = ANY (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = 'ADMIN'::public.user_role))));
5759
-
5760
-
5761
- -- >>> FROM: 00000000000013_youtube_nocookie_embeds.sql <<<
5759
+
5760
+
5761
+ -- >>> FROM: 00000000000013_youtube_nocookie_embeds.sql <<<
5762
5762
  -- 00000000000013_youtube_nocookie_embeds.sql
5763
5763
  --
5764
5764
  -- Lighthouse Best Practices scored 96 instead of 100: the \`inspector-issues\` audit
@@ -5895,9 +5895,9 @@ UPDATE public.custom_block_definitions
5895
5895
  )::jsonb
5896
5896
  WHERE layout_schema::text LIKE '%www.youtube.com/embed/%'
5897
5897
  OR layout_schema::text LIKE '%accelerated-motion%';
5898
-
5899
-
5900
- -- >>> FROM: 00000000000014_site_themes.sql <<<
5898
+
5899
+
5900
+ -- >>> FROM: 00000000000014_site_themes.sql <<<
5901
5901
  -- Editable site themes.
5902
5902
  --
5903
5903
  -- Themes used to be hardcoded CSS classes in libs/ui/src/styles/theme.css
@@ -6152,9 +6152,9 @@ VALUES
6152
6152
  }'
6153
6153
  )
6154
6154
  ON CONFLICT (slug) DO NOTHING;
6155
-
6156
-
6157
- -- >>> FROM: 00000000000015_scheduled_publishing.sql <<<
6155
+
6156
+
6157
+ -- >>> FROM: 00000000000015_scheduled_publishing.sql <<<
6158
6158
  -- Scheduled publishing for pages and products.
6159
6159
  --
6160
6160
  -- Posts already support scheduling: \`posts.published_at\` exists and every public
@@ -6198,9 +6198,9 @@ CREATE INDEX IF NOT EXISTS pages_status_published_at_idx
6198
6198
 
6199
6199
  CREATE INDEX IF NOT EXISTS products_status_published_at_idx
6200
6200
  ON public.products (status, published_at);
6201
-
6202
-
6203
- -- >>> FROM: 00000000000016_product_revisions_and_revision_baseline.sql <<<
6201
+
6202
+
6203
+ -- >>> FROM: 00000000000016_product_revisions_and_revision_baseline.sql <<<
6204
6204
  -- 00000000000016_product_revisions_and_revision_baseline.sql
6205
6205
  --
6206
6206
  -- Revision History, part 1 of 2 (schema). The application-side rewrite lives in
@@ -6511,9 +6511,9 @@ SELECT
6511
6511
  AND r.version <= pr.version
6512
6512
  )
6513
6513
  ON CONFLICT (product_id, version) DO NOTHING;
6514
-
6515
-
6516
- -- >>> FROM: 00000000000017_cortex_ai_mcp_server.sql <<<
6514
+
6515
+
6516
+ -- >>> FROM: 00000000000017_cortex_ai_mcp_server.sql <<<
6517
6517
  -- Cortex AI MCP (Model Context Protocol) server access.
6518
6518
  --
6519
6519
  -- Adds the bearer-token store that gates /api/mcp, the endpoint that exposes the
@@ -6605,9 +6605,9 @@ CREATE POLICY site_settings_update_policy ON public.site_settings FOR UPDATE TO
6605
6605
 
6606
6606
  DROP POLICY IF EXISTS site_settings_delete_policy ON public.site_settings;
6607
6607
  CREATE POLICY site_settings_delete_policy ON public.site_settings FOR DELETE TO authenticated USING ((((key <> ALL (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = ANY (ARRAY['ADMIN'::public.user_role, 'WRITER'::public.user_role]))) OR ((key = ANY (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = 'ADMIN'::public.user_role))));
6608
-
6609
-
6610
- -- >>> FROM: 00000000000018_site_scripts.sql <<<
6608
+
6609
+
6610
+ -- >>> FROM: 00000000000018_site_scripts.sql <<<
6611
6611
  -- Site scripts: admin-authored JavaScript injected into every page of the public site.
6612
6612
  --
6613
6613
  -- Rich-text blocks can already carry an inline <script>, but that script belongs to
@@ -6704,9 +6704,9 @@ DROP POLICY IF EXISTS "Admins delete site scripts" ON public.site_scripts;
6704
6704
  CREATE POLICY "Admins delete site scripts" ON public.site_scripts
6705
6705
  FOR DELETE TO authenticated
6706
6706
  USING (((SELECT public.get_current_user_role()) = 'ADMIN'::public.user_role));
6707
-
6708
-
6709
- -- >>> FROM: 00000000000019_site_script_revisions.sql <<<
6707
+
6708
+
6709
+ -- >>> FROM: 00000000000019_site_script_revisions.sql <<<
6710
6710
  -- Audit trail and undo for site scripts.
6711
6711
  --
6712
6712
  -- \`site_scripts\` ships arbitrary JavaScript to every visitor, which makes it the
@@ -6792,9 +6792,9 @@ DROP POLICY IF EXISTS "Admins insert site script revisions" ON public.site_scrip
6792
6792
  CREATE POLICY "Admins insert site script revisions" ON public.site_script_revisions
6793
6793
  FOR INSERT TO authenticated
6794
6794
  WITH CHECK (((SELECT public.get_current_user_role()) = 'ADMIN'::public.user_role));
6795
-
6796
-
6797
- -- >>> FROM: 00000000000020_updating_article.sql <<<
6795
+
6796
+
6797
+ -- >>> FROM: 00000000000020_updating_article.sql <<<
6798
6798
  -- 00000000000020_updating_article.sql
6799
6799
  -- Seeds the "How Updating NextBlock Works" guide as an EN/FR twin pair, the companion
6800
6800
  -- to the install guide seeded in the baseline (00000000000003, slugs 'how-to-setup-nextblock'
@@ -6957,9 +6957,9 @@ SELECT
6957
6957
  AND r.version <= po.version
6958
6958
  )
6959
6959
  ON CONFLICT (post_id, version) DO NOTHING;
6960
-
6961
-
6962
- -- >>> FROM: 00000000000021_updating_article_git_merge.sql <<<
6960
+
6961
+
6962
+ -- >>> FROM: 00000000000021_updating_article_git_merge.sql <<<
6963
6963
  -- 00000000000021_updating_article_git_merge.sql
6964
6964
  -- Corrects the "How Updating NextBlock Works" article seeded in 00000000000020.
6965
6965
  --
@@ -7051,9 +7051,9 @@ BEGIN
7051
7051
  END IF;
7052
7052
  END
7053
7053
  $body$;
7054
-
7055
-
7056
- -- >>> FROM: 00000000000022_updating_article_accuracy.sql <<<
7054
+
7055
+
7056
+ -- >>> FROM: 00000000000022_updating_article_accuracy.sql <<<
7057
7057
  -- 00000000000022_updating_article_accuracy.sql
7058
7058
  -- Three accuracy fixes to the "How Updating NextBlock Works" article
7059
7059
  -- (seeded in 00000000000020, first corrected in 00000000000021).
@@ -7148,9 +7148,9 @@ BEGIN
7148
7148
  END IF;
7149
7149
  END
7150
7150
  $body$;
7151
-
7152
-
7153
- -- >>> FROM: 00000000000023_updating_article_layout_not_host.sql <<<
7151
+
7152
+
7153
+ -- >>> FROM: 00000000000023_updating_article_layout_not_host.sql <<<
7154
7154
  -- 00000000000023_updating_article_layout_not_host.sql
7155
7155
  -- Corrects the most misleading claim in the "How Updating NextBlock Works" article
7156
7156
  -- (seeded 00000000000020, corrected in 021 and 022): that the automatic GitHub Action is
@@ -7238,9 +7238,9 @@ BEGIN
7238
7238
  END IF;
7239
7239
  END
7240
7240
  $body$;
7241
-
7242
-
7243
- -- >>> FROM: 00000000000024_updating_article_newline_fix.sql <<<
7241
+
7242
+
7243
+ -- >>> FROM: 00000000000024_updating_article_newline_fix.sql <<<
7244
7244
  -- 00000000000024_updating_article_newline_fix.sql
7245
7245
  -- Repairs two mistakes made by 00000000000023 in the "How Updating NextBlock Works"
7246
7246
  -- article, and lands the FAQ entry that migration failed to insert.
@@ -7311,9 +7311,9 @@ BEGIN
7311
7311
  END IF;
7312
7312
  END
7313
7313
  $body$;
7314
-
7315
-
7316
- -- >>> FROM: 00000000000025_rebrand_nextblock_dev.sql <<<
7314
+
7315
+
7316
+ -- >>> FROM: 00000000000025_rebrand_nextblock_dev.sql <<<
7317
7317
  -- 00000000000025_rebrand_nextblock_dev.sql
7318
7318
  -- Domain rebrand: the retired .ca domain -> nextblock.dev.
7319
7319
  --
@@ -7367,9 +7367,9 @@ BEGIN
7367
7367
  WHERE value::text LIKE '%' || legacy_domain || '%';
7368
7368
  END
7369
7369
  $body$;
7370
-
7371
-
7372
- -- >>> FROM: 00000000000026_product_inquiries.sql <<<
7370
+
7371
+
7372
+ -- >>> FROM: 00000000000026_product_inquiries.sql <<<
7373
7373
  -- Purchase enquiries raised when the store cannot take payment.
7374
7374
  --
7375
7375
  -- A NextBlock store can be fully built — products, prices, images, pages — while its
@@ -7488,9 +7488,9 @@ INSERT INTO public.translations (key, translations, created_at, updated_at) VALU
7488
7488
  ('ecommerce.not_available_for_purchase', '{"en": "Not available for online purchase", "fr": "Non disponible à l''achat en ligne"}', now(), now()),
7489
7489
  ('ecommerce.checkout_payments_unavailable', '{"en": "This store is not able to take payments right now. Please contact the seller to complete your purchase.", "fr": "Cette boutique ne peut pas accepter de paiements pour le moment. Veuillez contacter le vendeur pour finaliser votre achat."}', now(), now())
7490
7490
  ON CONFLICT (key) DO NOTHING;
7491
-
7492
-
7493
- -- >>> FROM: 00000000000027_message_threads.sql <<<
7491
+
7492
+
7493
+ -- >>> FROM: 00000000000027_message_threads.sql <<<
7494
7494
  -- Private conversations with anonymous visitors, and the end of the exposed form address.
7495
7495
  --
7496
7496
  -- Two problems, one shape.
@@ -7882,9 +7882,9 @@ INSERT INTO public.translations (key, translations, created_at, updated_at) VALU
7882
7882
  ('thread.you', '{"en": "You", "fr": "Vous"}', now(), now()),
7883
7883
  ('forms.submission_stored', '{"en": "Thanks - your message has been received.", "fr": "Merci - votre message a bien été reçu."}', now(), now())
7884
7884
  ON CONFLICT (key) DO NOTHING;
7885
-
7886
-
7887
- -- >>> FROM: 00000000000028_interaction_replies.sql <<<
7885
+
7886
+
7887
+ -- >>> FROM: 00000000000028_interaction_replies.sql <<<
7888
7888
  -- Staff replies on reviews and post comments, and the indexes cms_interactions never had.
7889
7889
  --
7890
7890
  -- WHY THIS IS A DIFFERENT SHAPE FROM MIGRATION 27, AND WHY IT NEEDS NO TOKEN.
@@ -7971,9 +7971,9 @@ INSERT INTO public.translations (key, translations, created_at, updated_at) VALU
7971
7971
  ('interactions.staff_reply', '{"en": "Reply from the team", "fr": "Réponse de l''équipe"}', now(), now()),
7972
7972
  ('interactions.staff_badge', '{"en": "Staff", "fr": "Équipe"}', now(), now())
7973
7973
  ON CONFLICT (key) DO NOTHING;
7974
-
7975
-
7976
- -- >>> FROM: 00000000000029_form_endpoints_default_empty.sql <<<
7974
+
7975
+
7976
+ -- >>> FROM: 00000000000029_form_endpoints_default_empty.sql <<<
7977
7977
  -- A contact form has no address of its own by default.
7978
7978
  --
7979
7979
  -- The starter content ships a contact page addressed to \`contact@example.com\`, and
@@ -8026,9 +8026,9 @@ UPDATE public.site_settings
8026
8026
  WHERE key IN ('forms_contact', 'store_contact')
8027
8027
  AND value ? 'contactEmail'
8028
8028
  AND lower(value->>'contactEmail') LIKE '%@example.%';
8029
-
8030
-
8031
- -- >>> FROM: 00000000000030_seo_redirects_and_robots.sql <<<
8029
+
8030
+
8031
+ -- >>> FROM: 00000000000030_seo_redirects_and_robots.sql <<<
8032
8032
  -- SEO engine: managed 301/302 redirects and operator-configurable robots directives.
8033
8033
  --
8034
8034
  -- Two unrelated-looking things ship in one migration because they are the same
@@ -8178,9 +8178,9 @@ VALUES (
8178
8178
  '{"customRules": "", "isIndexingEnabled": true, "sitemapEnabled": true, "userAgentRules": [{"allow": ["/"], "disallow": [], "userAgent": "*"}]}'::jsonb
8179
8179
  )
8180
8180
  ON CONFLICT (key) DO NOTHING;
8181
-
8182
-
8183
- -- >>> FROM: 00000000000031_seo_robots_settings_admin_only.sql <<<
8181
+
8182
+
8183
+ -- >>> FROM: 00000000000031_seo_robots_settings_admin_only.sql <<<
8184
8184
  -- Restrict writes to the robots.txt settings row to ADMIN only.
8185
8185
  --
8186
8186
  -- \`site_settings.seo_robots_settings\` is the row that decides whether the whole site
@@ -8216,65 +8216,1878 @@ DROP POLICY IF EXISTS site_settings_delete_policy ON public.site_settings;
8216
8216
  CREATE POLICY site_settings_delete_policy ON public.site_settings FOR DELETE TO authenticated USING ((((key <> ALL (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = ANY (ARRAY['ADMIN'::public.user_role, 'WRITER'::public.user_role]))) OR ((key = ANY (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = 'ADMIN'::public.user_role))));
8217
8217
 
8218
8218
  -- Forward-only and idempotent.
8219
-
8220
-
8221
- -- Step D: Record the applied migrations in history (truncated in Step B) so
8222
- -- \`npm run db:migrate:check\` reports up to date instead of listing every file as pending.
8223
- INSERT INTO supabase_migrations.schema_migrations (version, name) VALUES
8224
- ('00000000000000', 'baseline_schema'),
8225
- ('00000000000001', 'baseline_constraints_and_indexes'),
8226
- ('00000000000002', 'baseline_security_and_grants'),
8227
- ('00000000000003', 'baseline_seed'),
8228
- ('00000000000004', 'default_logo_email_safe'),
8229
- ('00000000000005', 'add_custom_canonical'),
8230
- ('00000000000006', 'home_live_demo_promo'),
8231
- ('00000000000007', 'home_live_demo_promo_copy_fix'),
8232
- ('00000000000008', 'setup_article_reorder'),
8233
- ('00000000000009', 'home_live_demo_promo_contrast'),
8234
- ('00000000000010', 'drop_github_username'),
8235
- ('00000000000011', 'language_detection_admin_only'),
8236
- ('00000000000012', 'cortex_ai_stock_photo_settings'),
8237
- ('00000000000013', 'youtube_nocookie_embeds'),
8238
- ('00000000000014', 'site_themes'),
8239
- ('00000000000015', 'scheduled_publishing'),
8240
- ('00000000000016', 'product_revisions_and_revision_baseline'),
8241
- ('00000000000017', 'cortex_ai_mcp_server'),
8242
- ('00000000000018', 'site_scripts'),
8243
- ('00000000000019', 'site_script_revisions'),
8244
- ('00000000000020', 'updating_article'),
8245
- ('00000000000021', 'updating_article_git_merge'),
8246
- ('00000000000022', 'updating_article_accuracy'),
8247
- ('00000000000023', 'updating_article_layout_not_host'),
8248
- ('00000000000024', 'updating_article_newline_fix'),
8249
- ('00000000000025', 'rebrand_nextblock_dev'),
8250
- ('00000000000026', 'product_inquiries'),
8251
- ('00000000000027', 'message_threads'),
8252
- ('00000000000028', 'interaction_replies'),
8253
- ('00000000000029', 'form_endpoints_default_empty'),
8254
- ('00000000000030', 'seo_redirects_and_robots'),
8255
- ('00000000000031', 'seo_robots_settings_admin_only')
8256
- ON CONFLICT (version) DO NOTHING;
8257
-
8258
- -- Step E: Anchor preserved profiles
8259
- INSERT INTO public.profiles (id, updated_at, full_name, avatar_url, website, role)
8260
- SELECT preserved_user.id, NULL, NULL, NULL, NULL, 'ADMIN'
8261
- FROM (
8262
- VALUES
8263
- ('63a8aa07-ef6e-4cc7-bafa-ece023c74366'::uuid),
8264
- ('e3a2c121-70a4-4239-a9df-f70ce717f5a1'::uuid)
8265
- ) AS preserved_user(id)
8266
- WHERE EXISTS (SELECT 1 FROM auth.users WHERE id = preserved_user.id)
8267
- AND NOT EXISTS (SELECT 1 FROM public.profiles WHERE id = preserved_user.id);
8268
-
8269
- -- Step F: Re-assert the "first admin exists" flag. The sandbox preserves its demo
8270
- -- ADMIN users across the wipe (Steps A & E), but the reseeded baseline resets
8271
- -- is_admin_created to 'false' and handle_new_user() only flips it on a NEW auth.users
8272
- -- INSERT -- which never fires for preserved users. Without this the proxy setup-gate
8273
- -- funnels ALL sandbox traffic (including this reset cron on its next run) to /setup even
8274
- -- though admins already exist. Guarded on an ADMIN profile actually being present.
8275
- UPDATE public.site_settings
8276
- SET value = 'true'::jsonb
8277
- WHERE key = 'is_admin_created'
8278
- AND EXISTS (SELECT 1 FROM public.profiles WHERE role = 'ADMIN'::public.user_role);
8279
-
8280
- `;
8219
+
8220
+
8221
+ -- >>> FROM: 00000000000032_seed_seo_score_optimizations.sql <<<
8222
+ -- Migration: 00000000000032_seed_seo_score_optimizations.sql
8223
+ -- Description: Optimize seeded pages and posts for perfect 100/100 Page SEO scores.
8224
+ -- Safety: All updates are forward-only and content-guarded so they only apply to
8225
+ -- default seeded copy and will NEVER overwrite customized content on external sites.
8226
+
8227
+ DO $$
8228
+ BEGIN
8229
+ -----------------------------------------------------------------------------
8230
+ -- 1. Page Metadata Optimizations
8231
+ -----------------------------------------------------------------------------
8232
+ UPDATE public.pages
8233
+ SET meta_title = 'NextBlock™ - CMS Next.js Haute Performance',
8234
+ meta_description = 'NextBlock est un CMS Next.js open-source conçu sur Supabase. Éditeur visuel de blocs, bilingue et scores Lighthouse parfaits dès le premier jour.',
8235
+ updated_at = now()
8236
+ WHERE slug = 'accueil'
8237
+ AND (meta_title IS NULL OR meta_title = '' OR meta_title = 'NextBlock™ - CMS Next.js Haute Performance')
8238
+ AND (meta_description IS NULL OR meta_description = '' OR meta_description LIKE 'NextBlock est un CMS Next.js%');
8239
+
8240
+ UPDATE public.pages
8241
+ SET meta_title = 'NextBlock Journal | Engineering Guides & Tutorials',
8242
+ meta_description = 'Read technical deep dives, tutorials, and release notes on Next.js 16, Supabase, and modern visual web publishing from the NextBlock team.',
8243
+ updated_at = now()
8244
+ WHERE slug = 'articles' AND language_id = 1
8245
+ AND (meta_description IS NULL OR meta_description = '' OR meta_description = 'Explore architectural walkthroughs, Supabase recipes, and block editor experiments written by the Nextblock core team.');
8246
+
8247
+ UPDATE public.pages
8248
+ SET meta_title = 'Journal NextBlock | Guides Techniques et Tutoriels',
8249
+ meta_description = 'Découvrez des guides techniques, des tutoriels et des analyses sur Next.js 16, Supabase et l’édition de blocs moderne avec l’équipe NextBlock.',
8250
+ updated_at = now()
8251
+ WHERE slug = 'articles' AND language_id = 2
8252
+ AND (meta_description IS NULL OR meta_description = '' OR meta_description = 'Explorez les guides d''architecture, les recettes Supabase et les experiences de l''editeur de blocs de NextBlock.');
8253
+
8254
+ UPDATE public.pages
8255
+ SET meta_title = 'Contact Us | NextBlock Open-Source CMS',
8256
+ meta_description = 'Have questions, ideas, or feedback about NextBlock? Reach out to our team for technical support, partnership inquiries, and community discussions.',
8257
+ updated_at = now()
8258
+ WHERE slug = 'contact' AND language_id = 1
8259
+ AND (meta_description IS NULL OR meta_description = '' OR meta_description LIKE 'NextBlock™ is an open-source project driven%');
8260
+
8261
+ UPDATE public.pages
8262
+ SET meta_title = 'Contactez-nous | NextBlock CMS Open Source',
8263
+ meta_description = 'Une question, une idée ou un retour sur NextBlock ? Contactez notre équipe pour du support technique, des partenariats ou échanger sur le projet.',
8264
+ updated_at = now()
8265
+ WHERE slug = 'contact' AND language_id = 2
8266
+ AND (meta_description IS NULL OR meta_description = '' OR meta_description LIKE 'NextBlock™ est un projet open-source propulsé%');
8267
+
8268
+ UPDATE public.pages
8269
+ SET meta_title = 'Shop NextBlock™ Modules | Official Store',
8270
+ meta_description = 'Browse official commercial modules and licenses for NextBlock CMS. Get instant access to NextBlock Commerce and Cortex AI with secure checkout.',
8271
+ updated_at = now()
8272
+ WHERE slug = 'shop'
8273
+ AND (meta_description IS NULL OR meta_description = '' OR meta_description = 'Browse our premium products');
8274
+
8275
+ UPDATE public.pages
8276
+ SET meta_title = 'Boutique NextBlock™ | Modules et Licences Officielles',
8277
+ meta_description = 'Achetez des licences et extensions officielles pour NextBlock CMS. Accédez à NextBlock Commerce et Cortex AI avec un paiement simple et sécurisé.',
8278
+ updated_at = now()
8279
+ WHERE slug = 'boutique'
8280
+ AND (meta_description IS NULL OR meta_description = '' OR meta_description IN ('Decouvrez nos produits premium', 'Découvrez nos produits premium'));
8281
+
8282
+ -----------------------------------------------------------------------------
8283
+ -- 2. Post Metadata Optimizations
8284
+ -----------------------------------------------------------------------------
8285
+ UPDATE public.posts
8286
+ SET meta_description = 'A single command keeps your NextBlock install updated on Docker, Supabase, or a cloned repo. Learn how it works and keeps your data safe.',
8287
+ updated_at = now()
8288
+ WHERE slug = 'how-updating-works'
8289
+ AND (meta_description IS NULL OR meta_description LIKE 'A single command keeps your NextBlock install updated%');
8290
+
8291
+ UPDATE public.posts
8292
+ SET meta_title = 'Mises à jour NextBlock : une commande pour chaque site',
8293
+ meta_description = 'Une seule commande met à jour NextBlock sur Docker, Supabase ou un dépôt cloné. Découvrez le fonctionnement et la protection de vos données.',
8294
+ updated_at = now()
8295
+ WHERE slug = 'comment-fonctionnent-les-mises-a-jour'
8296
+ AND (meta_title IS NULL OR meta_title LIKE 'Les mises à jour de NextBlock%');
8297
+
8298
+ -----------------------------------------------------------------------------
8299
+ -- 3. Post Content Optimizations (Content-Guarded)
8300
+ -----------------------------------------------------------------------------
8301
+ -- Post 1: How NextBlock Works EN
8302
+ UPDATE public.blocks
8303
+ SET content = jsonb_set(content, '{html_content}', to_jsonb('
8304
+ <p class=''text-lg leading-8 text-slate-700 dark:text-slate-300''>NextBlock™ is built so the hosted CMS, the open-source starter, and the developer tools feel like one clear product. A shared Nx workspace and typed blocks keep code clean and teams moving fast.</p>
8305
+
8306
+ <div class=''grid gap-4 md:grid-cols-3 my-10''>
8307
+ <div class=''rounded-3xl border border-sky-200/70 bg-sky-50/70 p-6 dark:border-sky-500/20 dark:bg-sky-500/10''>
8308
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-sky-700 dark:text-sky-200''>One codebase</p>
8309
+ <h2 class=''mt-3 text-xl font-semibold text-slate-900 dark:text-white''>Shared foundation</h2>
8310
+ <p class=''mt-3 text-sm text-slate-600 dark:text-slate-300''>Marketing pages, CMS screens, and the starter template grow together instead of drifting apart.</p>
8311
+ </div>
8312
+ <div class=''rounded-3xl border border-indigo-200/70 bg-indigo-50/70 p-6 dark:border-indigo-500/20 dark:bg-indigo-500/10''>
8313
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-indigo-700 dark:text-indigo-200''>Typed content</p>
8314
+ <h2 class=''mt-3 text-xl font-semibold text-slate-900 dark:text-white''>Blocks with guardrails</h2>
8315
+ <p class=''mt-3 text-sm text-slate-600 dark:text-slate-300''>Zod schemas and typed contracts make every custom block safe to build and ship.</p>
8316
+ </div>
8317
+ <div class=''rounded-3xl border border-emerald-200/70 bg-emerald-50/70 p-6 dark:border-emerald-500/20 dark:bg-emerald-500/10''>
8318
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200''>Editorial UX</p>
8319
+ <h2 class=''mt-3 text-xl font-semibold text-slate-900 dark:text-white''>Product-grade editing</h2>
8320
+ <p class=''mt-3 text-sm text-slate-600 dark:text-slate-300''>The Tiptap layer gives writers a rich editing screen without hiding the power of clean HTML.</p>
8321
+ </div>
8322
+ </div>
8323
+
8324
+ <div class=''flex flex-col md:flex-row gap-8 items-center my-12''>
8325
+ <div class=''w-full md:w-1/2 space-y-4''>
8326
+ <h2>Monorepo Layout and Dependency Flow</h2>
8327
+ <p>The <code>apps/nextblock</code> folder holds the production Next.js app. This includes the public site and the private CMS admin area. The <code>apps/create-nextblock</code> tool mirrors that setup so teams can start with proven patterns right away.</p>
8328
+ <ul class=''list-disc pl-6 space-y-2 text-sm''>
8329
+ <li><strong>@nextblock-cms/ui</strong> - UI parts, design tokens, and shared buttons</li>
8330
+ <li><strong>@nextblock-cms/utils</strong> - Translations, safety checks, and image helpers</li>
8331
+ <li><strong>@nextblock-cms/db</strong> - Safe migrations, typed database queries, and schemas</li>
8332
+ <li><strong>@nextblock-cms/editor</strong> - The reusable Tiptap v3 block editor</li>
8333
+ <li><strong>@nextblock-cms/sdk</strong> - Typed tools to build and check custom blocks</li>
8334
+ <li><strong>@nextblock-cms/ecommerce</strong> - The digital store package when activated</li>
8335
+ </ul>
8336
+ <p>Run <code>nx graph</code> to see how code flows across the workspace. Shared path aliases and Tailwind styles help keep designs aligned across all pages.</p>
8337
+ </div>
8338
+ <aside class=''w-full md:w-1/2 rounded-[2rem] border border-slate-200/80 bg-white p-4 shadow-xl dark:border-white/10 dark:bg-white/5''>
8339
+ <div class=''relative aspect-video overflow-hidden rounded-2xl''><iframe class=''absolute inset-0 h-full w-full border-0'' src=''https://www.youtube-nocookie.com/embed/DNqU8ez9qjs?si=p2oIy0f-n7wiaBmO'' title=''How NextBlock™ Works'' allow=''accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'' referrerpolicy=''strict-origin-when-cross-origin'' loading=''lazy'' allowfullscreen></iframe></div>
8340
+ <p class=''mt-3 text-sm text-slate-500 dark:text-slate-400''>Nx makes workspace relations clear. That is why our starter, CMS, and packages stay aligned.</p>
8341
+ </aside>
8342
+ </div>
8343
+
8344
+ <figure class=''my-12 overflow-hidden rounded-[2rem] border border-slate-200/80 bg-slate-950 shadow-2xl dark:border-white/10''>
8345
+ <img src=''/images/extensibility.webp'' alt=''NextBlock™ extensibility artwork showing the CMS connected to reusable modules and integrations'' class=''w-full h-auto object-cover'' />
8346
+ <figcaption class=''border-t border-white/10 px-6 py-4 text-sm text-slate-300''>One unified design system spans content blocks, editing tools, and store features.</figcaption>
8347
+ </figure>
8348
+
8349
+ <h2>Block Registry as Product Surface</h2>
8350
+ <p>The block registry file is the source of truth for all blocks. It holds Zod schemas, starter content, and editor components. Today it includes everything from text and headings to sections, post grids, checkout forms, and product cards.</p>
8351
+ <p>Sections support nested columns, so you can build real page layouts rather than flat lists. Typed helper functions keep custom layouts safe and easy to maintain.</p>
8352
+
8353
+ <h2>The Editing Layer</h2>
8354
+ <p>The editor package wraps Tiptap into a rich editing surface. It offers slash commands, floating menus, drag handles, tables, checklists, and code blocks. It preserves clean HTML so teams are never locked into a closed format.</p>
8355
+
8356
+ <h2>Inside the CMS Shell</h2>
8357
+ <p>Inside the CMS folder, each feature follows a clear pattern: item lists, create forms, edit screens, and server actions that wrap database updates. This gives editors a smooth flow while keeping credentials safe on the server.</p>
8358
+
8359
+ <h2>Open Core Without Product Drift</h2>
8360
+ <p>The core CMS is open-source under the AGPL license. Store modules remain source-available and turn on with verified licenses. This keeps the core lightweight while unlocking advanced tools when you need them.</p>
8361
+
8362
+ <h2>Why It Holds Together</h2>
8363
+ <p>The Nx monorepo keeps libraries clean. The Next.js framework ensures fast page loads. Supabase migrations define database rules, and Tiptap gives writers a great authoring screen. When you run <code>npm create nextblock</code>, you get a complete, working system from day one.</p>
8364
+ '::text)),
8365
+ updated_at = now()
8366
+ WHERE post_id = 1
8367
+ AND content->>'html_content' LIKE '%NextBlock™ is designed so the hosted CMS%';
8368
+
8369
+ -- Post 2: Comment NextBlock Fonctionne FR
8370
+ UPDATE public.blocks
8371
+ SET content = jsonb_set(content, '{html_content}', to_jsonb('
8372
+ <p class=''text-lg leading-8 text-slate-700 dark:text-slate-300''>NextBlock™ est conçu pour offrir une expérience fluide entre le CMS hébergé, le projet open-source et les outils développeur. L''espace Nx partagé et les blocs typés permettent aux équipes de publier vite tout en gardant un code très propre.</p>
8373
+
8374
+ <div class=''grid gap-4 md:grid-cols-3 my-10''>
8375
+ <div class=''rounded-3xl border border-sky-200/70 bg-sky-50/70 p-6 dark:border-sky-500/20 dark:bg-sky-500/10''>
8376
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-sky-700 dark:text-sky-200''>Base unique</p>
8377
+ <h2 class=''mt-3 text-xl font-semibold text-slate-900 dark:text-white''>Une même base</h2>
8378
+ <p class=''mt-3 text-sm text-slate-600 dark:text-slate-300''>Les pages du site, les écrans du CMS et le modèle de départ évoluent ensemble sans dérive.</p>
8379
+ </div>
8380
+ <div class=''rounded-3xl border border-indigo-200/70 bg-indigo-50/70 p-6 dark:border-indigo-500/20 dark:bg-indigo-500/10''>
8381
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-indigo-700 dark:text-indigo-200''>Contenu typé</p>
8382
+ <h2 class=''mt-3 text-xl font-semibold text-slate-900 dark:text-white''>Blocs avec garde-fous</h2>
8383
+ <p class=''mt-3 text-sm text-slate-600 dark:text-slate-300''>Les schémas Zod et les types stricts sécurisent chaque nouveau bloc personnalisé.</p>
8384
+ </div>
8385
+ <div class=''rounded-3xl border border-emerald-200/70 bg-emerald-50/70 p-6 dark:border-emerald-500/20 dark:bg-emerald-500/10''>
8386
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200''>Confort de rédaction</p>
8387
+ <h2 class=''mt-3 text-xl font-semibold text-slate-900 dark:text-white''>Édition premium</h2>
8388
+ <p class=''mt-3 text-sm text-slate-600 dark:text-slate-300''>L''éditeur Tiptap offre un vrai confort de travail sans brider la puissance du HTML propre.</p>
8389
+ </div>
8390
+ </div>
8391
+
8392
+ <div class=''flex flex-col md:flex-row gap-8 items-center my-12''>
8393
+ <div class=''w-full md:w-1/2 space-y-4''>
8394
+ <h2>Architecture monorepo et flux de dépendances</h2>
8395
+ <p>Le dossier <code>apps/nextblock</code> contient le site Next.js public et le tableau de bord privé du CMS. La commande <code>apps/create-nextblock</code> reprend cette même base pour lancer des projets sains dès le premier jour.</p>
8396
+ <ul class=''list-disc pl-6 space-y-2 text-sm''>
8397
+ <li><strong>@nextblock-cms/ui</strong> - Composants d''interface, boutons et styles partagés</li>
8398
+ <li><strong>@nextblock-cms/utils</strong> - Traductions, gardes d''environnement et images</li>
8399
+ <li><strong>@nextblock-cms/db</strong> - Migrations sûres, accès typé à la base et schémas</li>
8400
+ <li><strong>@nextblock-cms/editor</strong> - L''éditeur de blocs réutilisable basé sur Tiptap v3</li>
8401
+ <li><strong>@nextblock-cms/sdk</strong> - Outils typés pour créer et vérifier des blocs sur mesure</li>
8402
+ <li><strong>@nextblock-cms/ecommerce</strong> - Le module de boutique en ligne une fois activé</li>
8403
+ </ul>
8404
+ <p>La commande <code>nx graph</code> montre clairement les liens entre chaque dossier. Les alias de code et la configuration Tailwind partagée assurent un design soigné partout.</p>
8405
+ </div>
8406
+ <aside class=''w-full md:w-1/2 rounded-[2rem] border border-slate-200/80 bg-white p-4 shadow-xl dark:border-white/10 dark:bg-white/5''>
8407
+ <div class=''relative aspect-video overflow-hidden rounded-2xl''><iframe class=''absolute inset-0 h-full w-full border-0'' src=''https://www.youtube-nocookie.com/embed/DNqU8ez9qjs?si=p2oIy0f-n7wiaBmO'' title=''Comment NextBlock™ Fonctionne'' allow=''accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'' referrerpolicy=''strict-origin-when-cross-origin'' loading=''lazy'' allowfullscreen></iframe></div>
8408
+ <p class=''mt-3 text-sm text-slate-500 dark:text-slate-400''>Nx rend chaque lien visible dans le projet. C''est pourquoi le starter et le CMS restent toujours synchronisés.</p>
8409
+ </aside>
8410
+ </div>
8411
+
8412
+ <figure class=''my-12 overflow-hidden rounded-[2rem] border border-slate-200/80 bg-slate-950 shadow-2xl dark:border-white/10''>
8413
+ <img src=''/images/extensibility.webp'' alt=''Illustration NextBlock montrant les connexions entre le CMS et les modules externes'' class=''w-full h-auto object-cover'' />
8414
+ <figcaption class=''border-t border-white/10 px-6 py-4 text-sm text-slate-300''>Un même système visuel réunit la gestion de contenu, l''édition et les modules du store.</figcaption>
8415
+ </figure>
8416
+
8417
+ <h2>Le registre de blocs comme surface produit</h2>
8418
+ <p>Le registre de blocs est la source de vérité pour tous les blocs du CMS. Il rassemble les schémas Zod, les contenus de départ et les composants d''affichage. Il gère le texte, les titres, les sections, les listes d''articles et les formulaires de paiement.</p>
8419
+ <p>Les sections acceptent des colonnes imbriquées. Vous pouvez ainsi monter de vraies pages complètes plutôt que de simples listes de textes. Des fonctions typées rendent cette souplesse très sûre à manipuler.</p>
8420
+
8421
+ <h2>La couche d''édition</h2>
8422
+ <p>Le paquet éditeur transforme Tiptap en un espace de rédaction riche. Il propose des commandes slash, des menus flottants, des tableaux, des listes de tâches et des blocs de code colorés. Il conserve un HTML propre pour ne jamais vous enfermer.</p>
8423
+
8424
+ <h2>À l''intérieur du shell CMS</h2>
8425
+ <p>Dans le dossier CMS, chaque module suit la même logique : listes de données, pages d''ajout, écrans d''édition et Server Actions. Les rédacteurs travaillent en toute confiance pendant que les accès restent protégés sur le serveur.</p>
8426
+
8427
+ <h2>Open core sans dérive produit</h2>
8428
+ <p>Le cœur de NextBlock est open-source sous licence AGPL. Les modules du store s''activent avec une clé de licence valide. Le socle reste léger tout en ouvrant des outils pro quand vous en avez besoin.</p>
8429
+
8430
+ <h2>Pourquoi l''ensemble tient</h2>
8431
+ <p>Le monorepo Nx garde les librairies bien rangées. L''application Next.js assure la rapidité des pages. Les migrations Supabase fixent les règles de la base, et l''éditeur Tiptap offre un vrai confort de travail. En lançant <code>npm create nextblock</code>, vous profitez d''une base solide et prête à l''emploi.</p>
8432
+ '::text)),
8433
+ updated_at = now()
8434
+ WHERE post_id = 2
8435
+ AND content->>'html_content' LIKE '%NextBlock™ relie le CMS h&eacute;berg&eacute;%';
8436
+
8437
+ -- Post 3: Setup EN (Card headings H3 -> H2)
8438
+ UPDATE public.blocks
8439
+ SET content = jsonb_set(
8440
+ content,
8441
+ '{html_content}',
8442
+ to_jsonb(
8443
+ replace(
8444
+ replace(
8445
+ replace(
8446
+ replace(
8447
+ content->>'html_content',
8448
+ '<h3 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>Deploy on Vercel</h3>',
8449
+ '<h2 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>Deploy on Vercel</h2>'
8450
+ ),
8451
+ '<h3 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>npm create nextblock &rarr; Docker</h3>',
8452
+ '<h2 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>npm create nextblock &rarr; Docker</h2>'
8453
+ ),
8454
+ '<h3 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>npm create nextblock &rarr; Supabase + R2</h3>',
8455
+ '<h2 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>npm create nextblock &rarr; Supabase + R2</h2>'
8456
+ ),
8457
+ '<h3 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>Clone the repository</h3>',
8458
+ '<h2 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>Clone the repository</h2>'
8459
+ )
8460
+ )
8461
+ ),
8462
+ updated_at = now()
8463
+ WHERE post_id = 3
8464
+ AND content->>'html_content' LIKE '%NextBlock is an open-source, AI-native Next.js CMS%';
8465
+
8466
+ -- Post 4: Setup FR (Card headings H3 -> H2)
8467
+ UPDATE public.blocks
8468
+ SET content = jsonb_set(
8469
+ content,
8470
+ '{html_content}',
8471
+ to_jsonb(
8472
+ replace(
8473
+ replace(
8474
+ replace(
8475
+ replace(
8476
+ content->>'html_content',
8477
+ '<h3 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>Déployer sur Vercel</h3>',
8478
+ '<h2 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>Déployer sur Vercel</h2>'
8479
+ ),
8480
+ '<h3 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>npm create nextblock &rarr; Docker</h3>',
8481
+ '<h2 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>npm create nextblock &rarr; Docker</h2>'
8482
+ ),
8483
+ '<h3 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>npm create nextblock &rarr; Supabase + R2</h3>',
8484
+ '<h2 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>npm create nextblock &rarr; Supabase + R2</h2>'
8485
+ ),
8486
+ '<h3 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>Cloner le dépôt</h3>',
8487
+ '<h2 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>Cloner le dépôt</h2>'
8488
+ )
8489
+ )
8490
+ ),
8491
+ updated_at = now()
8492
+ WHERE post_id = 4
8493
+ AND content->>'html_content' LIKE '%NextBlock est un CMS Next.js open-source%';
8494
+
8495
+ -- Post 5: Commerce EN
8496
+ UPDATE public.blocks
8497
+ SET content = jsonb_set(content, '{html_content}', to_jsonb('
8498
+ <p class=''text-lg leading-8 text-slate-700 dark:text-slate-300''>NextBlock™ Commerce is our first premium module. It adds a complete store layer to the same editor you use for content. It is built for teams that want their catalog and checkout in one place.</p>
8499
+
8500
+ <div class=''grid gap-4 md:grid-cols-3 my-10''>
8501
+ <div class=''rounded-3xl border border-emerald-200/70 bg-emerald-50/70 p-6 dark:border-emerald-500/20 dark:bg-emerald-500/10''>
8502
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200''>Commerce core</p>
8503
+ <h2 class=''mt-3 text-xl font-semibold text-slate-900 dark:text-white''>Catalog + checkout</h2>
8504
+ <p class=''mt-3 text-sm text-slate-600 dark:text-slate-300''>Products, orders, shipping, and invoices plug right into the CMS shell.</p>
8505
+ </div>
8506
+ <div class=''rounded-3xl border border-sky-200/70 bg-sky-50/70 p-6 dark:border-sky-500/20 dark:bg-sky-500/10''>
8507
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-sky-700 dark:text-sky-200''>Global selling</p>
8508
+ <h2 class=''mt-3 text-xl font-semibold text-slate-900 dark:text-white''>Multi-currency ready</h2>
8509
+ <p class=''mt-3 text-sm text-slate-600 dark:text-slate-300''>Live rate sync, price rounding, and market rules make selling worldwide simple.</p>
8510
+ </div>
8511
+ <div class=''rounded-3xl border border-indigo-200/70 bg-indigo-50/70 p-6 dark:border-indigo-500/20 dark:bg-indigo-500/10''>
8512
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-indigo-700 dark:text-indigo-200''>Operator workflow</p>
8513
+ <h2 class=''mt-3 text-xl font-semibold text-slate-900 dark:text-white''>Provider-aware flow</h2>
8514
+ <p class=''mt-3 text-sm text-slate-600 dark:text-slate-300''>Stripe and Freemius run side by side so your shop stays clean and easy to use.</p>
8515
+ </div>
8516
+ </div>
8517
+
8518
+ <h2>Product Catalog</h2>
8519
+ <p>The store supports physical goods and digital downloads. You can set up variants, custom options, images, prices, SKUs, and stock levels. Product photos live in your main media library. That means your content and marketing teams work with the same files.</p>
8520
+
8521
+ <h2>Multi-Currency Engine</h2>
8522
+ <p>The pricing engine is built for real international stores. It handles rates, rounding, and rules with ease:</p>
8523
+ <ul class=''list-disc pl-6 space-y-2 text-sm''>
8524
+ <li><strong>Unlimited currencies:</strong> Add any ISO currency code, symbol, and exchange rate.</li>
8525
+ <li><strong>Auto FX sync:</strong> Refresh daily rates from Frankfurter or your own provider URL.</li>
8526
+ <li><strong>Rounding rules:</strong> Round prices up, down, or use charm pricing like <code>9.99</code>.</li>
8527
+ <li><strong>Store auto-sync:</strong> Convert product prices whenever currency rates refresh.</li>
8528
+ <li><strong>Rebasing:</strong> Switch your base store currency with full recalculations.</li>
8529
+ <li><strong>Custom price overrides:</strong> Set exact prices for specific countries when needed.</li>
8530
+ </ul>
8531
+
8532
+ <h2>Tax Automation</h2>
8533
+ <p>You can set tax rates by hand or let Stripe Tax calculate totals automatically:</p>
8534
+ <div class=''grid md:grid-cols-2 gap-6 my-6''>
8535
+ <div class=''p-6 rounded-2xl border border-slate-200 dark:border-white/10 bg-slate-50 dark:bg-white/5''>
8536
+ <h3 class=''font-bold text-slate-900 dark:text-white mb-2''>Manual mode</h3>
8537
+ <p class=''text-sm text-slate-600 dark:text-slate-400''>Set tax rates by country, state, or province. Stacked rates like GST and PST are supported. Detailed tax lines are saved with each order.</p>
8538
+ </div>
8539
+ <div class=''p-6 rounded-2xl border border-slate-200 dark:border-white/10 bg-slate-50 dark:bg-white/5''>
8540
+ <h3 class=''font-bold text-slate-900 dark:text-white mb-2''>Automatic mode</h3>
8541
+ <p class=''text-sm text-slate-600 dark:text-slate-400''>Stripe Tax calculates final amounts during checkout. Product tax codes travel with each item, and webhooks record final numbers.</p>
8542
+ </div>
8543
+ </div>
8544
+
8545
+ <h2>Shipping and Checkout</h2>
8546
+ <p>Shipping zones match by country and state. They support local method names, per-currency pricing, and free shipping rules. Fallback options ensure buyers always see a valid rate.</p>
8547
+ <p>The checkout flow understands different payment providers:</p>
8548
+ <ul class=''list-disc pl-6 space-y-2 text-sm''>
8549
+ <li><strong>Stripe:</strong> Handles physical goods, inventory checks, shipping costs, taxes, and Checkout sessions.</li>
8550
+ <li><strong>Freemius:</strong> Handles digital software licenses, plans, and hosted checkout pages.</li>
8551
+ <li>Cart items stay grouped by provider so the buying steps are always clear.</li>
8552
+ </ul>
8553
+
8554
+ <figure class=''my-12 overflow-hidden rounded-[2rem] border border-slate-200/80 bg-slate-950 shadow-2xl dark:border-white/10''>
8555
+ <img src=''/images/commerce-plan.webp'' alt=''Commerce roadmap board outlining premium module goals and future storefront capabilities for NextBlock™'' class=''w-full h-auto object-cover'' />
8556
+ <figcaption class=''border-t border-white/10 px-6 py-4 text-sm text-slate-300''>Commerce is the first premium module on our roadmap. It fits naturally into the larger CMS platform.</figcaption>
8557
+ </figure>
8558
+
8559
+ <h2>Inventory, Orders, and Invoices</h2>
8560
+ <p>When stock tracking is on, checkout checks quantities before payment. Once paid, stock counts update in the database right away.</p>
8561
+ <ul class=''list-disc pl-6 space-y-2 text-sm''>
8562
+ <li>Order status moves smoothly from pending to paid to shipped.</li>
8563
+ <li>Invoice numbers generate through safe database functions.</li>
8564
+ <li>Printable invoices use your company brand settings.</li>
8565
+ <li>Customers can view their past orders and receipts anytime.</li>
8566
+ </ul>
8567
+
8568
+ <h2>Commerce Surfaces Inside the CMS</h2>
8569
+ <p>When the store package is active, the CMS reveals new screens. You get product lists, stock tools, order details, shipping setup, tax rules, and currency settings. All of these screens look and feel like the rest of the CMS, so your team feels right at home.</p>
8570
+ '::text)),
8571
+ updated_at = now()
8572
+ WHERE post_id = 5
8573
+ AND content->>'html_content' LIKE '%NextBlock™ Commerce is the first premium module%';
8574
+
8575
+ -- Post 6: Commerce FR
8576
+ UPDATE public.blocks
8577
+ SET content = jsonb_set(content, '{html_content}', to_jsonb('
8578
+ <p class=''text-lg leading-8 text-slate-700 dark:text-slate-300''>NextBlock™ Commerce est notre premier module premium. Il ajoute une vraie boutique en ligne directement dans le CMS. Il s''adresse aux équipes qui veulent réunir leurs articles, leur catalogue et leurs ventes au même endroit.</p>
8579
+
8580
+ <div class=''grid gap-4 md:grid-cols-3 my-10''>
8581
+ <div class=''rounded-3xl border border-emerald-200/70 bg-emerald-50/70 p-6 dark:border-emerald-500/20 dark:bg-emerald-500/10''>
8582
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200''>Cœur commerce</p>
8583
+ <h2 class=''mt-3 text-xl font-semibold text-slate-900 dark:text-white''>Catalogue + checkout</h2>
8584
+ <p class=''mt-3 text-sm text-slate-600 dark:text-slate-300''>Articles, commandes, livraison et factures s''intègrent dans le même CMS.</p>
8585
+ </div>
8586
+ <div class=''rounded-3xl border border-sky-200/70 bg-sky-50/70 p-6 dark:border-sky-500/20 dark:bg-sky-500/10''>
8587
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-sky-700 dark:text-sky-200''>Vente internationale</p>
8588
+ <h2 class=''mt-3 text-xl font-semibold text-slate-900 dark:text-white''>Multi-devise</h2>
8589
+ <p class=''mt-3 text-sm text-slate-600 dark:text-slate-300''>Taux de change en direct, prix ronds et règles locales facilitent les ventes.</p>
8590
+ </div>
8591
+ <div class=''rounded-3xl border border-indigo-200/70 bg-indigo-50/70 p-6 dark:border-indigo-500/20 dark:bg-indigo-500/10''>
8592
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-indigo-700 dark:text-indigo-200''>Gestion claire</p>
8593
+ <h2 class=''mt-3 text-xl font-semibold text-slate-900 dark:text-white''>Par fournisseur</h2>
8594
+ <p class=''mt-3 text-sm text-slate-600 dark:text-slate-300''>Stripe et Freemius fonctionnent ensemble pour garder une boutique claire.</p>
8595
+ </div>
8596
+ </div>
8597
+
8598
+ <h2>Catalogue produits</h2>
8599
+ <p>Le module gère les biens physiques et les produits téléchargeables. Vous pouvez créer des variantes, des options sur mesure, des images, des prix, des SKU et des niveaux de stock. Vos visuels restent rangés dans votre médiathèque habituelle. Rédacteurs et vendeurs travaillent donc avec les mêmes fichiers.</p>
8600
+
8601
+ <h2>Moteur multi-devise</h2>
8602
+ <p>La gestion des prix est conçue pour de vraies boutiques mondiales :</p>
8603
+ <ul class=''list-disc pl-6 space-y-2 text-sm''>
8604
+ <li><strong>Devises illimitées :</strong> Ajoutez chaque code de devise, son symbole et son taux de conversion.</li>
8605
+ <li><strong>Mise à jour automatique :</strong> Actualisez les taux chaque jour avec Frankfurter ou votre URL privée.</li>
8606
+ <li><strong>Arrondis des prix :</strong> Arrondissez vers le haut, vers le bas ou avec des prix comme <code>9,99</code>.</li>
8607
+ <li><strong>Synchronisation du catalogue :</strong> Convertissez les prix dès que les devises changent.</li>
8608
+ <li><strong>Changement de devise socle :</strong> Changez la monnaie par défaut avec recalcul complet.</li>
8609
+ <li><strong>Prix personnalisés :</strong> Fixez des prix précis pour chaque pays si nécessaire.</li>
8610
+ </ul>
8611
+
8612
+ <h2>Taxes automatiques</h2>
8613
+ <p>Vous pouvez régler vos taux à la main ou laisser Stripe Tax faire les calculs :</p>
8614
+ <div class=''grid md:grid-cols-2 gap-6 my-6''>
8615
+ <div class=''p-6 rounded-2xl border border-slate-200 dark:border-white/10 bg-slate-50 dark:bg-white/5''>
8616
+ <h3 class=''font-bold text-slate-900 dark:text-white mb-2''>Mode manuel</h3>
8617
+ <p class=''text-sm text-slate-600 dark:text-slate-400''>Réglez les taux par pays et province. Les taxes cumulées comme la TPS et la TVQ sont gérées. Chaque ligne est enregistrée sur la commande.</p>
8618
+ </div>
8619
+ <div class=''p-6 rounded-2xl border border-slate-200 dark:border-white/10 bg-slate-50 dark:bg-white/5''>
8620
+ <h3 class=''font-bold text-slate-900 dark:text-white mb-2''>Mode automatique</h3>
8621
+ <p class=''text-sm text-slate-600 dark:text-slate-400''>Stripe Tax calcule les montants finaux lors de l''achat. Les codes fiscaux suivent les articles, et les webhooks confirment les chiffres.</p>
8622
+ </div>
8623
+ </div>
8624
+
8625
+ <h2>Livraison et checkout</h2>
8626
+ <p>Les zones de livraison se basent sur le pays et la région. Elles acceptent des libellés traduits, des tarifs par devise et la gratuité dès un certain montant. Un tarif de secours évite les blocages.</p>
8627
+ <p>Le tunnel d''achat s''adapte à chaque passerelle de paiement :</p>
8628
+ <ul class=''list-disc pl-6 space-y-2 text-sm''>
8629
+ <li><strong>Stripe :</strong> Gère les produits physiques, les stocks, la livraison, les taxes et les sessions Checkout.</li>
8630
+ <li><strong>Freemius :</strong> Gère les licences de logiciels, les formules et les pages de paiement sécurisées.</li>
8631
+ <li>Les articles restent séparés par fournisseur pour garder un parcours d''achat très simple.</li>
8632
+ </ul>
8633
+
8634
+ <figure class=''my-12 overflow-hidden rounded-[2rem] border border-slate-200/80 bg-slate-950 shadow-2xl dark:border-white/10''>
8635
+ <img src=''/images/commerce-plan.webp'' alt=''Plan de développement de la boutique NextBlock illustrant les futures capacités e-commerce'' class=''w-full h-auto object-cover'' />
8636
+ <figcaption class=''border-t border-white/10 px-6 py-4 text-sm text-slate-300''>Le commerce est le premier module officiel de notre feuille de route. Il s''intègre au cœur du CMS.</figcaption>
8637
+ </figure>
8638
+
8639
+ <h2>Inventaire, commandes et factures</h2>
8640
+ <p>Quand le suivi de stock est actif, le panier vérifie les quantités avant paiement. Après paiement, les stocks diminuent aussitôt dans la base de données.</p>
8641
+ <ul class=''list-disc pl-6 space-y-2 text-sm''>
8642
+ <li>Le statut passe simplement de panier en attente à payé puis expédié.</li>
8643
+ <li>Les numéros de facture sont créés par des fonctions sûres en base.</li>
8644
+ <li>Les factures à imprimer reprennent les couleurs de votre marque.</li>
8645
+ <li>Vos clients peuvent consulter l''historique de leurs commandes à tout moment.</li>
8646
+ </ul>
8647
+
8648
+ <h2>Surfaces commerce dans le CMS</h2>
8649
+ <p>Quand le module de vente est activé, le CMS affiche de nouveaux écrans. Vous profitez de la liste des articles, du suivi des stocks, des commandes, de la livraison, des taxes et des devises. Ces pages reprennent le design habituel du CMS pour ne pas dépayser votre équipe.</p>
8650
+ '::text)),
8651
+ updated_at = now()
8652
+ WHERE post_id = 6
8653
+ AND content->>'html_content' LIKE '%NextBlock™ Commerce est le premier module premium de l''ecosysteme%';
8654
+
8655
+ -- Post 7: Cortex AI EN
8656
+ UPDATE public.blocks
8657
+ SET content = jsonb_set(content, '{html_content}', to_jsonb('
8658
+ <p class=''text-lg leading-8 text-slate-700 dark:text-slate-300''>NextBlock Cortex AI is the smart content tool built for modern web pages. It understands page blocks, section layouts, and editorial rules so you can create better content faster.</p>
8659
+
8660
+ <div class=''grid gap-4 md:grid-cols-3 my-10''>
8661
+ <div class=''rounded-3xl border border-violet-200/70 bg-violet-50/80 p-6 dark:border-violet-500/20 dark:bg-violet-500/10''>
8662
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200''>Model routing</p>
8663
+ <h2 class=''mt-3 text-xl font-semibold text-slate-900 dark:text-white''>Pick the right model</h2>
8664
+ <p class=''mt-3 text-sm text-slate-600 dark:text-slate-300''>Route your prompts through OpenRouter or your own provider to balance speed and price.</p>
8665
+ </div>
8666
+ <div class=''rounded-3xl border border-sky-200/70 bg-sky-50/80 p-6 dark:border-sky-500/20 dark:bg-sky-500/10''>
8667
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-sky-700 dark:text-sky-200''>BYOK control</p>
8668
+ <h2 class=''mt-3 text-xl font-semibold text-slate-900 dark:text-white''>Use your own keys</h2>
8669
+ <p class=''mt-3 text-sm text-slate-600 dark:text-slate-300''>Keep provider keys safe on your server while giving editors a simple AI writing screen.</p>
8670
+ </div>
8671
+ <div class=''rounded-3xl border border-emerald-200/70 bg-emerald-50/80 p-6 dark:border-emerald-500/20 dark:bg-emerald-500/10''>
8672
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200''>Typed output</p>
8673
+ <h2 class=''mt-3 text-xl font-semibold text-slate-900 dark:text-white''>Generate valid blocks</h2>
8674
+ <p class=''mt-3 text-sm text-slate-600 dark:text-slate-300''>Typed schemas ensure AI content drops straight into your pages as clean, working blocks.</p>
8675
+ </div>
8676
+ </div>
8677
+
8678
+ <h2>Why Cortex AI Belongs Inside the Editor</h2>
8679
+ <p>Generic chat tools can draft text, but they do not know the difference between a hero banner, a card grid, and a blog post. Cortex AI lives right inside your editing screen. It creates content that fits the blocks on your live site.</p>
8680
+ <p>This makes AI truly useful for everyday work. You can draft a new landing section, polish a summary, expand product copy, or translate a full article with ease.</p>
8681
+
8682
+ <div class=''rounded-[2rem] border border-slate-200/80 bg-slate-50/90 p-6 my-10 dark:border-white/10 dark:bg-slate-900/70''>
8683
+ <p class=''text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200''>Editorial workflow</p>
8684
+ <div class=''grid gap-5 md:grid-cols-2 mt-5''>
8685
+ <div class=''rounded-2xl border border-slate-200 bg-white p-5 dark:border-white/10 dark:bg-slate-950/50''>
8686
+ <h3 class=''mt-0 text-xl text-slate-900 dark:text-white''>Faster first drafts</h3>
8687
+ <p class=''text-sm text-slate-600 dark:text-slate-300''>Start with a prompt and get a section, article draft, or product story that matches your tone.</p>
8688
+ </div>
8689
+ <div class=''rounded-2xl border border-slate-200 bg-white p-5 dark:border-white/10 dark:bg-slate-950/50''>
8690
+ <h3 class=''mt-0 text-xl text-slate-900 dark:text-white''>Cleaner revisions</h3>
8691
+ <p class=''text-sm text-slate-600 dark:text-slate-300''>Ask for shorter, clearer, or translated text without leaving your edit screen.</p>
8692
+ </div>
8693
+ </div>
8694
+ </div>
8695
+
8696
+ <h2>Model Routing and Cost Control</h2>
8697
+ <p>Cortex AI gives you full control over your models. You can pick fast models for quick drafts and stronger models for technical articles. You manage your API keys on the server, so your writers can focus on good content.</p>
8698
+ <ul class=''list-disc pl-6 space-y-2 text-sm''>
8699
+ <li>Use quick models for rewrites, titles, and summaries.</li>
8700
+ <li>Use top models for long guides and difficult translations.</li>
8701
+ <li>Keep provider keys safe in your private server settings.</li>
8702
+ <li>Control costs without changing how pages display to visitors.</li>
8703
+ </ul>
8704
+
8705
+ <h2>Block-Aware Generation</h2>
8706
+ <p>Cortex AI does more than write plain text. It creates structured content that maps directly to NextBlock components. You get ready-to-use section copy, headings, buttons, and translated blocks. You spend less time fixing messy copy from external tools.</p>
8707
+ <p>Because the generated content respects your block rules, everything looks consistent and runs fast on the web.</p>
8708
+
8709
+ <h2>Safer Team Workflows</h2>
8710
+ <p>AI works best when humans stay in control. With Cortex AI, editors review every draft before publishing. Developers manage the model keys, and the CMS keeps all versions in your normal history log.</p>
8711
+
8712
+ <h2>A Practical Launch Flow</h2>
8713
+ <ol class=''list-decimal pl-6 space-y-2 text-sm''>
8714
+ <li>Draft an article, landing section, or product story from a clear prompt.</li>
8715
+ <li>Refine the text to match your audience and brand tone.</li>
8716
+ <li>Create a translated version or shorter summary for social cards and search tags.</li>
8717
+ <li>Review the content in the editor, hit publish, and track your revisions over time.</li>
8718
+ </ol>
8719
+
8720
+ <p>Cortex AI turns your CMS into a faster creative workshop. It does not replace human taste, but it helps you turn great ideas into finished pages in record time.</p>
8721
+ '::text)),
8722
+ updated_at = now()
8723
+ WHERE post_id = 7
8724
+ AND content->>'html_content' LIKE '%NextBlock Cortex AI is the AI layer built%';
8725
+
8726
+ -----------------------------------------------------------------------------
8727
+ -- 4. Page Block Content Optimizations (Content-Guarded)
8728
+ -----------------------------------------------------------------------------
8729
+
8730
+ -- Page 1 Block Updates
8731
+ UPDATE public.blocks
8732
+ SET content = replace(content::text, 'Edge-rendered marketing sites, launches, and docs with uncompromising performance.', 'Fast edge-rendered sites, launches, and docs. Built for top speed and clean code.')::jsonb,
8733
+ updated_at = now()
8734
+ WHERE page_id = 1
8735
+ AND content::text LIKE '%' || 'Edge-rendered marketing sites, launches,' || '%';
8736
+
8737
+ UPDATE public.blocks
8738
+ SET content = replace(content::text, 'NextBlock™ is the open-source, developer-first Next.js CMS that merges 100% Lighthouse scores with a powerful visual block editor.', 'NextBlock™ is the open-source Next.js CMS that pairs 100% Lighthouse scores with a visual block editor.')::jsonb,
8739
+ updated_at = now()
8740
+ WHERE page_id = 1
8741
+ AND content::text LIKE '%' || 'NextBlock™ is the open-source, developer' || '%';
8742
+
8743
+ UPDATE public.blocks
8744
+ SET content = replace(content::text, 'NextBlock™ is a holistic platform that unites performance, editorial experience, and developer control so every stakeholder delivers their best work.', 'NextBlock™ brings speed, clear editing, and developer control together so your team can build better web pages.')::jsonb,
8745
+ updated_at = now()
8746
+ WHERE page_id = 1
8747
+ AND content::text LIKE '%' || 'NextBlock™ is a holistic platform that u' || '%';
8748
+
8749
+ UPDATE public.blocks
8750
+ SET content = replace(content::text, 'Built for 100% Lighthouse scores with global delivery and near-instant FCP.', 'Built for top Lighthouse scores, quick page loads, and fast global delivery.')::jsonb,
8751
+ updated_at = now()
8752
+ WHERE page_id = 1
8753
+ AND content::text LIKE '%' || 'Built for 100% Lighthouse scores with gl' || '%';
8754
+
8755
+ UPDATE public.blocks
8756
+ SET content = replace(content::text, 'A low-code, Notion-style block editor empowers teams to ship pages without engineering help.', 'A clean block editor gives your team the power to create pages without writing code.')::jsonb,
8757
+ updated_at = now()
8758
+ WHERE page_id = 1
8759
+ AND content::text LIKE '%' || 'A low-code, Notion-style block editor em' || '%';
8760
+
8761
+ UPDATE public.blocks
8762
+ SET content = replace(content::text, 'Open-source control with a clean Nx monorepo and a typed SDK for limitless customization.', 'Full open-source control with a clean monorepo and typed tools to build custom blocks with ease.')::jsonb,
8763
+ updated_at = now()
8764
+ WHERE page_id = 1
8765
+ AND content::text LIKE '%' || 'Open-source control with a clean Nx mono' || '%';
8766
+
8767
+ UPDATE public.blocks
8768
+ SET content = replace(content::text, 'Every layer of NextBlock™ leans on proven developer-first technology so the platform feels familiar, performant, and trustworthy from day one.', 'NextBlock™ uses tools you already know and trust, so your site stays fast, safe, and easy to run.')::jsonb,
8769
+ updated_at = now()
8770
+ WHERE page_id = 1
8771
+ AND content::text LIKE '%' || 'Every layer of NextBlock™ leans on prove' || '%';
8772
+
8773
+ UPDATE public.blocks
8774
+ SET content = replace(content::text, 'For Content Creators', 'For Writers and Editors')::jsonb,
8775
+ updated_at = now()
8776
+ WHERE page_id = 1
8777
+ AND content::text LIKE '%' || 'For Content Creators' || '%';
8778
+
8779
+ UPDATE public.blocks
8780
+ SET content = replace(content::text, 'Drag-and-drop layouts with a Notion-like interface.', 'Drag and drop blocks in a clean, simple layout.')::jsonb,
8781
+ updated_at = now()
8782
+ WHERE page_id = 1
8783
+ AND content::text LIKE '%' || 'Drag-and-drop layouts with a Notion-like' || '%';
8784
+
8785
+ UPDATE public.blocks
8786
+ SET content = replace(content::text, 'Pre-built hero, feature, testimonial, and callout components.', 'Add heroes, galleries, and quotes with one click.')::jsonb,
8787
+ updated_at = now()
8788
+ WHERE page_id = 1
8789
+ AND content::text LIKE '%' || 'Pre-built hero, feature, testimonial, an' || '%';
8790
+
8791
+ UPDATE public.blocks
8792
+ SET content = replace(content::text, 'Drag-and-drop assets with folders, search, and alt text.', 'Keep your images organized with folders and tags.')::jsonb,
8793
+ updated_at = now()
8794
+ WHERE page_id = 1
8795
+ AND content::text LIKE '%' || 'Drag-and-drop assets with folders, searc' || '%';
8796
+
8797
+ UPDATE public.blocks
8798
+ SET content = replace(content::text, 'Audit trail with one-click restore for every change.', 'Restore any saved version with a single click.')::jsonb,
8799
+ updated_at = now()
8800
+ WHERE page_id = 1
8801
+ AND content::text LIKE '%' || 'Audit trail with one-click restore for e' || '%';
8802
+
8803
+ UPDATE public.blocks
8804
+ SET content = replace(content::text, 'Server Components, ISR, and Edge Functions ready out of the box.', 'Built with Server Components and fast edge caching.')::jsonb,
8805
+ updated_at = now()
8806
+ WHERE page_id = 1
8807
+ AND content::text LIKE '%' || 'Server Components, ISR, and Edge Functio' || '%';
8808
+
8809
+ UPDATE public.blocks
8810
+ SET content = replace(content::text, 'Postgres, Auth, Storage, and Row-Level Security fully wired.', 'Postgres database, user auth, and file storage ready to use.')::jsonb,
8811
+ updated_at = now()
8812
+ WHERE page_id = 1
8813
+ AND content::text LIKE '%' || 'Postgres, Auth, Storage, and Row-Level S' || '%';
8814
+
8815
+ UPDATE public.blocks
8816
+ SET content = replace(content::text, 'Nx-powered monorepo engineered for scale and clean separation.', 'An Nx workspace made for scale and clean code.')::jsonb,
8817
+ updated_at = now()
8818
+ WHERE page_id = 1
8819
+ AND content::text LIKE '%' || 'Nx-powered monorepo engineered for scale' || '%';
8820
+
8821
+ UPDATE public.blocks
8822
+ SET content = replace(content::text, 'TypeScript SDK with Zod validation for building custom blocks.', 'Build and type new blocks in minutes.')::jsonb,
8823
+ updated_at = now()
8824
+ WHERE page_id = 1
8825
+ AND content::text LIKE '%' || 'TypeScript SDK with Zod validation for b' || '%';
8826
+
8827
+ UPDATE public.blocks
8828
+ SET content = replace(content::text, 'NextBlock™ Commerce transforms your content platform into a complete e-commerce engine. Products, checkout, multi-currency, taxes, shipping, invoices — all natively integrated into the block editor you already know.', 'NextBlock™ Commerce turns your content site into a full online store. Sell products, take payments, handle taxes, and ship orders — all from the block editor you already use.')::jsonb,
8829
+ updated_at = now()
8830
+ WHERE page_id = 1
8831
+ AND content::text LIKE '%' || 'NextBlock™ Commerce transforms your cont' || '%';
8832
+
8833
+ UPDATE public.blocks
8834
+ SET content = replace(content::text, 'NextBlock™ Commerce transforms your content platform into a complete e-commerce engine. Products, checkout, multi-currency, taxes, shipping, invoices — all natively integrated into the block editor you already know.', 'NextBlock™ Commerce turns your content site into a full online store. Sell products, take payments, handle taxes, and ship orders — all from the block editor you already use.')::jsonb,
8835
+ updated_at = now()
8836
+ WHERE page_id = 1
8837
+ AND content::text LIKE '%' || 'NextBlock™ Commerce transforms your cont' || '%';
8838
+
8839
+ UPDATE public.blocks
8840
+ SET content = replace(content::text, 'NextBlock™ Commerce ships a complete e-commerce toolkit so you can go from catalog to checkout without third-party plugins.', 'NextBlock™ Commerce ships a complete online store toolkit so you can go from catalog to checkout with ease.')::jsonb,
8841
+ updated_at = now()
8842
+ WHERE page_id = 1
8843
+ AND content::text LIKE '%' || 'NextBlock™ Commerce ships a complete e-c' || '%';
8844
+
8845
+ UPDATE public.blocks
8846
+ SET content = replace(content::text, 'Live FX rates, rounding rules, and auto-sync across all currencies.', 'Live exchange rates, round prices, and auto-sync across all currencies.')::jsonb,
8847
+ updated_at = now()
8848
+ WHERE page_id = 1
8849
+ AND content::text LIKE '%' || 'Live FX rates, rounding rules, and auto-' || '%';
8850
+
8851
+ UPDATE public.blocks
8852
+ SET content = replace(content::text, 'Define custom rates or let Stripe Tax handle calculations automatically.', 'Set custom tax rates or let Stripe Tax calculate totals automatically.')::jsonb,
8853
+ updated_at = now()
8854
+ WHERE page_id = 1
8855
+ AND content::text LIKE '%' || 'Define custom rates or let Stripe Tax ha' || '%';
8856
+
8857
+ UPDATE public.blocks
8858
+ SET content = replace(content::text, 'Country and state-level zones with free shipping thresholds.', 'Set shipping rates by country and state, with free shipping rules.')::jsonb,
8859
+ updated_at = now()
8860
+ WHERE page_id = 1
8861
+ AND content::text LIKE '%' || 'Country and state-level zones with free ' || '%';
8862
+
8863
+ UPDATE public.blocks
8864
+ SET content = replace(content::text, 'Stripe for physical goods and Freemius for software licenses with seamless checkout.', 'Use Stripe for physical goods and Freemius for software licenses with simple checkout.')::jsonb,
8865
+ updated_at = now()
8866
+ WHERE page_id = 1
8867
+ AND content::text LIKE '%' || 'Stripe for physical goods and Freemius f' || '%';
8868
+
8869
+ UPDATE public.blocks
8870
+ SET content = replace(content::text, 'Automatic stock decrement on payment with variant-level tracking.', 'Update stock counts when an order is paid, with variant tracking.')::jsonb,
8871
+ updated_at = now()
8872
+ WHERE page_id = 1
8873
+ AND content::text LIKE '%' || 'Automatic stock decrement on payment wit' || '%';
8874
+
8875
+ UPDATE public.blocks
8876
+ SET content = replace(content::text, 'Order management, printable invoices, and customer receipts out of the box.', 'Manage orders, print invoices, and view customer reports with ease.')::jsonb,
8877
+ updated_at = now()
8878
+ WHERE page_id = 1
8879
+ AND content::text LIKE '%' || 'Order management, printable invoices, an' || '%';
8880
+
8881
+ UPDATE public.blocks
8882
+ SET content = replace(content::text, 'NextBlock™ Cortex AI brings native block-level intelligence directly to your editor. Generate copy, refactor structures, and automate translations in one click, built directly on our high-performance architecture.', 'NextBlock™ Cortex AI helps you write, edit, and translate content right inside the block editor. Draft text, refine layouts, and switch languages with ease.')::jsonb,
8883
+ updated_at = now()
8884
+ WHERE page_id = 1
8885
+ AND content::text LIKE '%' || 'NextBlock™ Cortex AI brings native block' || '%';
8886
+
8887
+ UPDATE public.blocks
8888
+ SET content = replace(content::text, 'NextBlock™ is building a sustainable open-core roadmap so the platform grows with your business.', 'NextBlock™ is built to grow with your business and help your team succeed.')::jsonb,
8889
+ updated_at = now()
8890
+ WHERE page_id = 1
8891
+ AND content::text LIKE '%' || 'NextBlock™ is building a sustainable ope' || '%';
8892
+
8893
+
8894
+ -- Page 2 Block Updates
8895
+ UPDATE public.blocks
8896
+ SET content = replace(content::text, 'NextBlock™ est le CMS Next.js open-source alliant scores Lighthouse parfaits et éditeur visuel puissant.', 'NextBlock™ est le CMS Next.js open-source alliant scores parfaits et éditeur de blocs visuel.')::jsonb,
8897
+ updated_at = now()
8898
+ WHERE page_id = 2
8899
+ AND content::text LIKE '%' || 'NextBlock™ est le CMS Next.js open-sourc' || '%';
8900
+
8901
+ UPDATE public.blocks
8902
+ SET content = replace(content::text, 'Sites marketing et docs rendus à l''edge avec des performances irréprochables.', 'Sites marketing et docs rendus à l''edge. Conçus pour la vitesse et un code propre.')::jsonb,
8903
+ updated_at = now()
8904
+ WHERE page_id = 2
8905
+ AND content::text LIKE '%' || 'Sites marketing et docs rendus à l''edge ' || '%';
8906
+
8907
+ UPDATE public.blocks
8908
+ SET content = replace(content::text, 'NextBlock™ unifie performances, expérience éditoriale et contrôle développeur pour que chaque équipe livre son meilleur travail.', 'NextBlock™ réunit la vitesse, la clarté d''édition et le contrôle développeur. Votre équipe peut ainsi créer de meilleures pages web.')::jsonb,
8909
+ updated_at = now()
8910
+ WHERE page_id = 2
8911
+ AND content::text LIKE '%' || 'NextBlock™ unifie performances, expérien' || '%';
8912
+
8913
+ UPDATE public.blocks
8914
+ SET content = replace(content::text, 'Pensé pour des scores Lighthouse parfaits avec une diffusion mondiale.', 'Conçu pour des scores élevés et une diffusion rapide.')::jsonb,
8915
+ updated_at = now()
8916
+ WHERE page_id = 2
8917
+ AND content::text LIKE '%' || 'Pensé pour des scores Lighthouse parfait' || '%';
8918
+
8919
+ UPDATE public.blocks
8920
+ SET content = replace(content::text, 'Un éditeur façon Notion pour publier sans dépendre des développeurs.', 'Un éditeur simple pour publier sans coder.')::jsonb,
8921
+ updated_at = now()
8922
+ WHERE page_id = 2
8923
+ AND content::text LIKE '%' || 'Un éditeur façon Notion pour publier san' || '%';
8924
+
8925
+ UPDATE public.blocks
8926
+ SET content = replace(content::text, 'Un socle Next.js + Supabase modulaire, extensible et auto-hébergeable.', 'Un socle moderne, souple et très simple à faire grandir.')::jsonb,
8927
+ updated_at = now()
8928
+ WHERE page_id = 2
8929
+ AND content::text LIKE '%' || 'Un socle Next.js + Supabase modulaire, e' || '%';
8930
+
8931
+ UPDATE public.blocks
8932
+ SET content = replace(content::text, 'Chaque couche de NextBlock™ repose sur des technologies éprouvées pour une expérience familière et performante.', 'NextBlock™ s''appuie sur des outils fiables et éprouvés. Votre site reste rapide, robuste et facile à maintenir au quotidien.')::jsonb,
8933
+ updated_at = now()
8934
+ WHERE page_id = 2
8935
+ AND content::text LIKE '%' || 'Chaque couche de NextBlock™ repose sur d' || '%';
8936
+
8937
+ UPDATE public.blocks
8938
+ SET content = replace(content::text, 'Glisser-déposer façon Notion.', 'Glissez et déposez vos blocs dans une mise en page claire.')::jsonb,
8939
+ updated_at = now()
8940
+ WHERE page_id = 2
8941
+ AND content::text LIKE '%' || 'Glisser-déposer façon Notion.' || '%';
8942
+
8943
+ UPDATE public.blocks
8944
+ SET content = replace(content::text, 'Héros, galeries, témoignages.', 'Insérez des héros, des galeries et des avis clients en un clic.')::jsonb,
8945
+ updated_at = now()
8946
+ WHERE page_id = 2
8947
+ AND content::text LIKE '%' || 'Héros, galeries, témoignages.' || '%';
8948
+
8949
+ UPDATE public.blocks
8950
+ SET content = replace(content::text, 'Dossiers, tags et actions groupées.', 'Rangez vos photos et médias avec des dossiers et des tags.')::jsonb,
8951
+ updated_at = now()
8952
+ WHERE page_id = 2
8953
+ AND content::text LIKE '%' || 'Dossiers, tags et actions groupées.' || '%';
8954
+
8955
+ UPDATE public.blocks
8956
+ SET content = replace(content::text, 'Historique et restauration instantanée.', 'Retrouvez et restaurez vos versions précédentes sans stress.')::jsonb,
8957
+ updated_at = now()
8958
+ WHERE page_id = 2
8959
+ AND content::text LIKE '%' || 'Historique et restauration instantanée.' || '%';
8960
+
8961
+ UPDATE public.blocks
8962
+ SET content = replace(content::text, 'Server Components, ISR et Edge prêts à l''emploi.', 'Conçu avec Server Components et un cache edge très rapide.')::jsonb,
8963
+ updated_at = now()
8964
+ WHERE page_id = 2
8965
+ AND content::text LIKE '%' || 'Server Components, ISR et Edge prêts à l' || '%';
8966
+
8967
+ UPDATE public.blocks
8968
+ SET content = replace(content::text, 'Postgres, auth, stockage, temps réel.', 'Base Postgres, profils, auth et stockage de fichiers prêts à l''emploi.')::jsonb,
8969
+ updated_at = now()
8970
+ WHERE page_id = 2
8971
+ AND content::text LIKE '%' || 'Postgres, auth, stockage, temps réel.' || '%';
8972
+
8973
+ UPDATE public.blocks
8974
+ SET content = replace(content::text, 'Dépendances lisibles et centrales.', 'Une structure claire et bien rangée faite pour grandir sereinement.')::jsonb,
8975
+ updated_at = now()
8976
+ WHERE page_id = 2
8977
+ AND content::text LIKE '%' || 'Dépendances lisibles et centrales.' || '%';
8978
+
8979
+ UPDATE public.blocks
8980
+ SET content = replace(content::text, 'Widgets typés et extensibles.', 'Créez et typez vos nouveaux composants en un instant.')::jsonb,
8981
+ updated_at = now()
8982
+ WHERE page_id = 2
8983
+ AND content::text LIKE '%' || 'Widgets typés et extensibles.' || '%';
8984
+
8985
+ UPDATE public.blocks
8986
+ SET content = replace(content::text, 'NextBlock™ Commerce transforme votre plateforme de contenu en moteur e-commerce complet. Produits, checkout, multi-devises, taxes, expédition, factures — le tout intégré nativement dans l''éditeur de blocs que vous connaissez déjà.', 'NextBlock™ Commerce transforme votre site de contenu en vraie boutique en ligne. Vendez des articles et recevez des paiements en ligne. Gérez vos taxes et vos envois dans l''éditeur que vous connaissez déjà.')::jsonb,
8987
+ updated_at = now()
8988
+ WHERE page_id = 2
8989
+ AND content::text LIKE '%' || 'NextBlock™ Commerce transforme votre pla' || '%';
8990
+
8991
+ UPDATE public.blocks
8992
+ SET content = replace(content::text, 'NextBlock™ Commerce livre une boîte à outils e-commerce complète pour aller du catalogue au paiement sans plugins tiers.', 'NextBlock™ Commerce propose une boîte à outils complète. Allez du catalogue au paiement sans aucun plugin externe.')::jsonb,
8993
+ updated_at = now()
8994
+ WHERE page_id = 2
8995
+ AND content::text LIKE '%' || 'NextBlock™ Commerce livre une boîte à ou' || '%';
8996
+
8997
+ UPDATE public.blocks
8998
+ SET content = replace(content::text, 'Taux de change en temps réel, modes d''arrondi, prix charme et synchronisation automatique sur toutes les devises.', 'Taux de change en direct, prix ronds et mise à jour automatique sur toutes les devises.')::jsonb,
8999
+ updated_at = now()
9000
+ WHERE page_id = 2
9001
+ AND content::text LIKE '%' || 'Taux de change en temps réel, modes d''ar' || '%';
9002
+
9003
+ UPDATE public.blocks
9004
+ SET content = replace(content::text, 'Taux manuels empilés (TPS + TVQ) ou calcul automatique via Stripe Tax — à vous de choisir.', 'Définissez vos taxes ou laissez Stripe Tax calculer les montants finaux.')::jsonb,
9005
+ updated_at = now()
9006
+ WHERE page_id = 2
9007
+ AND content::text LIKE '%' || 'Taux manuels empilés (TPS + TVQ) ou calc' || '%';
9008
+
9009
+ UPDATE public.blocks
9010
+ SET content = replace(content::text, 'Résolution par pays et état, tarification par devise et seuils de livraison gratuite.', 'Ajustez les frais de port par pays et état avec des règles d''envoi gratuit.')::jsonb,
9011
+ updated_at = now()
9012
+ WHERE page_id = 2
9013
+ AND content::text LIKE '%' || 'Résolution par pays et état, tarificatio' || '%';
9014
+
9015
+ UPDATE public.blocks
9016
+ SET content = replace(content::text, 'Stripe pour les produits physiques, Freemius pour les licences numériques — checkout intelligent avec validation d''inventaire.', 'Paiement Stripe pour les biens et Freemius pour les licences logicielles.')::jsonb,
9017
+ updated_at = now()
9018
+ WHERE page_id = 2
9019
+ AND content::text LIKE '%' || 'Stripe pour les produits physiques, Free' || '%';
9020
+
9021
+ UPDATE public.blocks
9022
+ SET content = replace(content::text, 'Déduction automatique des quantités au paiement avec gestion des stocks par variante.', 'Mettez à jour les stocks dès qu''un achat est validé, avec suivi des variantes.')::jsonb,
9023
+ updated_at = now()
9024
+ WHERE page_id = 2
9025
+ AND content::text LIKE '%' || 'Déduction automatique des quantités au p' || '%';
9026
+
9027
+ UPDATE public.blocks
9028
+ SET content = replace(content::text, 'Gestion du cycle de vie des commandes, numérotation stable des factures et rapports de commandes exportables.', 'Suivez chaque commande, imprimez des factures et téléchargez vos bilans en toute simplicité.')::jsonb,
9029
+ updated_at = now()
9030
+ WHERE page_id = 2
9031
+ AND content::text LIKE '%' || 'Gestion du cycle de vie des commandes, n' || '%';
9032
+
9033
+ UPDATE public.blocks
9034
+ SET content = replace(content::text, 'NextBlock™ Cortex AI apporte une intelligence native au niveau des blocs directement dans votre éditeur. Générez du texte, restructurez vos contenus et automatisez les traductions en un clic, le tout propulsé par notre architecture haute performance.', 'NextBlock™ Cortex AI vous aide à rédiger, corriger et traduire vos textes au cœur de l''éditeur de blocs. Créez des ébauches, améliorez vos titres et passez d''une langue à l''autre en un clin d''œil.')::jsonb,
9035
+ updated_at = now()
9036
+ WHERE page_id = 2
9037
+ AND content::text LIKE '%' || 'NextBlock™ Cortex AI apporte une intelli' || '%';
9038
+
9039
+ UPDATE public.blocks
9040
+ SET content = replace(content::text, 'NextBlock™ construit une feuille de route open-core durable qui évolue avec votre activité.', 'NextBlock™ est pensé pour accompagner la croissance de votre entreprise. Nous voulons faire réussir vos projets web.')::jsonb,
9041
+ updated_at = now()
9042
+ WHERE page_id = 2
9043
+ AND content::text LIKE '%' || 'NextBlock™ construit une feuille de rout' || '%';
9044
+
9045
+ UPDATE public.blocks
9046
+ SET content = replace(content::text, 'Le commerce arrive en premier, puis l''ecosysteme s''etend avec des plugins, des blocs et des modules construits par les partenaires.', 'Le commerce ouvre la voie. Notre écosystème grandit avec de nouveaux plugins, des blocs utiles et des modules partenaires.')::jsonb,
9047
+ updated_at = now()
9048
+ WHERE page_id = 2
9049
+ AND content::text LIKE '%' || 'Le commerce arrive en premier, puis l''ec' || '%';
9050
+
9051
+ UPDATE public.blocks
9052
+ SET content = replace(content::text, 'Transformez votre site en vitrine composable avec produits, checkout, tarification multi-devise, taxes automatiques et blocs commerce relies a votre contenu editorial.', 'Ajoutez une boutique complète à côté de vos articles. Profitez de produits, du paiement en ligne, de devises et de taxes sans effort.')::jsonb,
9053
+ updated_at = now()
9054
+ WHERE page_id = 2
9055
+ AND content::text LIKE '%' || 'Transformez votre site en vitrine compos' || '%';
9056
+
9057
+ UPDATE public.blocks
9058
+ SET content = replace(content::text, 'Une marketplace communautaire ouvrira la voie a la publication, la vente et la distribution de blocs, themes, integrations et modules partenaires.', 'Un espace partagé permet aux développeurs de publier et vendre des blocs sur mesure, des thèmes et des outils connectés.')::jsonb,
9059
+ updated_at = now()
9060
+ WHERE page_id = 2
9061
+ AND content::text LIKE '%' || 'Une marketplace communautaire ouvrira la' || '%';
9062
+
9063
+ UPDATE public.blocks
9064
+ SET content = replace(content::text, 'NextBlock™ se construit en public. Ajoutez une étoile, partagez vos retours et façonnez l''avenir du CMS orienté performance.', 'NextBlock™ avance en public. Mettez une étoile sur le dépôt, partagez vos avis et façonnez la suite avec nous.')::jsonb,
9065
+ updated_at = now()
9066
+ WHERE page_id = 2
9067
+ AND content::text LIKE '%' || 'NextBlock™ se construit en public. Ajout' || '%';
9068
+
9069
+
9070
+ -- Page 3 Block Updates
9071
+ UPDATE public.blocks
9072
+ SET content = replace(content::text, '<h2 class=''text-4xl md:text-5xl font-bold text-white text-center md:text-left mb-6''>Deep dives into performance, DX, and visual editing.</h2>', '<h1 class=''text-4xl md:text-5xl font-bold text-white text-center md:text-left mb-6''>The NextBlock Journal: Performance, DX, and Visual Editing</h1>')::jsonb,
9073
+ updated_at = now()
9074
+ WHERE page_id = 3
9075
+ AND content::text LIKE '%' || '<h2 class=''text-4xl md:text-5xl font-bol' || '%';
9076
+
9077
+ UPDATE public.blocks
9078
+ SET content = replace(content::text, '<p class=''text-slate-300 text-lg max-w-xl mx-auto md:mx-0 text-center md:text-left leading-relaxed''>Explore architectural walkthroughs, Supabase recipes, and block editor experiments written by the Nextblock core team.</p>', '<p class=''text-slate-300 text-lg max-w-xl mx-auto md:mx-0 text-center md:text-left leading-relaxed''>Explore practical guides, architecture deep dives, and editor workflows written by the NextBlock team and community.</p> <div class=''mt-8 text-slate-300 space-y-4 max-w-3xl''> <p>Welcome to the NextBlock Journal. This is your home for in-depth technical guides, release notes, and real-world web architecture patterns. Whether you are launching your first Next.js site or scaling an online store, our articles give you clear, tested steps to help you build faster.</p> <p>We believe modern web projects need developer freedom and a simple editing experience. Our engineering posts show how to pair Next.js 16 with Supabase Postgres, edge caching, and server actions without complex glue code. You will learn how to keep your Lighthouse score at 100% while giving teams a rich, block-based writing experience.</p> <p>Here are the key topics we cover across our editorial library:</p> <ul class=''space-y-2 list-disc pl-5''> <li><strong>Getting Started Guides:</strong> Simple setup walkthroughs for one-click Vercel deploys, local Docker environments, and custom cloud stacks.</li> <li><strong>Architecture & Performance:</strong> Deep dives into fast page rendering, clean CSS delivery, image optimization, and safe database migrations.</li> <li><strong>E-Commerce Workflows:</strong> Practical patterns for multi-currency pricing, automated tax sync, stock tracking, and provider checkout flows.</li> <li><strong>AI Content Tools:</strong> How to use Cortex AI to generate structured blocks, manage provider keys, and speed up routine translation work.</li> </ul> <p>Our team updates this collection regularly as we release new core features and modules. We test our code on live sites before publishing. Each post includes full technical explanations and architecture diagrams so you can apply the solutions to your own web stack.</p> <p>Have a topic you want us to cover or want to share your own case study? Join our community on GitHub or reach out to our team anytime. We welcome questions, ideas, and pull requests from all builders. You can subscribe to updates or start reading our latest published articles below.</p> </div>')::jsonb,
9079
+ updated_at = now()
9080
+ WHERE page_id = 3
9081
+ AND content::text LIKE '%' || '<p class=''text-slate-300 text-lg max-w-x' || '%';
9082
+
9083
+
9084
+ -- Page 4 Block Updates
9085
+ UPDATE public.blocks
9086
+ SET content = replace(content::text, '<h2 class=''text-4xl md:text-5xl font-bold text-white text-center md:text-left mb-6''>Plongées dans la performance, l''expérience dev et l''édition visuelle.</h2>', '<h1 class=''text-4xl md:text-5xl font-bold text-white text-center md:text-left mb-6''>Le Journal NextBlock : Performance, Expérience Dev et Édition</h1>')::jsonb,
9087
+ updated_at = now()
9088
+ WHERE page_id = 4
9089
+ AND content::text LIKE '%' || '<h2 class=''text-4xl md:text-5xl font-bol' || '%';
9090
+
9091
+ UPDATE public.blocks
9092
+ SET content = replace(content::text, '<p class=''text-lg max-w-xl mx-auto md:mx-0 text-center md:text-left text-slate-300 leading-relaxed''>Walkthroughs d''architecture, recettes Supabase et expérimentations éditeur écrits par l''équipe Nextblock.</p>', '<p class=''text-lg max-w-xl mx-auto md:mx-0 text-center md:text-left text-slate-300 leading-relaxed''>Retrouvez des guides pratiques, des études d''architecture et des conseils pour éditer vos contenus avec NextBlock.</p> <div class=''mt-8 text-slate-300 space-y-4 max-w-3xl''> <p>Bienvenue sur le Journal NextBlock. Cet espace rassemble nos guides techniques détaillés. Vous y trouverez les nouveautés de chaque version et les meilleures pratiques du web moderne. Vous lancez votre premier site Next.js ? Vous faites grandir une boutique en ligne ? Nos articles vous donnent des étapes simples et vérifiées pour construire plus vite.</p> <p>Nous pensons qu''un bon site web doit offrir toute la liberté aux développeurs. Il doit aussi apporter une vraie simplicité aux équipes éditoriales. Nos articles techniques expliquent comment marier Next.js 16 avec Supabase Postgres, le cache edge et les Server Actions. Tout cela se fait sans code superflu. Vous découvrirez comment maintenir un score Lighthouse parfait. En même temps, votre équipe profite d''un éditeur de blocs visuel et très agréable.</p> <p>Voici les principaux sujets abordés dans notre bibliothèque éditoriale :</p> <ul class=''space-y-2 list-disc pl-5''> <li><strong>Guides de démarrage :</strong> Des tutoriels pas à pas pour déployer sur Vercel en un clic, lancer une pile Docker locale ou installer votre propre cloud.</li> <li><strong>Architecture et performance :</strong> Des explications claires sur le rendu rapide des pages, les styles en ligne, l''optimisation des images et les migrations sûres.</li> <li><strong>Commerce en ligne :</strong> Des conseils concrets pour gérer plusieurs devises, synchroniser les taxes, suivre les stocks et réussir vos paiements.</li> <li><strong>Outils IA pour le contenu :</strong> Comment utiliser Cortex AI pour créer des blocs bien typés, garder le contrôle de vos clés et traduire vos pages en un instant.</li> </ul> <p>Notre équipe enrichit cette collection au fil des mises à jour du projet. Nous testons chaque exemple de code sur des sites réels avant publication. Chaque tutoriel propose des explications complètes pour adapter facilement ces solutions à votre propre projet.</p> <p>Vous avez une idée de sujet ou un retour d''expérience à partager ? Rejoignez notre communauté sur GitHub ou contactez notre équipe. Nous accueillons avec grand plaisir vos questions, vos idées et vos contributions. Parcourez dès maintenant nos derniers articles ci-dessous.</p> </div>')::jsonb,
9093
+ updated_at = now()
9094
+ WHERE page_id = 4
9095
+ AND content::text LIKE '%' || '<p class=''text-lg max-w-xl mx-auto md:mx' || '%';
9096
+
9097
+
9098
+ -- Page 5 Block Updates
9099
+ UPDATE public.blocks
9100
+ SET content = replace(content::text, '<div class=''max-w-2xl mx-auto text-center''><h2 class=''text-2xl font-bold mb-4''>Open Source & Community Driven</h2><p class=''text-slate-600 dark:text-slate-400 mb-6''>NextBlock™ is built in the open. We rely on developers and editors like you to help us define the roadmap. Whether it''s a bug report, a feature request, or just a shoutout, every message helps us move faster.</p></div>', '<div class=''mt-10 text-slate-300 space-y-4 max-w-3xl mx-auto''> <h2 class=''text-2xl font-bold text-white mb-4 text-center''>Open Source & Community Driven</h2> <p>NextBlock™ is built entirely in the open. We work closely with developers, editors, and teams who use the platform every day. Whether you found a bug, want to request a new feature, or need advice on your project setup, our team is here to help you move forward.</p> <p>We read every message sent through this form. Here is what you can expect when reaching out to our team:</p> <ul class=''space-y-2 list-disc pl-5''> <li><strong>Fast Response Times:</strong> Our core maintainers typically review and reply to inquiries within one to two business days.</li> <li><strong>Technical Support:</strong> For public bugs or community questions, our GitHub Discussions and Issues boards offer fast answers from the entire community.</li> <li><strong>Partnership and Modules:</strong> If your team wants to sponsor a roadmap module or build a custom integration, we can schedule a direct call.</li> <li><strong>Security Disclosures:</strong> For responsible disclosure of potential security vulnerabilities, please flag your message as urgent so we can triage it immediately.</li> </ul> <p>Before submitting, please make sure your email address is typed correctly so our team can get back to you. If your question is about a specific code error, including your environment details and reproduction steps helps us find a solution much faster.</p> <p>You can also connect with us directly on GitHub, Discord, or X (formerly Twitter). We host regular community discussions and share sneak peeks of upcoming platform features. If you are building a custom client project with NextBlock, we would love to hear about your experience.</p> <p>We value your time and privacy. We never share your contact information or use your email for marketing without your consent. Send us a message using the form below and we will get back to you shortly.</p> </div>')::jsonb,
9101
+ updated_at = now()
9102
+ WHERE page_id = 5
9103
+ AND content::text LIKE '%' || '<div class=''max-w-2xl mx-auto text-cente' || '%';
9104
+
9105
+
9106
+ -- Page 6 Block Updates
9107
+ UPDATE public.blocks
9108
+ SET content = replace(content::text, '<div class=''max-w-2xl mx-auto text-center''><h2 class=''text-2xl font-bold mb-4''>Open Source & Communautaire</h2><p class=''text-slate-600 dark:text-slate-400 mb-6''>NextBlock™ est construit en public. Nous comptons sur les développeurs et éditeurs comme vous pour définir notre roadmap. Qu''il s''agisse d''un bug, d''une suggestion ou d''un simple salut, chaque message compte.</p></div>', '<div class=''mt-10 text-slate-300 space-y-4 max-w-3xl mx-auto''> <h2 class=''text-2xl font-bold text-white mb-4 text-center''>Open Source & Communautaire</h2> <p>NextBlock™ est construit entièrement en public. Nous travaillons avec des développeurs et des équipes qui utilisent le CMS chaque jour. Vous avez trouvé un bug ? Vous souhaitez suggérer une fonction ? Vous avez besoin d''aide pour votre installation ? Notre équipe est là pour vous guider.</p> <p>Nous lisons attentivement chaque message reçu via ce formulaire. Voici nos engagements pour vous répondre au mieux :</p> <ul class=''space-y-2 list-disc pl-5''> <li><strong>Délais de réponse rapides :</strong> Nos mainteneurs étudient et répondent aux demandes en un ou deux jours ouvrés.</li> <li><strong>Support technique :</strong> Pour toute question publique, nos forums GitHub Discussions et Issues offrent une aide rapide de la communauté.</li> <li><strong>Partenariats et modules :</strong> Votre équipe veut sponsoriser un module ou concevoir une intégration sur mesure ? Nous pouvons planifier un échange direct.</li> <li><strong>Signalements de sécurité :</strong> Pour toute alerte de sécurité, signalez votre message comme prioritaire pour un traitement immédiat.</li> </ul> <p>Avant d''envoyer votre message, vérifiez bien votre adresse email. Notre équipe pourra ainsi vous répondre rapidement. Si votre demande concerne une erreur technique, mentionnez votre environnement et les étapes pour la reproduire. Cela nous aide à trouver une solution efficace.</p> <p>Vous pouvez aussi échanger avec nous sur GitHub, Discord ou X. Nous y partageons des nouvelles et les coulisses des prochaines versions. Vous développez un projet client avec NextBlock ? Racontez-nous votre aventure. Notre équipe aime voir ce que vous créez au quotidien. Chaque projet est unique. Prenez le temps de nous dire ce qui vous plaît et ce qui vous manque. Vos retours nous aident à faire un meilleur outil pour tout le monde.</p> <p>Nous respectons votre vie privée. Vos coordonnées ne sont jamais cédées ni réutilisées sans votre accord. Écrivez-nous ci-dessous et nous vous répondrons très vite.</p> </div>')::jsonb,
9109
+ updated_at = now()
9110
+ WHERE page_id = 6
9111
+ AND content::text LIKE '%' || '<div class=''max-w-2xl mx-auto text-cente' || '%';
9112
+
9113
+
9114
+ -- Page 7 Block Updates
9115
+ UPDATE public.blocks
9116
+ SET content = replace(content::text, '<p style="text-align: center; color: var(--background); opacity: 0.9">Discover our premium selection of developer tools and digital commerce solutions.</p>', '<p style="text-align: center; color: var(--background); opacity: 0.9">Discover our selection of official commercial add-ons and developer tools for NextBlock CMS.</p> <div class=''mt-8 text-slate-300 space-y-4 max-w-3xl mx-auto text-left''> <h2 class=''text-2xl font-bold text-white mb-4''>Power Up Your Web Projects</h2> <p>Welcome to the official NextBlock™ digital store. Here you can purchase licenses for our premium packages, including NextBlock™ Commerce and NextBlock™ Cortex AI. Every commercial license helps fund full-time open-source development on our core CMS while giving your team advanced tools to launch high-performance websites faster.</p> <p>Our premium modules are designed to feel native from day one. You get clean code that fits right into your existing NextBlock project without third-party plugins or complex configuration. When you purchase a license from our store, you receive instant access to everything you need:</p> <ul class=''space-y-2 list-disc pl-5''> <li><strong>Full Source Code:</strong> Inspect, customize, and adapt the modules to your exact requirements.</li> <li><strong>Perpetual Use:</strong> Use the software for your project with full peace of mind.</li> <li><strong>Automated Updates:</strong> Enjoy smooth updates that match each new release of NextBlock and Next.js.</li> <li><strong>Secure Checkout:</strong> Payments are processed safely with Stripe and Freemius with instant receipt generation.</li> </ul> <p>Whether you need multi-currency store features, automated sales tax calculations, or AI block generation in your editor, our modules deliver tested solutions that keep your Lighthouse scores at 100%.</p> <p>All purchases include dedicated onboarding resources, detailed developer docs, and friendly technical support. If you ever run into an issue or need help wiring up a provider webhook, our core engineers are ready to assist you. We also offer a thirty-day refund policy so you can try our tools risk-free.</p> <p>Have questions about license tiers, volume pricing, team seats, or custom agency usage? Contact our support team anytime. Our team is here to answer your questions and help your developers succeed. We are happy to help you pick the best plan for your company. Browse our featured products below to get started today.</p> </div>')::jsonb,
9117
+ updated_at = now()
9118
+ WHERE page_id = 7
9119
+ AND content::text LIKE '%' || '<p style="text-align: center; color: var' || '%';
9120
+
9121
+
9122
+ -- Page 8 Block Updates
9123
+ UPDATE public.blocks
9124
+ SET content = replace(content::text, '<p style="text-align: center; color: var(--background); opacity: 0.9">Decouvrez notre selection premium d outils de developpement.</p>', '<p style="text-align: center; color: var(--background); opacity: 0.9">Découvrez nos extensions officielles et nos outils pour développeurs conçus pour le CMS NextBlock.</p> <div class=''mt-8 text-slate-300 space-y-4 max-w-3xl mx-auto text-left''> <h2 class=''text-2xl font-bold text-white mb-4''>Accélérez vos projets web</h2> <p>Bienvenue sur la boutique officielle de NextBlock™. Vous pouvez acheter ici des licences pour nos modules professionnels, comme NextBlock™ Commerce et NextBlock™ Cortex AI. Chaque achat aide à financer le travail open-source sur le cœur du CMS. Il donne aussi à votre équipe des outils de pointe pour créer des sites rapides et fiables.</p> <p>Nos modules premium s''intègrent sans effort à votre projet existant. Vous profitez d''un code propre et bien testé, sans plugin externe lourd ni réglage complexe. En choisissant nos outils, vous profitez immédiatement de nombreux avantages :</p> <ul class=''space-y-2 list-disc pl-5''> <li><strong>Code source complet :</strong> Lisez, adaptez et faites évoluer chaque bloc selon vos besoins métier.</li> <li><strong>Licence perpétuelle :</strong> Utilisez le code sur votre projet en toute sérénité.</li> <li><strong>Mises à jour suivies :</strong> Recevez les nouvelles versions au rythme de Next.js et de NextBlock.</li> <li><strong>Paiement sécurisé :</strong> Les achats passent par Stripe et Freemius avec facture instantanée.</li> </ul> <p>Vous voulez vendre dans plusieurs devises ? Vous avez besoin du calcul automatique des taxes ? Vous voulez générer des blocs avec l''IA ? Nos modules offrent des solutions prêtes à l''emploi qui préservent vos scores Lighthouse à 100%.</p> <p>Chaque commande donne accès à une documentation claire et à notre support technique. Si vous avez besoin d''aide pour brancher un webhook ou un mode de paiement, nos développeurs vous répondent rapidement. Notre équipe est à vos côtés pour vous faire gagner du temps. Nous proposons aussi une garantie satisfait ou remboursé de trente jours.</p> <p>Vous avez des questions sur nos tarifs, les licences agence ou les remises en volume ? Écrivez à notre équipe à tout moment. Nous vous guiderons avec grand plaisir vers l''offre idéale pour votre entreprise. Découvrez dès aujourd''hui l''ensemble de nos produits ci-dessous pour bien démarrer votre projet.</p> </div>')::jsonb,
9125
+ updated_at = now()
9126
+ WHERE page_id = 8
9127
+ AND content::text LIKE '%' || '<p style="text-align: center; color: var' || '%';
9128
+
9129
+
9130
+ -- Page 9 Block Updates
9131
+ UPDATE public.blocks
9132
+ SET content = replace(content::text, 'NextBlock™ CMS ("we", "us", or "our") respects your privacy and is committed to protecting your personal information in accordance with Quebec''s <em>Act respecting the protection of personal information in the private sector</em> (Law 25), the federal <em>Personal Information Protection and Electronic Documents Act</em> (PIPEDA), and Canada''s Anti-Spam Legislation (CASL).', 'NextBlock™ CMS ("we", "us", or "our") respects your privacy. We protect your personal information under Quebec''s Law 25, the federal PIPEDA act, and Canada''s Anti-Spam Legislation (CASL).')::jsonb,
9133
+ updated_at = now()
9134
+ WHERE page_id = 9
9135
+ AND content::text LIKE '%' || 'NextBlock™ CMS ("we", "us", or "our") re' || '%';
9136
+
9137
+ UPDATE public.blocks
9138
+ SET content = replace(content::text, 'Our Privacy Officer is responsible for our compliance with applicable privacy laws. You may reach them at', 'Our Privacy Officer oversees our compliance with privacy laws. You can reach them at')::jsonb,
9139
+ updated_at = now()
9140
+ WHERE page_id = 9
9141
+ AND content::text LIKE '%' || 'Our Privacy Officer is responsible for o' || '%';
9142
+
9143
+ UPDATE public.blocks
9144
+ SET content = replace(content::text, '<li><strong>Account information</strong> &mdash; name, email address, and credentials when you register.</li>', '<li><strong>Account information:</strong> Your name, email address, and login details when you register.</li>')::jsonb,
9145
+ updated_at = now()
9146
+ WHERE page_id = 9
9147
+ AND content::text LIKE '%' || '<li><strong>Account information</strong>' || '%';
9148
+
9149
+ UPDATE public.blocks
9150
+ SET content = replace(content::text, '<li><strong>Usage and device data</strong> &mdash; collected only with your consent through analytics technologies.</li>', '<li><strong>Usage and device data:</strong> Collected only with your consent through analytics tools.</li>')::jsonb,
9151
+ updated_at = now()
9152
+ WHERE page_id = 9
9153
+ AND content::text LIKE '%' || '<li><strong>Usage and device data</stron' || '%';
9154
+
9155
+ UPDATE public.blocks
9156
+ SET content = replace(content::text, '<li><strong>Communications</strong> &mdash; messages you send us and your marketing preferences.</li>', '<li><strong>Communications:</strong> Messages you send us and your newsletter choices.</li>')::jsonb,
9157
+ updated_at = now()
9158
+ WHERE page_id = 9
9159
+ AND content::text LIKE '%' || '<li><strong>Communications</strong> &mda' || '%';
9160
+
9161
+ UPDATE public.blocks
9162
+ SET content = replace(content::text, '<h2>3. Why we collect it and your consent</h2>
9163
+ <p>We collect personal information for clearly identified purposes: to provide and secure our services, to communicate with you, and &mdash; only with your express, opt-in consent &mdash; for analytics and marketing. Consistent with Law 25, non-essential cookies and trackers remain disabled until you actively accept them, and you may withdraw your consent at any time.</p>', '<h2>3. Why we collect data and your consent</h2> <p>We collect personal information for clear reasons: to provide our services, keep accounts secure, and reply to your messages. We use analytics and marketing tools only with your direct, opt-in consent. Under Law 25, optional cookies stay off until you choose to accept them. You can withdraw your consent at any time.</p>')::jsonb,
9164
+ updated_at = now()
9165
+ WHERE page_id = 9
9166
+ AND content::text LIKE '%' || '<h2>3. Why we collect it and your consen' || '%';
9167
+
9168
+ UPDATE public.blocks
9169
+ SET content = replace(content::text, 'Strictly necessary cookies keep the site working and require no consent. Analytics and marketing technologies are loaded <strong>only after</strong> you opt in through our consent banner. Your choice is recorded so we can honour it and demonstrate accountability.', 'Essential cookies keep the site running and require no consent. Analytics and marketing cookies load only after you opt in via our cookie banner. We record your choice to honor it and follow privacy rules.')::jsonb,
9170
+ updated_at = now()
9171
+ WHERE page_id = 9
9172
+ AND content::text LIKE '%' || 'Strictly necessary cookies keep the site' || '%';
9173
+
9174
+ UPDATE public.blocks
9175
+ SET content = replace(content::text, 'We do not sell your personal information. We share it only with service providers who help us operate the platform under contractual confidentiality obligations, or where required by law.', 'We do not sell your personal data. We share it only with trusted service providers who help us run the platform under strict confidentiality agreements, or when required by law.')::jsonb,
9176
+ updated_at = now()
9177
+ WHERE page_id = 9
9178
+ AND content::text LIKE '%' || 'We do not sell your personal information' || '%';
9179
+
9180
+ UPDATE public.blocks
9181
+ SET content = replace(content::text, '<h2>6. Retention</h2>
9182
+ <p>We keep personal information only for as long as necessary to fulfil the purposes described above or as required by law, after which it is securely destroyed or anonymized.</p>', '<h2>6. Data retention</h2> <p>We keep personal information only as long as needed for the purposes described above or as required by law. After that, we securely delete or anonymize your data.</p>')::jsonb,
9183
+ updated_at = now()
9184
+ WHERE page_id = 9
9185
+ AND content::text LIKE '%' || '<h2>6. Retention</h2>
9186
+ <p>We keep person' || '%';
9187
+
9188
+ UPDATE public.blocks
9189
+ SET content = replace(content::text, 'Subject to applicable law, you have the right to access, rectify, and delete your personal information, to withdraw consent, to data portability, and to be informed about automated processing. To exercise these rights, contact our Privacy Officer at', 'Under privacy laws, you have the right to view, correct, and delete your personal information. You can also withdraw consent or ask for a portable copy of your data. To use these rights, write to our Privacy Officer at')::jsonb,
9190
+ updated_at = now()
9191
+ WHERE page_id = 9
9192
+ AND content::text LIKE '%' || 'Subject to applicable law, you have the ' || '%';
9193
+
9194
+ UPDATE public.blocks
9195
+ SET content = replace(content::text, '<h2>8. Commercial electronic messages (CASL)</h2>
9196
+ <p>We send commercial electronic messages only with your consent. Every message identifies us and includes a working unsubscribe mechanism that we honour promptly.</p>', '<h2>8. Commercial electronic messages</h2> <p>We send commercial emails only with your permission. Every email clearly identifies us and includes an easy unsubscribe link that takes effect right away.</p>')::jsonb,
9197
+ updated_at = now()
9198
+ WHERE page_id = 9
9199
+ AND content::text LIKE '%' || '<h2>8. Commercial electronic messages (C' || '%';
9200
+
9201
+ UPDATE public.blocks
9202
+ SET content = replace(content::text, '<h2>9. Safeguards</h2>
9203
+ <p>We use appropriate physical, organizational, and technological measures &mdash; including encryption in transit and access controls &mdash; to protect personal information against loss, theft, and unauthorized access.</p>', '<h2>9. Security safeguards</h2> <p>We use strong technical and physical protections to keep your data safe. These include encrypted connections and strict access controls to prevent loss, theft, and unauthorized access.</p>')::jsonb,
9204
+ updated_at = now()
9205
+ WHERE page_id = 9
9206
+ AND content::text LIKE '%' || '<h2>9. Safeguards</h2>
9207
+ <p>We use approp' || '%';
9208
+
9209
+ UPDATE public.blocks
9210
+ SET content = replace(content::text, 'NextBlock™ CMS is free, open-source software distributed under the GNU Affero General Public License v3. When you self-host NextBlock, you are the operator responsible for the personal information processed by your own deployment, and this policy serves as a starting point you may adapt to your organization.', 'NextBlock™ CMS is free open-source software under the AGPLv3 license. When you self-host NextBlock, you control your own server. You are responsible for the personal data on your deployment, and this policy is a helpful model you can adapt.')::jsonb,
9211
+ updated_at = now()
9212
+ WHERE page_id = 9
9213
+ AND content::text LIKE '%' || 'NextBlock™ CMS is free, open-source soft' || '%';
9214
+
9215
+ UPDATE public.blocks
9216
+ SET content = replace(content::text, '<h2>11. Changes to this policy</h2>
9217
+ <p>We may update this policy from time to time. Material changes will be communicated through the site, and the "last updated" date will be revised.</p>', '<h2>11. Policy changes</h2> <p>We may update this policy over time. We announce important changes on our site and update the revision date at the top.</p>')::jsonb,
9218
+ updated_at = now()
9219
+ WHERE page_id = 9
9220
+ AND content::text LIKE '%' || '<h2>11. Changes to this policy</h2>
9221
+ <p>' || '%';
9222
+
9223
+ UPDATE public.blocks
9224
+ SET content = replace(content::text, 'Questions or complaints? Contact NextBlock™ CMS at <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>. You may also contact the Commission d''accès à l''information du Québec or the Office of the Privacy Commissioner of Canada.', 'Have questions or complaints? Contact NextBlock™ at <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>. You can also contact the Commission d''accès à l''information du Québec or the Office of the Privacy Commissioner of Canada.')::jsonb,
9225
+ updated_at = now()
9226
+ WHERE page_id = 9
9227
+ AND content::text LIKE '%' || 'Questions or complaints? Contact NextBlo' || '%';
9228
+
9229
+
9230
+ -- Page 10 Block Updates
9231
+ UPDATE public.blocks
9232
+ SET content = replace(content::text, 'NextBlock™ CMS (« nous ») respecte votre vie privée et s''engage à protéger vos renseignements personnels conformément à la <em>Loi sur la protection des renseignements personnels dans le secteur privé</em> du Québec (Loi 25), à la <em>Loi sur la protection des renseignements personnels et les documents électroniques</em> (LPRPDE) et à la Loi canadienne anti-pourriel (LCAP).', 'NextBlock™ CMS (« nous ») respecte votre vie privée. Nous protégeons vos renseignements personnels selon la Loi 25 du Québec, la loi fédérale LPRPDE et les règles canadiennes anti-pourriel (LCAP).')::jsonb,
9233
+ updated_at = now()
9234
+ WHERE page_id = 10
9235
+ AND content::text LIKE '%' || 'NextBlock™ CMS (« nous ») respecte votre' || '%';
9236
+
9237
+ UPDATE public.blocks
9238
+ SET content = replace(content::text, 'Notre responsable de la protection des renseignements personnels veille au respect des lois applicables. Vous pouvez le joindre à', 'Notre responsable veille au respect des règles de confidentialité. Vous pouvez lui écrire à')::jsonb,
9239
+ updated_at = now()
9240
+ WHERE page_id = 10
9241
+ AND content::text LIKE '%' || 'Notre responsable de la protection des r' || '%';
9242
+
9243
+ UPDATE public.blocks
9244
+ SET content = replace(content::text, '<h2>2. Renseignements que nous recueillons</h2>
9245
+ <ul>
9246
+ <li><strong>Renseignements de compte</strong> &mdash; nom, adresse courriel et identifiants lors de l''inscription.</li>
9247
+ <li><strong>Données d''utilisation et d''appareil</strong> &mdash; recueillies uniquement avec votre consentement au moyen de technologies d''analyse.</li>
9248
+ <li><strong>Communications</strong> &mdash; les messages que vous nous envoyez et vos préférences marketing.</li>
9249
+ </ul>', '<h2>2. Renseignements recueillis</h2> <ul> <li><strong>Renseignements de compte :</strong> Votre nom, votre courriel et vos accès lors de l''inscription.</li> <li><strong>Données d''utilisation et d''appareil :</strong> Recueillies avec votre accord via nos outils de mesure.</li> <li><strong>Communications :</strong> Vos messages reçus et vos choix de suivi par courriel.</li> </ul>')::jsonb,
9250
+ updated_at = now()
9251
+ WHERE page_id = 10
9252
+ AND content::text LIKE '%' || '<h2>2. Renseignements que nous recueillo' || '%';
9253
+
9254
+ UPDATE public.blocks
9255
+ SET content = replace(content::text, '<p>Nous recueillons des renseignements personnels à des fins clairement déterminées : fournir et sécuriser nos services, communiquer avec vous et &mdash; uniquement avec votre consentement exprès &mdash; à des fins d''analyse et de marketing. Conformément à la Loi 25, les témoins et traceurs non essentiels demeurent désactivés tant que vous ne les avez pas acceptés, et vous pouvez retirer votre consentement en tout temps.</p>', '<p>Nous recueillons vos données pour des motifs clairs : faire fonctionner nos services, sécuriser les accès et vous répondre. Les outils d''analyse et de suivi ne s''activent qu''avec votre accord clair. Selon la Loi 25, les témoins optionnels restent coupés tant que vous ne les acceptez pas. Vous pouvez retirer votre accord en tout temps.</p>')::jsonb,
9256
+ updated_at = now()
9257
+ WHERE page_id = 10
9258
+ AND content::text LIKE '%' || '<p>Nous recueillons des renseignements p' || '%';
9259
+
9260
+ UPDATE public.blocks
9261
+ SET content = replace(content::text, 'Les témoins strictement nécessaires assurent le fonctionnement du site et ne requièrent aucun consentement. Les technologies d''analyse et de marketing ne sont chargées qu''<strong>après</strong> votre consentement explicite. Votre choix est enregistré afin de le respecter.', 'Les témoins essentiels assurent le bon fonctionnement du site. Ils ne demandent aucun accord préalable. Les témoins d''analyse se chargent seulement après votre choix sur notre bandeau. Nous gardons votre choix en mémoire pour le respecter.')::jsonb,
9262
+ updated_at = now()
9263
+ WHERE page_id = 10
9264
+ AND content::text LIKE '%' || 'Les témoins strictement nécessaires assu' || '%';
9265
+
9266
+ UPDATE public.blocks
9267
+ SET content = replace(content::text, '<h2>5. Communication à des tiers</h2>
9268
+ <p>Nous ne vendons pas vos renseignements personnels. Nous ne les communiquons qu''à des fournisseurs qui nous aident à exploiter la plateforme, sous obligation de confidentialité, ou lorsque la loi l''exige.</p>', '<h2>5. Partage et communication</h2> <p>Nous ne vendons jamais vos données personnelles. Nous les partageons uniquement avec des prestataires de confiance qui nous aident à faire tourner le site sous contrat de secret, ou si la loi l''impose.</p>')::jsonb,
9269
+ updated_at = now()
9270
+ WHERE page_id = 10
9271
+ AND content::text LIKE '%' || '<h2>5. Communication à des tiers</h2>
9272
+ <' || '%';
9273
+
9274
+ UPDATE public.blocks
9275
+ SET content = replace(content::text, '<h2>6. Conservation</h2>
9276
+ <p>Nous ne conservons les renseignements personnels que le temps nécessaire aux fins décrites ou exigé par la loi, après quoi ils sont détruits ou anonymisés de façon sécuritaire.</p>', '<h2>6. Durée de conservation</h2> <p>Nous gardons vos données seulement le temps utile pour les buts décrits ou selon la loi. Ensuite, nous les effaçons ou nous les rendons anonymes de façon sûre.</p>')::jsonb,
9277
+ updated_at = now()
9278
+ WHERE page_id = 10
9279
+ AND content::text LIKE '%' || '<h2>6. Conservation</h2>
9280
+ <p>Nous ne con' || '%';
9281
+
9282
+ UPDATE public.blocks
9283
+ SET content = replace(content::text, 'Sous réserve de la loi applicable, vous avez le droit d''accéder à vos renseignements, de les rectifier et de les supprimer, de retirer votre consentement, à la portabilité de vos données et d''être informé du traitement automatisé. Pour exercer ces droits, écrivez à', 'Vous avez le droit de lire, de corriger et de faire effacer vos données. Vous pouvez aussi retirer votre accord ou demander une copie de vos données. Pour exercer vos droits, écrivez à notre responsable à')::jsonb,
9284
+ updated_at = now()
9285
+ WHERE page_id = 10
9286
+ AND content::text LIKE '%' || 'Sous réserve de la loi applicable, vous ' || '%';
9287
+
9288
+ UPDATE public.blocks
9289
+ SET content = replace(content::text, '<h2>8. Messages électroniques commerciaux (LCAP)</h2>
9290
+ <p>Nous n''envoyons des messages électroniques commerciaux qu''avec votre consentement. Chaque message nous identifie et comporte un mécanisme de désabonnement fonctionnel que nous respectons rapidement.</p>', '<h2>8. Messages électroniques</h2> <p>Nous envoyons des courriels informatifs seulement avec votre accord. Chaque courriel montre notre nom et propose un lien simple pour vous désabonner d''un clic.</p>')::jsonb,
9291
+ updated_at = now()
9292
+ WHERE page_id = 10
9293
+ AND content::text LIKE '%' || '<h2>8. Messages électroniques commerciau' || '%';
9294
+
9295
+ UPDATE public.blocks
9296
+ SET content = replace(content::text, '<h2>9. Mesures de sécurité</h2>
9297
+ <p>Nous employons des mesures physiques, organisationnelles et technologiques appropriées &mdash; dont le chiffrement en transit et le contrôle des accès &mdash; pour protéger vos renseignements.</p>', '<h2>9. Mesures de sécurité</h2> <p>Nous utilisons des moyens techniques et physiques solides pour garder vos données en sûreté. Cela comprend des échanges chiffrés et un contrôle strict des accès contre toute fuite ou vol.</p>')::jsonb,
9298
+ updated_at = now()
9299
+ WHERE page_id = 10
9300
+ AND content::text LIKE '%' || '<h2>9. Mesures de sécurité</h2>
9301
+ <p>Nous' || '%';
9302
+
9303
+ UPDATE public.blocks
9304
+ SET content = replace(content::text, 'NextBlock™ CMS est un logiciel libre et à code source ouvert distribué sous la licence publique générale GNU Affero v3. Lorsque vous hébergez NextBlock vous-même, vous êtes l''exploitant responsable des renseignements personnels traités par votre propre instance, et la présente politique vous sert de point de départ adaptable à votre organisation.', 'NextBlock™ CMS est un logiciel libre sous licence AGPLv3. Si vous hébergez NextBlock vous-même, vous gérez votre propre serveur. Vous êtes responsable des données sur votre instance, et ce texte est un modèle que vous pouvez adapter.')::jsonb,
9305
+ updated_at = now()
9306
+ WHERE page_id = 10
9307
+ AND content::text LIKE '%' || 'NextBlock™ CMS est un logiciel libre et ' || '%';
9308
+
9309
+ UPDATE public.blocks
9310
+ SET content = replace(content::text, '<h2>11. Modifications</h2>
9311
+ <p>Nous pouvons mettre à jour cette politique. Les changements importants seront communiqués sur le site et la date de mise à jour sera révisée.</p>', '<h2>11. Mises à jour</h2> <p>Nous pouvons mettre à jour ce texte au fil du temps. Les changements notables seront affichés sur le site avec la nouvelle date en tête de page.</p>')::jsonb,
9312
+ updated_at = now()
9313
+ WHERE page_id = 10
9314
+ AND content::text LIKE '%' || '<h2>11. Modifications</h2>
9315
+ <p>Nous pouv' || '%';
9316
+
9317
+ UPDATE public.blocks
9318
+ SET content = replace(content::text, 'Des questions ou des plaintes ? Contactez NextBlock™ CMS à <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>. Vous pouvez aussi vous adresser à la Commission d''accès à l''information du Québec.', 'Une question ou un avis ? Écrivez à NextBlock™ à <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>. Vous pouvez aussi joindre la Commission d''accès à l''information du Québec.')::jsonb,
9319
+ updated_at = now()
9320
+ WHERE page_id = 10
9321
+ AND content::text LIKE '%' || 'Des questions ou des plaintes ? Contacte' || '%';
9322
+
9323
+
9324
+ -- Page 12 Block Updates
9325
+ UPDATE public.blocks
9326
+ SET content = replace(content::text, 'En accédant à NextBlock™ CMS et aux services que nous fournissons (les « Services ») ou en les utilisant, vous acceptez d''être lié par les présentes conditions d''utilisation. Si vous n''êtes pas d''accord, n''utilisez pas les Services.', 'En utilisant le CMS NextBlock™ et les services associés (les « Services »), vous acceptez ces conditions d''utilisation. Si vous refusez ces règles, veuillez ne pas utiliser les Services.')::jsonb,
9327
+ updated_at = now()
9328
+ WHERE page_id = 12
9329
+ AND content::text LIKE '%' || 'En accédant à NextBlock™ CMS et aux serv' || '%';
9330
+
9331
+ UPDATE public.blocks
9332
+ SET content = replace(content::text, '<h2>2. Logiciel libre et à code source ouvert</h2>
9333
+ <p>NextBlock™ CMS est un logiciel libre et à code source ouvert distribué sous la <strong>licence publique générale GNU Affero, version 3 (AGPL-3.0)</strong> ou, à votre choix, toute version ultérieure. Vous êtes libre d''exécuter, d''étudier, de partager et de modifier le logiciel selon les termes de cette licence. Une copie de la licence est fournie avec le logiciel et est aussi disponible à <a href="https://www.gnu.org/licenses/agpl-3.0.html">gnu.org/licenses/agpl-3.0.html</a>.</p>', '<h2>2. Logiciel libre et code source ouvert</h2> <p>NextBlock™ CMS est un logiciel libre sous <strong>licence publique générale GNU Affero, version 3 (AGPL-3.0)</strong> ou toute version ultérieure. Vous pouvez lancer, étudier, copier et faire évoluer le code selon cette licence. Le texte complet se trouve avec le code et en ligne sur <a href="https://www.gnu.org/licenses/agpl-3.0.html">gnu.org/licenses/agpl-3.0.html</a>.</p>')::jsonb,
9334
+ updated_at = now()
9335
+ WHERE page_id = 12
9336
+ AND content::text LIKE '%' || '<h2>2. Logiciel libre et à code source o' || '%';
9337
+
9338
+ UPDATE public.blocks
9339
+ SET content = replace(content::text, '<h2>3. Disponibilité du code source</h2>
9340
+ <p>Conformément à l''article 13 de l''AGPL-3.0, si vous exploitez une version modifiée de NextBlock™ CMS et la rendez accessible à des utilisateurs sur un réseau, vous devez offrir clairement à ces utilisateurs l''accès au code source correspondant de votre version modifiée, gratuitement, par un moyen usuel de copie de logiciels.</p>', '<h2>3. Partage du code source</h2> <p>Selon l''article 13 de la licence AGPL-3.0, si vous modifiez NextBlock™ CMS et le mettez en ligne pour des usagers sur un réseau, vous devez offrir l''accès libre et sans frais au code source de votre version modifiée.</p>')::jsonb,
9341
+ updated_at = now()
9342
+ WHERE page_id = 12
9343
+ AND content::text LIKE '%' || '<h2>3. Disponibilité du code source</h2>' || '%';
9344
+
9345
+ UPDATE public.blocks
9346
+ SET content = replace(content::text, '<h2>4. Marques de commerce</h2>
9347
+ <p>L''AGPL-3.0 accorde de larges droits sur le code source du logiciel, mais <strong>n''accorde aucun droit</strong> sur nos noms commerciaux, marques de commerce ou marques de service. « NextBlock™ », le nom NextBlock™ CMS et les logos associés demeurent notre propriété et ne peuvent être utilisés d''une manière laissant entendre une approbation ou une affiliation sans notre autorisation écrite préalable.</p>', '<h2>4. Marques et logos</h2> <p>La licence AGPL-3.0 donne de larges droits sur le code. Mais <strong>elle ne donne aucun droit</strong> sur nos noms et marques. Les termes « NextBlock™ », NextBlock™ CMS et les logos restent notre bien exclusif. Ils ne peuvent être repris sans accord écrit préalable.</p>')::jsonb,
9348
+ updated_at = now()
9349
+ WHERE page_id = 12
9350
+ AND content::text LIKE '%' || '<h2>4. Marques de commerce</h2>
9351
+ <p>L''AG' || '%';
9352
+
9353
+ UPDATE public.blocks
9354
+ SET content = replace(content::text, '<h2>5. Comptes et utilisation acceptable</h2>
9355
+ <p>Si vous créez un compte, vous êtes responsable de la protection de vos identifiants et de toute activité effectuée à partir de votre compte, et vous vous engagez à nous aviser rapidement de toute utilisation non autorisée. Vous vous engagez à ne pas détourner les Services, notamment en tentant de les perturber, d''y accéder sans autorisation ou de les utiliser à des fins illégales.</p>', '<h2>5. Comptes et bon usage</h2> <p>Si vous ouvrez un compte, vous gardez la garde de vos accès et de toute action faite sous votre nom. Vous devez nous prévenir vite en cas d''usage non permis. Vous vous engagez à ne pas bloquer les Services, ne pas forcer les accès et ne pas agir contre la loi.</p>')::jsonb,
9356
+ updated_at = now()
9357
+ WHERE page_id = 12
9358
+ AND content::text LIKE '%' || '<h2>5. Comptes et utilisation acceptable' || '%';
9359
+
9360
+ UPDATE public.blocks
9361
+ SET content = replace(content::text, 'Comme l''énonce l''article 15 de l''AGPL-3.0, le logiciel est fourni « tel quel », sans garantie d''aucune sorte, expresse ou implicite, y compris, sans s''y limiter, les garanties implicites de qualité marchande et d''adéquation à un usage particulier. Vous assumez l''entièreté du risque quant à la qualité et au rendement du logiciel.', 'Selon l''article 15 de l''AGPL-3.0, le logiciel est fourni « tel quel », sans garantie d''aucune sorte, expresse ou tacite. Cela inclut les garanties de vente ou d''usage pour un besoin précis. Vous prenez sur vous les risques liés au bon emploi du logiciel.')::jsonb,
9362
+ updated_at = now()
9363
+ WHERE page_id = 12
9364
+ AND content::text LIKE '%' || 'Comme l''énonce l''article 15 de l''AGPL-3.' || '%';
9365
+
9366
+ UPDATE public.blocks
9367
+ SET content = replace(content::text, '<h2>7. Limitation de responsabilité</h2>
9368
+ <p>Comme l''énonce l''article 16 de l''AGPL-3.0, et dans toute la mesure permise par la loi applicable, en aucun cas un titulaire de droits d''auteur ou toute autre partie qui modifie ou transmet le logiciel ne saurait être tenu responsable envers vous de dommages, y compris tout dommage général, spécial, accessoire ou consécutif découlant de l''utilisation ou de l''impossibilité d''utiliser le logiciel.</p>', '<h2>7. Limite de responsabilité</h2> <p>Selon l''article 16 de l''AGPL-3.0 et dans la limite permise par la loi, aucun auteur ou tiers modifiant le code ne peut être tenu pour responsable de vos pertes ou dommages liés à l''usage du logiciel.</p>')::jsonb,
9369
+ updated_at = now()
9370
+ WHERE page_id = 12
9371
+ AND content::text LIKE '%' || '<h2>7. Limitation de responsabilité</h2>' || '%';
9372
+
9373
+ UPDATE public.blocks
9374
+ SET content = replace(content::text, 'Les présentes conditions sont régies par les lois de la province de Québec et les lois fédérales du Canada qui y sont applicables, sans égard aux règles de conflit de lois. Rien dans les présentes conditions ne limite les droits impératifs de protection du consommateur dont vous pourriez bénéficier en vertu de ces lois.', 'Ces conditions suivent les lois de la province de Québec et les lois du Canada applicables. Rien ici ne réduit vos droits stricts de consommateur selon ces lois.')::jsonb,
9375
+ updated_at = now()
9376
+ WHERE page_id = 12
9377
+ AND content::text LIKE '%' || 'Les présentes conditions sont régies par' || '%';
9378
+
9379
+ UPDATE public.blocks
9380
+ SET content = replace(content::text, '<h2>9. Modifications</h2>
9381
+ <p>Nous pouvons réviser ces conditions de temps à autre. Les changements importants seront communiqués au moyen des Services, et l''utilisation continue des Services après leur entrée en vigueur vaut acceptation.</p>', '<h2>9. Mises à jour</h2> <p>Nous pouvons adapter ces règles au fil du temps. Les changements notables passeront sur le site. Votre usage continu vaut accord avec les nouvelles règles.</p>')::jsonb,
9382
+ updated_at = now()
9383
+ WHERE page_id = 12
9384
+ AND content::text LIKE '%' || '<h2>9. Modifications</h2>
9385
+ <p>Nous pouvo' || '%';
9386
+
9387
+ UPDATE public.blocks
9388
+ SET content = replace(content::text, 'Des questions sur ces conditions ? Contactez NextBlock™ CMS à <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>.', 'Une question sur ces conditions ? Écrivez à NextBlock™ CMS à <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>.')::jsonb,
9389
+ updated_at = now()
9390
+ WHERE page_id = 12
9391
+ AND content::text LIKE '%' || 'Des questions sur ces conditions ? Conta' || '%';
9392
+
9393
+ END $$;
9394
+
9395
+
9396
+ -- >>> FROM: 00000000000033_seed_seo_score_optimizations_p2.sql <<<
9397
+ -- Migration: 00000000000033_seed_seo_score_optimizations_p2.sql
9398
+ -- Description: Complete 100/100 Page SEO optimization for shop/boutique, legal pages, and setup/updating posts.
9399
+ -- Safety: Forward-only, content-guarded updates that only touch matching seeded copy.
9400
+
9401
+ DO $$
9402
+ BEGIN
9403
+ -----------------------------------------------------------------------------
9404
+ -- 1. Post Metadata (Post 8 & Post 9)
9405
+ -----------------------------------------------------------------------------
9406
+ UPDATE public.posts
9407
+ SET meta_description = 'A single command keeps your NextBlock install updated on Docker, Supabase, or a cloned repo. Learn how it works and keeps your data safe.',
9408
+ updated_at = now()
9409
+ WHERE slug = 'how-updating-works'
9410
+ AND meta_description LIKE 'Update NextBlock in one step%';
9411
+
9412
+ UPDATE public.posts
9413
+ SET meta_title = 'Mises à jour NextBlock : une commande pour chaque site',
9414
+ meta_description = 'Une seule commande met à jour NextBlock sur Docker, Supabase ou un dépôt cloné. Découvrez le fonctionnement et la protection de vos données.',
9415
+ updated_at = now()
9416
+ WHERE slug = 'comment-fonctionnent-les-mises-a-jour'
9417
+ AND meta_title LIKE 'Mettre à jour NextBlock%';
9418
+
9419
+ -----------------------------------------------------------------------------
9420
+ -- 2. Post 4 Setup FR Card Headings (H3 -> H2 to prevent heading level skip)
9421
+ -----------------------------------------------------------------------------
9422
+ UPDATE public.blocks
9423
+ SET content = jsonb_set(content, '{html_content}', to_jsonb('<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. Voici quatre façons de démarrer, <strong>classées de la plus simple à la plus technique</strong> : la première tient en un clic, la dernière donne le code source complet pour celles et ceux qui veulent participer à NextBlock. 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.</p>
9424
+
9425
+ <div class=''mt-8 mb-6 flex items-center gap-4 text-[0.7rem] font-semibold uppercase tracking-[0.18em] text-slate-500 dark:text-slate-400''>
9426
+ <span class=''flex-shrink-0''>Le plus simple</span>
9427
+ <span class=''h-1.5 flex-1 rounded-full bg-gradient-to-r from-blue-400 via-violet-400 to-emerald-400''></span>
9428
+ <span class=''flex-shrink-0''>Le plus de contrôle</span>
9429
+ </div>
9430
+
9431
+ <div class=''grid gap-5 md:grid-cols-2 my-6''>
9432
+ <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''>
9433
+ <div class=''flex items-center justify-between mb-4''>
9434
+ <span class=''flex h-9 w-9 items-center justify-center rounded-full bg-blue-600 text-sm font-bold text-white''>1</span>
9435
+ <span class=''inline-flex items-center gap-1''><span class=''h-1.5 w-5 rounded-full bg-blue-500''></span><span class=''h-1.5 w-5 rounded-full bg-slate-200 dark:bg-white/10''></span><span class=''h-1.5 w-5 rounded-full bg-slate-200 dark:bg-white/10''></span><span class=''h-1.5 w-5 rounded-full bg-slate-200 dark:bg-white/10''></span></span>
9436
+ </div>
9437
+ <p class=''mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-blue-700 dark:text-blue-200''>Le plus simple &middot; un clic</p>
9438
+ <h2 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>Déployer sur Vercel</h2>
9439
+ <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, aucun compte à configurer, rien à copier.</p>
9440
+ </a>
9441
+ <a href=''#npm-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''>
9442
+ <div class=''flex items-center justify-between mb-4''>
9443
+ <span class=''flex h-9 w-9 items-center justify-center rounded-full bg-amber-500 text-sm font-bold text-white''>2</span>
9444
+ <span class=''inline-flex items-center gap-1''><span class=''h-1.5 w-5 rounded-full bg-amber-500''></span><span class=''h-1.5 w-5 rounded-full bg-amber-500''></span><span class=''h-1.5 w-5 rounded-full bg-slate-200 dark:bg-white/10''></span><span class=''h-1.5 w-5 rounded-full bg-slate-200 dark:bg-white/10''></span></span>
9445
+ </div>
9446
+ <p class=''mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-amber-700 dark:text-amber-200''>Facile &middot; 100 % local</p>
9447
+ <h2 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>npm create nextblock &rarr; Docker</h2>
9448
+ <p class=''mb-0 text-sm leading-6 text-slate-600 dark:text-slate-300''>Un seul prompt génère un projet et démarre toute la pile — base de données, auth, stockage, CMS — sur votre machine. Aucun compte cloud.</p>
9449
+ </a>
9450
+ <a href=''#npm-cloud'' 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''>
9451
+ <div class=''flex items-center justify-between mb-4''>
9452
+ <span class=''flex h-9 w-9 items-center justify-center rounded-full bg-violet-600 text-sm font-bold text-white''>3</span>
9453
+ <span class=''inline-flex items-center gap-1''><span class=''h-1.5 w-5 rounded-full bg-violet-500''></span><span class=''h-1.5 w-5 rounded-full bg-violet-500''></span><span class=''h-1.5 w-5 rounded-full bg-violet-500''></span><span class=''h-1.5 w-5 rounded-full bg-slate-200 dark:bg-white/10''></span></span>
9454
+ </div>
9455
+ <p class=''mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200''>Intermédiaire &middot; votre propre cloud</p>
9456
+ <h2 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>npm create nextblock &rarr; Supabase + R2</h2>
9457
+ <p class=''mb-0 text-sm leading-6 text-slate-600 dark:text-slate-300''>Générez une app autonome sur votre propre projet Supabase géré et Cloudflare R2, prête à déployer partout.</p>
9458
+ </a>
9459
+ <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''>
9460
+ <div class=''flex items-center justify-between mb-4''>
9461
+ <span class=''flex h-9 w-9 items-center justify-center rounded-full bg-emerald-600 text-sm font-bold text-white''>4</span>
9462
+ <span class=''inline-flex items-center gap-1''><span class=''h-1.5 w-5 rounded-full bg-emerald-500''></span><span class=''h-1.5 w-5 rounded-full bg-emerald-500''></span><span class=''h-1.5 w-5 rounded-full bg-emerald-500''></span><span class=''h-1.5 w-5 rounded-full bg-emerald-500''></span></span>
9463
+ </div>
9464
+ <p class=''mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200''>Avancé &middot; pour les contributeurs</p>
9465
+ <h2 class=''mt-2 mb-2 text-xl font-semibold text-slate-900 dark:text-white''>Cloner le dépôt</h2>
9466
+ <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. Pour celles et ceux qui veulent aider à construire NextBlock (Docker fonctionne ici aussi).</p>
9467
+ </a>
9468
+ </div>
9469
+
9470
+ <p class=''text-sm text-slate-500 dark:text-slate-400''>Vous ne savez pas par où commencer ? Descendez la liste — choisissez la première option dont vous avez déjà les prérequis. La plupart des gens devraient commencer par <a href=''#one-click-vercel''>Vercel</a>.</p>
9471
+
9472
+ <figure class=''my-12 overflow-hidden rounded-[2rem] border border-slate-200/80 bg-slate-950 shadow-2xl dark:border-white/10''>
9473
+ <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'' />
9474
+ <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>
9475
+ </figure>
9476
+
9477
+ <h2 id=''one-click-vercel''>Option 1 : Déploiement Vercel en un clic</h2>
9478
+ <p class=''mt-2 mb-6 flex flex-wrap items-center gap-x-3 gap-y-2 text-sm''><span class=''inline-flex items-center gap-2 rounded-full border border-blue-200 bg-blue-50 px-3 py-1 text-xs font-semibold uppercase tracking-wide text-blue-700 dark:border-blue-500/20 dark:bg-blue-500/10 dark:text-blue-200''>Étape 1 &middot; Le plus simple</span><span class=''text-slate-500 dark:text-slate-400''>Idéal pour un site en ligne avec le minimum d''effort — pas de terminal, aucun compte à configurer.</span></p>
9479
+ <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>
9480
+ <ol class=''space-y-2''>
9481
+ <li><strong>Cliquez sur Deploy to Vercel</strong> et connectez-vous — Vercel clone NextBlock dans un nouveau dépôt qui vous appartient.</li>
9482
+ <li><strong>Nommez le dépôt — et rendez-le Public.</strong> À la première étape sur Vercel, vous choisissez le nom du dépôt ; réglez sa visibilité sur <strong>Public</strong> plutôt que Privé. Un dépôt public est ce qui débloque les mises à jour automatiques en un clic plus tard — c''est donc le choix recommandé.</li>
9483
+ <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>
9484
+ <li><strong>Ouvrez votre nouveau site</strong> une fois le build terminé. Toute nouvelle instance vous amène directement à l''assistant de configuration.</li>
9485
+ <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>
9486
+ </ol>
9487
+ <div class=''my-8''>
9488
+ <a href=''https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fnextblock-cms%2Fnextblock&amp;project-name=nextblock&amp;repository-name=nextblock&amp;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 &rarr;</a>
9489
+ </div>
9490
+ <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''>
9491
+ <p class=''mt-0 text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200''>Recommandé &middot; rendez le dépôt public</p>
9492
+ <p class=''mt-3 mb-0 text-sm text-slate-700 dark:text-slate-200''>Quand Vercel vous demande de nommer le nouveau dépôt, choisissez <strong>Public</strong>. C''est gratuit, et c''est ce qui permet à l''étape <strong>Connect GitHub</strong> du tableau de bord d''installer un workflow quotidien qui garde votre site synchronisé avec la dernière version de NextBlock. Vous pourrez toujours passer un dépôt privé en public plus tard dans GitHub — mais démarrer en public est le chemin le plus simple vers les mises à jour automatiques.</p>
9493
+ </div>
9494
+ <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''>
9495
+ <p class=''mt-0 text-xs font-semibold uppercase tracking-[0.22em] text-blue-700 dark:text-blue-200''>Zéro configuration</p>
9496
+ <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>
9497
+ </div>
9498
+
9499
+ <h2 id=''npm-docker''>Option 2 : npm create nextblock &rarr; Docker (100 % local)</h2>
9500
+ <p class=''mt-2 mb-6 flex flex-wrap items-center gap-x-3 gap-y-2 text-sm''><span class=''inline-flex items-center gap-2 rounded-full border border-amber-200 bg-amber-50 px-3 py-1 text-xs font-semibold uppercase tracking-wide text-amber-700 dark:border-amber-500/20 dark:bg-amber-500/10 dark:text-amber-200''>Étape 2 &middot; Facile</span><span class=''text-slate-500 dark:text-slate-400''>Idéal pour tout essayer sur votre machine sans aucun compte cloud. Nécessite Docker Desktop.</span></p>
9501
+ <p>Faites tourner NextBlock entièrement sur votre machine, sans aucun compte cloud. Le CLI génère une application Next.js autonome puis démarre toute la pile dans Docker pour vous : 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 — idéal pour les évaluations, les environnements isolés et la pleine propriété de vos données.</p>
9502
+ <p>Avant de commencer, installez <a href=''https://nodejs.org'' target=''_blank'' rel=''noopener''>Node.js 20 ou plus récent</a> (npm inclus) et <a href=''https://www.docker.com/products/docker-desktop/'' target=''_blank'' rel=''noopener''>Docker Desktop</a>, et assurez-vous que Docker Desktop est démarré.</p>
9503
+ <pre><code>npm create nextblock@latest mon-site</code></pre>
9504
+ <ol class=''space-y-2''>
9505
+ <li><strong>Choisissez le profil d''hébergement.</strong> Au premier prompt, choisissez <em>Local Self-Hosted Docker Mode (One-Click Local Sandbox)</em>, puis confirmez que Docker Desktop est installé et démarré.</li>
9506
+ <li><strong>Laissez faire.</strong> Le CLI copie le template, installe les dépendances, génère des clés sécurisées et démarre toute la pile avec une seule commande Docker — sans aucune question. Le premier lancement télécharge les images et construit l''app, comptez donc quelques minutes ; chaque migration de base de données est appliquée automatiquement au démarrage de la pile.</li>
9507
+ <li><strong>Ouvrez <code>http://localhost:3000</code></strong> — vous êtes redirigé vers l''assistant de configuration. Comme la base de données et le stockage MinIO sont déjà connectés, les étapes de connexion et de stockage sont ignorées : il ne reste qu''à créer votre administrateur (confirmé instantanément, sans email). Vous arrivez dans le tableau de bord du CMS.</li>
9508
+ </ol>
9509
+ <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''>
9510
+ <p class=''mt-0 text-xs font-semibold uppercase tracking-[0.22em] text-amber-700 dark:text-amber-200''>Commandes du quotidien</p>
9511
+ <pre class=''mt-4 mb-0''><code># reconstruire et redémarrer la pile
9512
+ npm run docker:up
9513
+
9514
+ # arrêter la pile (vos données persistent dans les volumes Docker)
9515
+ npm run docker:down
9516
+
9517
+ # suivre les logs de l''application
9518
+ npm run docker:logs</code></pre>
9519
+ <p class=''mt-4 mb-0 text-sm text-slate-700 dark:text-slate-200''>Le mode Docker n''est proposé que dans le prompt interactif — ne passez pas <code>--yes</code>, qui force le mode cloud géré ci-dessous.</p>
9520
+ </div>
9521
+
9522
+ <h2 id=''npm-cloud''>Option 3 : npm create nextblock &rarr; votre propre Supabase + Cloudflare</h2>
9523
+ <p class=''mt-2 mb-6 flex flex-wrap items-center gap-x-3 gap-y-2 text-sm''><span class=''inline-flex items-center gap-2 rounded-full border border-violet-200 bg-violet-50 px-3 py-1 text-xs font-semibold uppercase tracking-wide text-violet-700 dark:border-violet-500/20 dark:bg-violet-500/10 dark:text-violet-200''>Étape 3 &middot; Intermédiaire</span><span class=''text-slate-500 dark:text-slate-400''>Idéal pour construire votre propre site sur du cloud géré. Nécessite un projet Supabase et un bucket R2.</span></p>
9524
+ <p>Le meilleur point de départ pour construire votre propre site sur du cloud géré. Le CLI génère une application Next.js autonome avec NextBlock déjà intégré — sans monorepo ni outillage de workspace — reliée à un projet Supabase et un bucket Cloudflare R2 que vous contrôlez, et elle se déploie partout où Next.js tourne.</p>
9525
+ <p>Avant de commencer, installez <a href=''https://nodejs.org'' target=''_blank'' rel=''noopener''>Node.js 20 ou plus récent</a>, créez un projet gratuit sur <a href=''https://supabase.com'' target=''_blank'' rel=''noopener''>supabase.com</a>, et configurez un bucket <a href=''https://developers.cloudflare.com/r2/'' target=''_blank'' rel=''noopener''>Cloudflare R2</a> pour vos images et fichiers.</p>
9526
+ <pre><code>npm create nextblock@latest mon-site
9527
+ cd mon-site
9528
+ npm run dev</code></pre>
9529
+ <p>Au premier prompt, choisissez <em>Managed Cloud Mode (Vercel + Supabase Cloud)</em> et nommez votre projet. Ouvrez ensuite <code>http://localhost:3000/setup</code> et laissez l''assistant faire le travail :</p>
9530
+ <ol class=''space-y-2''>
9531
+ <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>
9532
+ <li><strong>Ajoutez Cloudflare R2</strong> — saisissez votre identifiant de compte R2, le nom du bucket, la clé d''accès (access key ID), la clé secrète et l''URL publique du bucket pour servir vos images et fichiers.</li>
9533
+ <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>
9534
+ </ol>
9535
+ <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''>
9536
+ <p class=''mt-0 text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200''>Modules premium</p>
9537
+ <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>
9538
+ </div>
9539
+
9540
+ <h2 id=''git-clone''>Option 4 : Cloner le dépôt</h2>
9541
+ <p class=''mt-2 mb-6 flex flex-wrap items-center gap-x-3 gap-y-2 text-sm''><span class=''inline-flex items-center gap-2 rounded-full border border-emerald-200 bg-emerald-50 px-3 py-1 text-xs font-semibold uppercase tracking-wide text-emerald-700 dark:border-emerald-500/20 dark:bg-emerald-500/10 dark:text-emerald-200''>Étape 4 &middot; Avancé</span><span class=''text-slate-500 dark:text-slate-400''>Idéal pour les contributeurs et les équipes qui veulent personnaliser la plateforme. Nécessite Node.js et git.</span></p>
9542
+ <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 de celles et ceux qui veulent participer au projet — contributeurs, auteurs de plugins et équipes qui personnalisent la plateforme elle-même.</p>
9543
+ <pre><code>git clone https://github.com/nextblock-cms/nextblock.git
9544
+ cd nextblock
9545
+ npm install
9546
+ npx nx serve nextblock</code></pre>
9547
+ <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>
9548
+ <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''>
9549
+ <p class=''mt-0 text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200''>Vous préférez rester local ? Docker fonctionne ici aussi</p>
9550
+ <p class=''mt-3 mb-0 text-sm text-slate-700 dark:text-slate-200''>Pas besoin de comptes cloud pour développer sur le monorepo. Avec Docker Desktop démarré, une seule commande lance la même pile auto-hébergée que l''option 2 — Postgres, auth, stockage et le CMS — directement depuis votre clone :</p>
9551
+ <pre class=''mt-4 mb-0''><code>npm run docker:setup</code></pre>
9552
+ <p class=''mt-4 mb-0 text-sm text-slate-700 dark:text-slate-200''>Quand c''est terminé, ouvrez <code>http://localhost:3000</code> et créez votre administrateur. Notez que le monorepo n''a pas de <code>npm run dev</code> — utilisez <code>npx nx serve nextblock</code> (port 4200) pour le chemin cloud.</p>
9553
+ </div>
9554
+
9555
+ <h2 id=''after-install''>Après l''installation : vos 10 premières minutes</h2>
9556
+ <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>
9557
+ <ul class=''space-y-2''>
9558
+ <li><strong>Ajoutez votre identité visuelle</strong> — téléversez votre logo et définissez le titre du site.</li>
9559
+ <li><strong>Réglez votre pied de page</strong> — mention de copyright et navigation du pied de page.</li>
9560
+ <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>
9561
+ <li><strong>Extras optionnels</strong> — connectez vos outils d''analytics, activez la protection anti-bots et (sur Vercel) les mises à jour automatiques.</li>
9562
+ </ul>
9563
+ <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>
9564
+
9565
+ <h2 id=''faq''>FAQ d''installation</h2>
9566
+ <h3>Que dois-je installer ?</h3>
9567
+ <p>Rien pour le chemin Vercel — tout se passe dans le navigateur. Pour <code>npm create nextblock</code> en mode Docker : <a href=''https://nodejs.org'' target=''_blank'' rel=''noopener''>Node.js 20+</a> et Docker Desktop. Pour le mode cloud géré : Node.js 20+ ainsi qu''un projet Supabase et un bucket Cloudflare R2. Pour le dépôt cloné : Node.js 20+ et git (ajoutez Docker Desktop si vous voulez faire tourner la pile locale).</p>
9568
+ <h3>NextBlock est-il gratuit ?</h3>
9569
+ <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>
9570
+ <h3>Ai-je besoin d''un compte Supabase ?</h3>
9571
+ <p>Sur Vercel, la base de données est créée pour vous pendant le déploiement. Pour le chemin cloud géré <code>npm create nextblock</code> et le dépôt cloné, il vous faut un projet Supabase gratuit. Avec Docker — via le mode Docker du CLI ou <code>npm run docker:setup</code> dans le clone — aucun compte cloud n''est nécessaire.</p>
9572
+ <h3>Dois-je exécuter des migrations ou du SQL à la main ?</h3>
9573
+ <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>
9574
+ <h3>Puis-je changer de chemin plus tard ?</h3>
9575
+ <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>
9576
+ <h3>Comment mettre à jour NextBlock ?</h3>
9577
+ <p>Sur Vercel, l''étape Connect GitHub de la checklist active une synchronisation quotidienne automatique (cela nécessite un dépôt public). 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>
9578
+
9579
+ <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''>
9580
+ <p class=''mt-0 text-2xl font-semibold text-slate-900 dark:text-white''>Prêt à vous lancer ?</p>
9581
+ <p class=''text-sm text-slate-600 dark:text-slate-300''>Choisissez votre chemin ci-dessus, ou passez directement au plus rapide.</p>
9582
+ <div class=''mt-5 flex flex-wrap justify-center gap-3''>
9583
+ <a href=''https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fnextblock-cms%2Fnextblock&amp;project-name=nextblock&amp;repository-name=nextblock&amp;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>
9584
+ <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>
9585
+ </div>
9586
+ </div>'::text)),
9587
+ updated_at = now()
9588
+ WHERE post_id = 4
9589
+ AND content->>'html_content' LIKE '%NextBlock est un CMS open source et%';
9590
+
9591
+ -----------------------------------------------------------------------------
9592
+ -- 3. Page 7 (Shop EN) & Page 8 (Boutique FR) Expanded Body Content (>= 300 words)
9593
+ -----------------------------------------------------------------------------
9594
+ UPDATE public.blocks
9595
+ SET content = jsonb_set(content, '{column_blocks,0,1,content,html_content}', to_jsonb('<p style="text-align: center; color: var(--background); opacity: 0.9">Discover our selection of official commercial add-ons and developer tools for NextBlock CMS.</p><div class=''mt-8 text-slate-300 space-y-4 max-w-3xl mx-auto text-left''><h2 class=''text-2xl font-bold text-white mb-4''>Power Up Your Web Projects</h2><p>Welcome to the official NextBlock™ digital store. Here you can purchase licenses for our premium packages, including NextBlock™ Commerce and NextBlock™ Cortex AI. Every commercial license helps fund full-time open-source development on our core CMS while giving your team advanced tools to launch high-performance websites faster.</p><p>Our premium modules are designed to feel native from day one. You get clean code that fits right into your existing NextBlock project without third-party plugins or complex configuration. When you purchase a license from our store, you receive instant access to everything you need:</p><ul class=''space-y-2 list-disc pl-5''><li><strong>Full Source Code:</strong> Inspect, customize, and adapt the modules to your exact requirements.</li><li><strong>Perpetual Use:</strong> Use the software for your project with full peace of mind.</li><li><strong>Automated Updates:</strong> Enjoy smooth updates that match each new release of NextBlock and Next.js.</li><li><strong>Secure Checkout:</strong> Payments are processed safely with Stripe and Freemius with instant receipt generation.</li></ul><p>Whether you need multi-currency store features, automated sales tax calculations, or AI block generation in your editor, our modules deliver tested solutions that keep your Lighthouse scores at 100%.</p><p>All purchases include dedicated onboarding resources, detailed developer docs, and friendly technical support. If you ever run into an issue or need help wiring up a provider webhook, our core engineers are ready to assist you. We also offer a thirty-day refund policy so you can try our tools risk-free.</p><p>Have questions about license tiers, volume pricing, team seats, or custom agency usage? Contact our support team anytime. Our team is here to answer your questions and help your developers succeed. We are happy to help you pick the best plan for your company. Browse our featured products below to get started today.</p></div>'::text)),
9596
+ updated_at = now()
9597
+ WHERE page_id = 7
9598
+ AND content#>>'{column_blocks,0,1,content,html_content}' LIKE '%Discover our premium selection%';
9599
+
9600
+ UPDATE public.blocks
9601
+ SET content = jsonb_set(content, '{column_blocks,0,1,content,html_content}', to_jsonb('<p style="text-align: center; color: var(--background); opacity: 0.9">Découvrez nos extensions officielles et nos outils pour développeurs conçus pour le CMS NextBlock.</p><div class=''mt-8 text-slate-300 space-y-4 max-w-3xl mx-auto text-left''><h2 class=''text-2xl font-bold text-white mb-4''>Accélérez vos projets web</h2><p>Bienvenue sur la boutique officielle de NextBlock™. Vous pouvez acheter ici des licences pour nos modules professionnels, comme NextBlock™ Commerce et NextBlock™ Cortex AI. Chaque achat aide à financer le travail open-source sur le cœur du CMS. Il donne aussi à votre équipe des outils de pointe pour créer des sites rapides et fiables.</p><p>Nos modules premium s''intègrent sans effort à votre projet existant. Vous profitez d''un code propre et bien testé, sans plugin externe lourd ni réglage complexe. En choisissant nos outils, vous profitez immédiatement de nombreux avantages :</p><ul class=''space-y-2 list-disc pl-5''><li><strong>Code source complet :</strong> Lisez, adaptez et faites évoluer chaque bloc selon vos besoins métier.</li><li><strong>Licence perpétuelle :</strong> Utilisez le code sur votre projet en toute sérénité.</li><li><strong>Mises à jour suivies :</strong> Recevez les nouvelles versions au rythme de Next.js et de NextBlock.</li><li><strong>Paiement sécurisé :</strong> Les achats passent par Stripe et Freemius avec facture instantanée.</li></ul><p>Vous voulez vendre dans plusieurs devises ? Vous avez besoin du calcul automatique des taxes ? Vous voulez générer des blocs avec l''IA ? Nos modules offrent des solutions prêtes à l''emploi qui préservent vos scores Lighthouse à 100%.</p><p>Chaque commande donne accès à une documentation claire et à notre support technique. Si vous avez besoin d''aide pour brancher un webhook ou un mode de paiement, nos développeurs vous répondent rapidement. Notre équipe est à vos côtés pour vous faire gagner du temps. Nous proposons aussi une garantie satisfait ou remboursé de trente jours.</p><p>Vous avez des questions sur nos tarifs, les licences agence ou les remises en volume ? Écrivez à notre équipe à tout moment. Nous vous guiderons avec grand plaisir vers l''offre idéale pour votre entreprise. Découvrez dès aujourd''hui l''ensemble de nos produits ci-dessous pour bien démarrer votre projet.</p></div>'::text)),
9602
+ updated_at = now()
9603
+ WHERE page_id = 8
9604
+ AND content#>>'{column_blocks,0,1,content,html_content}' LIKE '%Decouvrez notre selection premium%';
9605
+
9606
+ -----------------------------------------------------------------------------
9607
+ -- 4. Page 9 (Privacy EN), Page 10 (Politique FR), Page 12 (Conditions FR) Readability
9608
+ -----------------------------------------------------------------------------
9609
+ UPDATE public.blocks
9610
+ SET content = jsonb_set(content, '{html_content}', to_jsonb('
9611
+ <h1>Privacy Policy</h1>
9612
+ <p><em>Last updated: June 4, 2026</em></p>
9613
+ <p>NextBlock™ CMS ("we", "us", or "our") respects your privacy. We protect your personal information under Quebec''s Law 25, the federal PIPEDA act, and Canada''s Anti-Spam Legislation (CASL).</p>
9614
+
9615
+ <h2>1. Person responsible for personal information</h2>
9616
+ <p>Our Privacy Officer oversees our compliance with privacy laws. You can reach them at <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>.</p>
9617
+
9618
+ <h2>2. What we collect</h2>
9619
+ <ul>
9620
+ <li><strong>Account information:</strong> Your name, email address, and login details when you register.</li>
9621
+ <li><strong>Usage and device data:</strong> Collected only with your consent through analytics tools.</li>
9622
+ <li><strong>Communications:</strong> Messages you send us and your newsletter choices.</li>
9623
+ </ul>
9624
+
9625
+ <h2>3. Why we collect it and your consent</h2>
9626
+ <p>We collect personal information for clear reasons: to provide our services, keep accounts secure, and reply to your messages. We use analytics and marketing tools only with your direct, opt-in consent. Under Law 25, optional cookies stay off until you choose to accept them. You can withdraw your consent at any time.</p>
9627
+
9628
+ <h2>4. Cookies and tracking technologies</h2>
9629
+ <p>Essential cookies keep the site running and require no consent. Analytics and marketing cookies load only after you opt in via our cookie banner. We record your choice to honor it and follow privacy rules.</p>
9630
+
9631
+ <h2>5. Disclosure and sharing</h2>
9632
+ <p>We do not sell your personal data. We share it only with trusted service providers who help us run the platform under strict confidentiality agreements, or when required by law.</p>
9633
+
9634
+ <h2>6. Retention</h2>
9635
+ <p>We keep personal information only as long as needed for the purposes described above or as required by law. After that, we securely delete or anonymize your data.</p>
9636
+
9637
+ <h2>7. Your rights</h2>
9638
+ <p>Under privacy laws, you have the right to view, correct, and delete your personal information. You can also withdraw consent or ask for a portable copy of your data. To use these rights, write to our Privacy Officer at <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>.</p>
9639
+
9640
+ <h2>8. Commercial electronic messages (CASL)</h2>
9641
+ <p>We send commercial emails only with your permission. Every email clearly identifies us and includes an easy unsubscribe link that takes effect right away.</p>
9642
+
9643
+ <h2>9. Safeguards</h2>
9644
+ <p>We use strong technical and physical protections to keep your data safe. These include encrypted connections and strict access controls to prevent loss, theft, and unauthorized access.</p>
9645
+
9646
+ <h2>10. Open-source software</h2>
9647
+ <p>NextBlock™ CMS is free open-source software under the AGPLv3 license. When you self-host NextBlock, you control your own server. You are responsible for the personal data on your deployment, and this policy is a helpful model you can adapt.</p>
9648
+
9649
+ <h2>11. Changes to this policy</h2>
9650
+ <p>We may update this policy over time. We announce important changes on our site and update the revision date at the top.</p>
9651
+
9652
+ <h2>12. Contact us</h2>
9653
+ <p>Have questions or complaints? Contact NextBlock™ at <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>. You can also contact the Commission d''accès à l''information du Québec or the Office of the Privacy Commissioner of Canada.</p>
9654
+ '::text)),
9655
+ updated_at = now()
9656
+ WHERE page_id = 9
9657
+ AND content->>'html_content' LIKE '%respects your privacy and is committed%';
9658
+
9659
+ UPDATE public.blocks
9660
+ SET content = jsonb_set(content, '{html_content}', to_jsonb('
9661
+ <h1>Politique de confidentialité</h1>
9662
+ <p><em>Dernière mise à jour : 4 juin 2026</em></p>
9663
+ <p>NextBlock™ CMS (« nous ») respecte votre vie privée. Nous protégeons vos renseignements personnels selon la Loi 25 du Québec, la loi fédérale LPRPDE et les règles canadiennes anti-pourriel (LCAP).</p>
9664
+
9665
+ <h2>1. Responsable de la protection des renseignements personnels</h2>
9666
+ <p>Notre responsable veille au respect des règles de confidentialité. Vous pouvez lui écrire à <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>.</p>
9667
+
9668
+ <h2>2. Renseignements que nous recueillons</h2>
9669
+ <ul>
9670
+ <li><strong>Renseignements de compte :</strong> Votre nom, votre courriel et vos accès lors de l''inscription.</li>
9671
+ <li><strong>Données d''utilisation et d''appareil :</strong> Recueillies avec votre accord via nos outils de mesure.</li>
9672
+ <li><strong>Communications :</strong> Vos messages reçus et vos choix de suivi par courriel.</li>
9673
+ </ul>
9674
+
9675
+ <h2>3. Finalités et consentement</h2>
9676
+ <p>Nous recueillons vos données pour des motifs clairs : faire fonctionner nos services, sécuriser les accès et vous répondre. Les outils d''analyse et de suivi ne s''activent qu''avec votre accord clair. Selon la Loi 25, les témoins optionnels restent coupés tant que vous ne les acceptez pas. Vous pouvez retirer votre accord en tout temps.</p>
9677
+
9678
+ <h2>4. Témoins et technologies de suivi</h2>
9679
+ <p>Les témoins essentiels assurent le bon fonctionnement du site. Ils ne demandent aucun accord préalable. Les témoins d''analyse se chargent seulement après votre choix sur notre bandeau. Nous gardons votre choix en mémoire pour le respecter.</p>
9680
+
9681
+ <h2>5. Communication à des tiers</h2>
9682
+ <p>Nous ne vendons jamais vos données personnelles. Nous les partageons uniquement avec des prestataires de confiance qui nous aident à faire tourner le site sous contrat de secret, ou si la loi l''impose.</p>
9683
+
9684
+ <h2>6. Conservation</h2>
9685
+ <p>Nous gardons vos données seulement le temps utile pour les buts décrits ou selon la loi. Ensuite, nous les effaçons ou nous les rendons anonymes de façon sûre.</p>
9686
+
9687
+ <h2>7. Vos droits</h2>
9688
+ <p>Vous avez le droit de lire, de corriger et de faire effacer vos données. Vous pouvez aussi retirer votre accord ou demander une copie de vos données. Pour exercer vos droits, écrivez à notre responsable à <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>.</p>
9689
+
9690
+ <h2>8. Messages électroniques commerciaux (LCAP)</h2>
9691
+ <p>Nous envoyons des courriels informatifs seulement avec votre accord. Chaque courriel montre notre nom et propose un lien simple pour vous désabonner d''un clic.</p>
9692
+
9693
+ <h2>9. Mesures de sécurité</h2>
9694
+ <p>Nous utilisons des moyens techniques et physiques solides pour garder vos données en sûreté. Cela comprend des échanges chiffrés et un contrôle strict des accès contre toute fuite ou vol.</p>
9695
+
9696
+ <h2>10. Logiciel libre</h2>
9697
+ <p>NextBlock™ CMS est un logiciel libre sous licence AGPLv3. Si vous hébergez NextBlock vous-même, vous gérez votre propre serveur. Vous êtes responsable des données sur votre instance, et ce texte est un modèle que vous pouvez adapter.</p>
9698
+
9699
+ <h2>11. Modifications</h2>
9700
+ <p>Nous pouvons mettre à jour ce texte au fil du temps. Les changements notables seront affichés sur le site avec la nouvelle date en tête de page.</p>
9701
+
9702
+ <h2>12. Nous joindre</h2>
9703
+ <p>Une question ou un avis ? Écrivez à NextBlock™ à <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>. Vous pouvez aussi joindre la Commission d''accès à l''information du Québec.</p>
9704
+ '::text)),
9705
+ updated_at = now()
9706
+ WHERE page_id = 10
9707
+ AND content->>'html_content' LIKE '%respecte votre vie privée et s''engage%';
9708
+
9709
+ UPDATE public.blocks
9710
+ SET content = jsonb_set(content, '{html_content}', to_jsonb('
9711
+ <h1>Conditions d''utilisation</h1>
9712
+ <p><em>Dernière mise à jour : 4 juin 2026</em></p>
9713
+
9714
+ <h2>1. Acceptation des conditions</h2>
9715
+ <p>En utilisant le CMS NextBlock™ et les services associés (les « Services »), vous acceptez ces conditions d''utilisation. Si vous refusez ces règles, veuillez ne pas utiliser les Services.</p>
9716
+
9717
+ <h2>2. Logiciel libre et à code source ouvert</h2>
9718
+ <p>NextBlock™ CMS est un logiciel libre sous <strong>licence publique générale GNU Affero, version 3 (AGPL-3.0)</strong> ou toute version ultérieure. Vous pouvez lancer, étudier, copier et faire évoluer le code selon cette licence. Le texte complet se trouve avec le code et en ligne sur <a href="https://www.gnu.org/licenses/agpl-3.0.html">gnu.org/licenses/agpl-3.0.html</a>.</p>
9719
+ <p>Droit d''auteur © 2025 NextBlock™ CMS.</p>
9720
+
9721
+ <h2>3. Disponibilité du code source</h2>
9722
+ <p>Selon l''article 13 de la licence AGPL-3.0, si vous modifiez NextBlock™ CMS et le mettez en ligne pour des usagers sur un réseau, vous devez offrir l''accès libre et sans frais au code source de votre version modifiée.</p>
9723
+
9724
+ <h2>4. Marques de commerce</h2>
9725
+ <p>La licence AGPL-3.0 donne de larges droits sur le code. Mais <strong>elle ne donne aucun droit</strong> sur nos noms et marques. Les termes « NextBlock™ », NextBlock™ CMS et les logos restent notre bien exclusif. Ils ne peuvent être repris sans accord écrit préalable.</p>
9726
+
9727
+ <h2>5. Comptes et utilisation acceptable</h2>
9728
+ <p>Si vous ouvrez un compte, vous gardez la garde de vos accès et de toute action faite sous votre nom. Vous devez nous prévenir vite en cas d''usage non permis. Vous vous engagez à ne pas bloquer les Services, ne pas forcer les accès et ne pas agir contre la loi.</p>
9729
+
9730
+ <h2>6. Absence de garantie</h2>
9731
+ <p>Selon l''article 15 de l''AGPL-3.0, le logiciel est fourni « tel quel », sans garantie d''aucune sorte, expresse ou tacite. Cela inclut les garanties de vente ou d''usage pour un besoin précis. Vous prenez sur vous les risques liés au bon emploi du logiciel.</p>
9732
+
9733
+ <h2>7. Limitation de responsabilité</h2>
9734
+ <p>Selon l''article 16 de l''AGPL-3.0 et dans la limite permise par la loi, aucun auteur ou tiers modifiant le code ne peut être tenu pour responsable de vos pertes ou dommages liés à l''usage du logiciel.</p>
9735
+
9736
+ <h2>8. Droit applicable</h2>
9737
+ <p>Ces conditions suivent les lois de la province de Québec et les lois du Canada applicables. Rien ici ne réduit vos droits stricts de consommateur selon ces lois.</p>
9738
+
9739
+ <h2>9. Modifications</h2>
9740
+ <p>Nous pouvons adapter ces règles au fil du temps. Les changements notables passeront sur le site. Votre usage continu vaut accord avec les nouvelles règles.</p>
9741
+
9742
+ <h2>10. Nous joindre</h2>
9743
+ <p>Une question sur ces conditions ? Écrivez à NextBlock™ CMS à <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>.</p>
9744
+ '::text)),
9745
+ updated_at = now()
9746
+ WHERE page_id = 12
9747
+ AND content->>'html_content' LIKE '%En accédant à NextBlock™ CMS et aux services%';
9748
+
9749
+ END $$;
9750
+
9751
+
9752
+ -- >>> FROM: 00000000000034_seed_seo_french_legal_readability.sql <<<
9753
+ -- Migration: 00000000000034_seed_seo_french_legal_readability.sql
9754
+ -- Description: Optimize French legal pages (politique de confidentialité & conditions d'utilisation) readability to achieve 100/100 Page SEO score.
9755
+ -- Safety: Forward-only, content-guarded updates that only apply to default seeded content.
9756
+
9757
+ DO $$
9758
+ BEGIN
9759
+ -- Page 10: Politique de confidentialité FR (Block 92)
9760
+ UPDATE public.blocks
9761
+ SET content = jsonb_set(content, '{html_content}', to_jsonb('
9762
+ <h1>Politique de confidentialité</h1>
9763
+ <p><em>Dernière mise à jour : 4 juin 2026</em></p>
9764
+ <p>NextBlock™ CMS (« nous ») respecte votre vie privée. Nous protégeons vos données personnelles selon la Loi 25 du Québec, la loi fédérale LPRPDE et les règles canadiennes anti-pourriel (LCAP).</p>
9765
+
9766
+ <h2>1. Responsable de la protection des données personnelles</h2>
9767
+ <p>Notre responsable veille au respect des règles de confidentialité. Vous pouvez lui écrire à <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>.</p>
9768
+
9769
+ <h2>2. Renseignements que nous recueillons</h2>
9770
+ <ul>
9771
+ <li><strong>Renseignements de compte</strong> &mdash; nom, adresse courriel et identifiants lors de l''inscription.</li>
9772
+ <li><strong>Données d''utilisation et d''appareil</strong> &mdash; recueillies uniquement avec votre consentement au moyen de outils web.</li>
9773
+ <li><strong>Communications</strong> &mdash; les messages que vous nous envoyez et vos préférences marketing.</li>
9774
+ </ul>
9775
+
9776
+ <h2>3. Finalités et consentement</h2>
9777
+ <p>Nous recueillons vos données pour des motifs clairs : faire fonctionner nos services, sécuriser les accès et vous répondre. Les outils d''analyse et de suivi ne s''activent qu''avec votre accord clair. Selon la Loi 25, les témoins optionnels restent coupés tant que vous ne les acceptez pas. Vous pouvez retirer votre accord en tout temps.</p>
9778
+
9779
+ <h2>4. Témoins et technologies de suivi</h2>
9780
+ <p>Les témoins essentiels assurent le bon usage du site. Ils ne demandent aucun accord préalable. Les témoins d''analyse se chargent seulement après votre choix sur notre bandeau. Nous gardons votre choix en mémoire pour le respecter.</p>
9781
+
9782
+ <h2>5. Partage des données</h2>
9783
+ <p>Nous ne vendons pas vos données personnelles. Nous ne les communiquons qu''à des fournisseurs qui nous aident à exploiter la plateforme, sous obligation de confidentialité, ou lorsque la loi l''exige.</p>
9784
+
9785
+ <h2>6. Conservation</h2>
9786
+ <p>Nous ne conservons les données personnelles que le temps nécessaire aux fins décrites ou exigé par la loi, après quoi ils sont détruits ou anonymisés sans risque.</p>
9787
+
9788
+ <h2>7. Vos droits</h2>
9789
+ <p>Vous avez le droit de lire, de corriger et de faire effacer vos données. Vous pouvez aussi retirer votre accord ou demander une copie de vos données. Pour exercer vos droits, écrivez à notre responsable à <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>.</p>
9790
+
9791
+ <h2>8. Messages électroniques commerciaux (LCAP)</h2>
9792
+ <p>Nous n''envoyons des messages électroniques commerciaux qu''avec votre consentement. Chaque message nous identifie et comporte un mécanisme de désabonnement fonctionnel que nous respectons rapidement.</p>
9793
+
9794
+ <h2>9. Mesures de sécurité</h2>
9795
+ <p>Nous employons des mesures physiques, organisationnelles et technologiques appropriées &mdash; dont le chiffrement en transit et le contrôle des accès &mdash; pour protéger vos données.</p>
9796
+
9797
+ <h2>10. Logiciel libre</h2>
9798
+ <p>NextBlock™ CMS est un logiciel libre sous licence AGPLv3. Si vous hébergez NextBlock vous-même, vous gérez votre propre serveur. Vous êtes responsable des données sur votre instance, et ce texte est un modèle que vous pouvez adapter.</p>
9799
+
9800
+ <h2>11. Modifications</h2>
9801
+ <p>Nous pouvons mettre à jour cette politique. Les changements importants seront communiqués sur le site et la date de mise à jour sera révisée.</p>
9802
+
9803
+ <h2>12. Nous joindre</h2>
9804
+ <p>Des questions ou des plaintes ? Contactez NextBlock™ CMS à <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>. Vous pouvez aussi vous adresser à la Commission d''accès à l''information du Québec.</p>
9805
+ '::text)),
9806
+ updated_at = now()
9807
+ WHERE id = 92
9808
+ AND page_id = 10
9809
+ AND content->>'html_content' LIKE '%Politique de confidentialité%';
9810
+
9811
+ -- Page 12: Conditions d'utilisation FR (Block 94)
9812
+ UPDATE public.blocks
9813
+ SET content = jsonb_set(content, '{html_content}', to_jsonb('
9814
+ <h1>Règles du service</h1>
9815
+ <p><em>Dernière mise à jour : 4 juin 2026</em></p>
9816
+
9817
+ <h2>1. Acceptation des conditions</h2>
9818
+ <p>En utilisant le CMS NextBlock™ et les services associés (les « Services »), vous acceptez ces règles du service. Si vous refusez ces règles, veuillez ne pas utiliser les Services.</p>
9819
+
9820
+ <h2>2. Logiciel libre et à code source ouvert</h2>
9821
+ <p>NextBlock™ CMS est un logiciel libre et à code source ouvert distribué sous la <strong>licence publique générale GNU Affero, version 3 (AGPL-3.0)</strong> ou, à votre choix, toute version ultérieure. Vous êtes libre d''exécuter, d''étudier, de partager et de modifier le logiciel selon les termes de cette licence. Une copie de la licence est fournie avec le logiciel et est aussi disponible à <a href="https://www.gnu.org/licenses/agpl-3.0.html">gnu.org/licenses/agpl-3.0.html</a>.</p>
9822
+ <p>Droit d''auteur © 2025 NextBlock™ CMS.</p>
9823
+
9824
+ <h2>3. Disponibilité du code source</h2>
9825
+ <p>Conformément à l''article 13 de l''AGPL-3.0, si vous exploitez une version modifiée de NextBlock™ CMS et la rendez accessible à des utilisateurs sur un réseau, vous devez offrir clairement à ces utilisateurs l''accès au code source correspondant de votre version modifiée, gratuitement, par un moyen usuel de copie de logiciels.</p>
9826
+
9827
+ <h2>4. Marques de commerce</h2>
9828
+ <p>L''AGPL-3.0 accorde de larges droits sur le code source du logiciel, mais <strong>n''accorde aucun droit</strong> sur nos noms commerciaux, marques de commerce ou marques de service. « NextBlock™ », le nom NextBlock™ CMS et les logos associés demeurent notre propriété et ne peuvent être utilisés d''une manière laissant entendre une approbation ou une affiliation sans notre autorisation écrite préalable.</p>
9829
+
9830
+ <h2>5. Comptes et utilisation acceptable</h2>
9831
+ <p>Si vous créez un compte, vous êtes responsable de la protection de vos identifiants et de toute activité effectuée à partir de votre compte, et vous vous engagez à nous aviser rapidement de toute utilisation non autorisée. Vous vous engagez à ne pas détourner les Services, notamment en tentant de les perturber, d''y accéder sans autorisation ou de les utiliser à des fins illégales.</p>
9832
+
9833
+ <h2>6. Absence de garantie</h2>
9834
+ <p>Selon l''article 15 de l''AGPL-3.0, le logiciel est fourni « tel quel », sans garantie d''aucune sorte, expresse ou tacite. Cela inclut les garanties de vente ou d''usage pour un besoin précis. Vous prenez sur vous les risques liés au bon emploi du logiciel.</p>
9835
+
9836
+ <h2>7. Limitation de devoir</h2>
9837
+ <p>Comme l''énonce l''article 16 de l''AGPL-3.0, et dans toute la mesure permise par la loi applicable, en aucun cas un titulaire de droits d''auteur ou toute autre partie qui modifie ou transmet le logiciel ne saurait être tenu responsable envers vous de dommages, y compris tout dommage général, spécial, accessoire ou consécutif liés à l''usage du code.</p>
9838
+
9839
+ <h2>8. Droit applicable</h2>
9840
+ <p>Ces conditions suivent les lois de la province de Québec et les lois du Canada applicables. Rien ici ne réduit vos droits stricts de consommateur selon ces lois.</p>
9841
+
9842
+ <h2>9. Modifications</h2>
9843
+ <p>Nous pouvons réviser ces conditions de temps à autre. Les changements importants seront communiqués au moyen des Services, et l''utilisation continue des Services après leur entrée en vigueur vaut acceptation.</p>
9844
+
9845
+ <h2>10. Nous joindre</h2>
9846
+ <p>Des questions sur ces conditions ? Contactez NextBlock™ CMS à <a href="mailto:{{privacy_email}}">{{privacy_email}}</a>.</p>
9847
+ '::text)),
9848
+ updated_at = now()
9849
+ WHERE id = 94
9850
+ AND page_id = 12
9851
+ AND content->>'html_content' LIKE '%Conditions d''utilisation%';
9852
+
9853
+ END $$;
9854
+
9855
+
9856
+ -- >>> FROM: 00000000000035_digital_products_seo_optimizations.sql <<<
9857
+ -- Migration: 00000000000035_digital_products_seo_optimizations.sql
9858
+ -- Purpose: Set meta_title and meta_description for the 2 real digital products (EN + FR)
9859
+ -- and optimize their block heading levels and copy readability to achieve 100/100 SEO scores.
9860
+ -- Safety: Append-only, forward-only, content-guarded updates.
9861
+
9862
+
9863
+ -- 1. Digital Products SEO Metadata (Titles & Descriptions)
9864
+ -- NextBlock Cortex AI - Cortex AI License (EN)
9865
+ UPDATE public.products
9866
+ SET meta_title = 'NextBlock Cortex AI License | Native AI Content Engine',
9867
+ meta_description = 'Add native AI copywriting, real-time block translation, and structure refactoring to your NextBlock editor with our BYOK Cortex AI license.',
9868
+ updated_at = NOW()
9869
+ WHERE id = 'd48a4bb4-5119-4576-9c1d-32c404dd84f8';
9870
+
9871
+ -- Licence NextBlock™ Cortex AI (FR)
9872
+ UPDATE public.products
9873
+ SET meta_title = 'Licence NextBlock Cortex AI | Moteur IA pour Éditeur',
9874
+ meta_description = 'Intégrez la rédaction assistée par IA, la traduction de blocs et l''optimisation de structure dans NextBlock grâce à la licence Cortex AI.',
9875
+ updated_at = NOW()
9876
+ WHERE id = '69848224-a6d6-43c9-9748-f41a8e8e424b';
9877
+
9878
+ -- NextBlock Commerce Pro - Commerce License (EN)
9879
+ UPDATE public.products
9880
+ SET meta_title = 'NextBlock Commerce Pro | Global Next.js Storefronts',
9881
+ meta_description = 'Launch high-performance digital and physical stores with headless Stripe checkout, Freemius licensing, and multi-currency pricing in NextBlock.',
9882
+ updated_at = NOW()
9883
+ WHERE id = 'ed86bd77-da61-4e6f-826c-956f9a55b7aa';
9884
+
9885
+ -- Licence NextBlock™ Commerce Pro (FR)
9886
+ UPDATE public.products
9887
+ SET meta_title = 'Licence NextBlock Commerce Pro | E-Commerce Next.js',
9888
+ meta_description = 'Créez des boutiques Next.js performantes avec paiement Stripe headless, licences logicielles Freemius et gestion multi-devises dans NextBlock.',
9889
+ updated_at = NOW()
9890
+ WHERE id = '5c9e1b99-eeed-4fe0-adfa-31e81004c2f9';
9891
+
9892
+ -- 2. Digital Products Block Content & Heading Optimizations
9893
+ -- Block ID 39
9894
+ UPDATE public.blocks
9895
+ SET content = '{"padding":{"top":"xl","bottom":"xl"},"background":{"type":"gradient","gradient":{"type":"linear","stops":[{"color":"#064e3b","position":0},{"color":"#0f172a","position":100}],"direction":"135deg"}},"column_gap":"xl","column_blocks":[[{"block_type":"text","content":{"html_content":"<p class=\\"text-xs uppercase tracking-[0.3em] text-emerald-400 font-semibold mb-4\\">Moteur E-Commerce d''Entreprise</p><h2 class=\\"text-3xl sm:text-4xl font-extrabold text-white tracking-tight mb-4\\">Faites de Next.js une Boutique Mondiale.</h2><p class=\\"text-base text-slate-300 leading-relaxed\\">Commerce Pro est un moteur de boutique moderne conçu pour NextBlock. Il gère vos catalogues physiques et vos produits numériques avec rapidité. Tout tourne sur votre propre serveur avec un contrôle total de vos données.</p>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"rounded-2xl border border-emerald-700 bg-slate-950 p-6 shadow-xl sm:p-8\\"><h3 class=\\"text-lg font-bold text-white mb-4\\">Pourquoi choisir Commerce Pro</h3><ul class=\\"space-y-3 text-sm text-slate-300\\"><li class=\\"flex items-start gap-3\\"><span class=\\"text-emerald-400 font-bold\\">✓</span><span><strong>Multi-Devises</strong> — Taux de change en direct, règles d''arrondis et détection automatique du pays de l''acheteur.</span></li><li class=\\"flex items-start gap-3\\"><span class=\\"text-emerald-400 font-bold\\">✓</span><span><strong>Taxes automatiques</strong> — Prise en charge native de Stripe Tax pour respecter les règles fiscales locales.</span></li><li class=\\"flex items-start gap-3\\"><span class=\\"text-emerald-400 font-bold\\">✓</span><span><strong>Catalogue hybride</strong> — Vendez des produits physiques avec gestion de stock et des licences logicielles.</span></li></ul></div>"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":2},"vertical_alignment":"center"}'::jsonb,
9896
+ updated_at = NOW()
9897
+ WHERE id = 39;
9898
+
9899
+ -- Block ID 41
9900
+ UPDATE public.blocks
9901
+ SET content = '{"padding":{"top":"lg","bottom":"lg"},"background":{"type":"solid","color":"transparent"},"column_gap":"lg","column_blocks":[[{"block_type":"text","content":{"html_content":"<div class=\\"h-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm transition-colors hover:border-emerald-300 dark:border-slate-800 dark:bg-slate-900\\"><div class=\\"mb-4 flex h-10 w-10 items-center justify-center rounded-xl bg-emerald-50 text-xl dark:bg-emerald-950\\">💳</div><h4 class=\\"text-lg font-bold text-foreground mb-2\\">Checkout Stripe Headless</h4><p class=\\"text-sm text-muted-foreground leading-relaxed\\">Paiement direct et sécurisé pour un ou plusieurs articles. Les commandes se valident automatiquement grâce aux webhooks Stripe.</p></div>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"h-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm transition-colors hover:border-emerald-300 dark:border-slate-800 dark:bg-slate-900\\"><div class=\\"mb-4 flex h-10 w-10 items-center justify-center rounded-xl bg-emerald-50 text-xl dark:bg-emerald-950\\">🔑</div><h4 class=\\"text-lg font-bold text-foreground mb-2\\">Licences Numériques Freemius</h4><p class=\\"text-sm text-muted-foreground leading-relaxed\\">Distribuez vos logiciels, activez vos clés et gérez les périodes d''essai SaaS. Tout fonctionne directement avec Freemius sans souci.</p></div>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"h-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm transition-colors hover:border-emerald-300 dark:border-slate-800 dark:bg-slate-900\\"><div class=\\"mb-4 flex h-10 w-10 items-center justify-center rounded-xl bg-emerald-50 text-xl dark:bg-emerald-950\\">🛍️</div><h4 class=\\"text-lg font-bold text-foreground mb-2\\">Merchandising Visuel</h4><p class=\\"text-sm text-muted-foreground leading-relaxed\\">Concevez vos fiches produits, mettez en valeur vos promotions et créez vos rayons directement dans l''éditeur de blocs.</p></div>"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":2,"desktop":3},"vertical_alignment":"stretch"}'::jsonb,
9902
+ updated_at = NOW()
9903
+ WHERE id = 41;
9904
+
9905
+ -- Block ID 42
9906
+ UPDATE public.blocks
9907
+ SET content = '{"padding":{"top":"xl","bottom":"xl"},"background":{"type":"gradient","gradient":{"type":"linear","stops":[{"color":"#0f172a","position":0},{"color":"#064e3b","position":100}],"direction":"135deg"}},"column_gap":"xl","column_blocks":[[{"block_type":"text","content":{"html_content":"<p class=\\"text-xs uppercase tracking-[0.3em] text-emerald-400 font-semibold mb-4\\">Sous le capot</p><h3 class=\\"text-2xl font-bold text-white mb-4\\">Conçu pour la production à grande échelle</h3><p class=\\"text-sm text-slate-300 leading-relaxed mb-4\\">Commerce Pro a été pensé dès le début pour les boutiques actives. Chaque route API est mise en cache, et les requêtes SQL sont optimisées.</p><p class=\\"text-sm text-slate-300 leading-relaxed\\">Que vous vendiez des logiciels ou des biens réels, votre site reste fluide. Il absorbe les pics de trafic sans ralentissement.</p>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"space-y-4\\"><div class=\\"p-5 rounded-xl border border-slate-700 bg-slate-900\\"><h4 class=\\"text-sm font-bold text-white mb-1\\">Gestion des commandes</h4><p class=\\"text-xs text-slate-400 leading-relaxed\\">Suivez chaque commande du panier à la livraison. Mises à jour d''état, e-mails de confirmation et retours sont gérés d''office.</p></div><div class=\\"p-5 rounded-xl border border-slate-700 bg-slate-900\\"><h4 class=\\"text-sm font-bold text-white mb-1\\">Catégories de produits</h4><p class=\\"text-xs text-slate-400 leading-relaxed\\">Organisez vos articles avec des URLs claires, des photos et des filtres de langues. Pilotez tout depuis le tableau de bord du CMS.</p></div><div class=\\"p-5 rounded-xl border border-slate-700 bg-slate-900\\"><h4 class=\\"text-sm font-bold text-white mb-1\\">Boutiques multilingues</h4><p class=\\"text-xs text-slate-400 leading-relaxed\\">Traduisez vos articles et vos rayons dans toutes les langues. Les stocks sont partagés tout en gardant des métadonnées SEO propres.</p></div></div>"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":2},"vertical_alignment":"center"}'::jsonb,
9908
+ updated_at = NOW()
9909
+ WHERE id = 42;
9910
+
9911
+ -- Block ID 43
9912
+ UPDATE public.blocks
9913
+ SET content = '{"padding":{"top":"xl","bottom":"xl"},"background":{"type":"gradient","gradient":{"type":"linear","stops":[{"color":"#064e3b","position":0},{"color":"#022c22","position":100}],"direction":"135deg"}},"column_gap":"none","column_blocks":[[{"block_type":"heading","content":{"level":2,"textAlign":"center","textColor":"background","text_content":"Prêt à lancer votre boutique ?"}},{"block_type":"text","content":{"html_content":"<p class=\\"text-center text-emerald-100 max-w-xl mx-auto mt-2 mb-6\\">Commencez à vendre dès aujourd''hui avec Commerce Pro. Multi-devises, conforme aux taxes et rapide dès l''installation.</p>"}},{"block_type":"button","content":{"url":"https://nextblock.dev/product/nextblock-commerce-pro-commerce-license","size":"lg","text":"Acheter Commerce Pro","variant":"secondary","position":"center"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":1},"vertical_alignment":"center"}'::jsonb,
9914
+ updated_at = NOW()
9915
+ WHERE id = 43;
9916
+
9917
+ -- Block ID 49
9918
+ UPDATE public.blocks
9919
+ SET content = '{"padding":{"top":"xl","bottom":"xl"},"background":{"type":"gradient","gradient":{"type":"linear","stops":[{"color":"#1e1b4b","position":0},{"color":"#0f172a","position":100}],"direction":"135deg"}},"column_gap":"xl","column_blocks":[[{"block_type":"text","content":{"html_content":"<p class=\\"text-xs uppercase tracking-[0.3em] text-violet-400 font-semibold mb-4\\">Couche d''Intelligence IA</p><h2 class=\\"text-3xl sm:text-4xl font-extrabold text-white tracking-tight mb-4\\">Boostez votre éditeur avec l''IA native.</h2><p class=\\"text-base text-slate-300 leading-relaxed\\">Cortex AI apporte la puissance des grands modèles de langage dans votre éditeur. Rédigez des articles, améliorez vos textes et traduisez des pages en quelques clics. Les blocs créés restent stables, rapides et fidèles à votre charte.</p>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"rounded-2xl border border-violet-700 bg-slate-950 p-6 shadow-xl sm:p-8\\"><h3 class=\\"text-lg font-bold text-white mb-4\\">OpenRouter et architecture BYOK</h3><ul class=\\"space-y-3 text-sm text-slate-300\\"><li class=\\"flex items-start gap-3\\"><span class=\\"text-violet-400 font-bold\\">✓</span><span><strong>Apportez votre clé API</strong> — Maîtrisez vos coûts avec vos propres clés OpenRouter. Aucun frais caché.</span></li><li class=\\"flex items-start gap-3\\"><span class=\\"text-violet-400 font-bold\\">✓</span><span><strong>Contexte structuré</strong> — L''IA comprend la mise en page et les colonnes pour des sorties toujours précises.</span></li><li class=\\"flex items-start gap-3\\"><span class=\\"text-violet-400 font-bold\\">✓</span><span><strong>Liberté de modèle</strong> — Choisissez librement entre Claude, GPT et les modèles open-source sans changer de code.</span></li></ul></div>"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":2},"vertical_alignment":"center"}'::jsonb,
9920
+ updated_at = NOW()
9921
+ WHERE id = 49;
9922
+
9923
+ -- Block ID 51
9924
+ UPDATE public.blocks
9925
+ SET content = '{"padding":{"top":"lg","bottom":"lg"},"background":{"type":"solid","color":"transparent"},"column_gap":"lg","column_blocks":[[{"block_type":"text","content":{"html_content":"<div class=\\"h-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm transition-colors hover:border-violet-300 dark:border-slate-800 dark:bg-slate-900\\"><div class=\\"mb-4 flex h-10 w-10 items-center justify-center rounded-xl bg-violet-50 text-xl dark:bg-violet-950\\">✍️</div><h4 class=\\"text-lg font-bold text-foreground mb-2\\">Rédaction en un clic</h4><p class=\\"text-sm text-muted-foreground leading-relaxed\\">Rédigez des guides, ajustez vos titres et créez des appels à l''action. Cortex AI adopte votre ton et écrit un texte clair.</p></div>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"h-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm transition-colors hover:border-violet-300 dark:border-slate-800 dark:bg-slate-900\\"><div class=\\"mb-4 flex h-10 w-10 items-center justify-center rounded-xl bg-violet-50 text-xl dark:bg-violet-950\\">🔄</div><h4 class=\\"text-lg font-bold text-foreground mb-2\\">Refactorisation de structure</h4><p class=\\"text-sm text-muted-foreground leading-relaxed\\">Ajustez vos colonnes, ajoutez des grilles et réorganisez vos sections. Cortex AI génère des données valides sans effort.</p></div>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"h-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm transition-colors hover:border-violet-300 dark:border-slate-800 dark:bg-slate-900\\"><div class=\\"mb-4 flex h-10 w-10 items-center justify-center rounded-xl bg-violet-50 text-xl dark:bg-violet-950\\">🌐</div><h4 class=\\"text-lg font-bold text-foreground mb-2\\">Traduction automatique</h4><p class=\\"text-sm text-muted-foreground leading-relaxed\\">Traduisez vos pages complètes entre le français et l''anglais. Cortex AI conserve vos mises en page et styles intacts.</p></div>"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":2,"desktop":3},"vertical_alignment":"stretch"}'::jsonb,
9926
+ updated_at = NOW()
9927
+ WHERE id = 51;
9928
+
9929
+ -- Block ID 52
9930
+ UPDATE public.blocks
9931
+ SET content = '{"padding":{"top":"xl","bottom":"xl"},"background":{"type":"gradient","gradient":{"type":"linear","stops":[{"color":"#0f172a","position":0},{"color":"#1e1b4b","position":100}],"direction":"135deg"}},"column_gap":"xl","column_blocks":[[{"block_type":"text","content":{"html_content":"<p class=\\"text-xs uppercase tracking-[0.3em] text-violet-400 font-semibold mb-4\\">Comment ça marche</p><h3 class=\\"text-2xl font-bold text-white mb-4\\">Une IA qui comprend les blocs</h3><p class=\\"text-sm text-slate-300 leading-relaxed mb-4\\">La plupart des outils IA créent du texte brut sans structure. Cortex AI a été pensé pour l''éditeur de NextBlock. Il analyse vos blocs, vos colonnes et vos options visuelles.</p><p class=\\"text-sm text-slate-300 leading-relaxed\\">Cette approche évite les erreurs de balisage et les données invalides. Votre équipe obtient des rendus élégants sur mobile et ordinateur.</p>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"space-y-4\\"><div class=\\"p-5 rounded-xl border border-slate-700 bg-slate-900\\"><h4 class=\\"text-sm font-bold text-white mb-1\\">Génération de contenu</h4><p class=\\"text-xs text-slate-400 leading-relaxed\\">Produisez du contenu percutant pour vos pages et articles. L''assistant respecte votre style et délivre des textes fluides.</p></div><div class=\\"p-5 rounded-xl border border-slate-700 bg-slate-900\\"><h4 class=\\"text-sm font-bold text-white mb-1\\">Optimisation SEO</h4><p class=\\"text-xs text-slate-400 leading-relaxed\\">Rédigez des titres et méta descriptions de qualité. Cortex AI vérifie la lisibilité et les mots clés avant publication.</p></div><div class=\\"p-5 rounded-xl border border-slate-700 bg-slate-900\\"><h4 class=\\"text-sm font-bold text-white mb-1\\">Conception axée sur la vie privée</h4><p class=\\"text-xs text-slate-400 leading-relaxed\\">Vos requêtes vont directement à votre fournisseur d''IA via votre clé privée. Vos données ne sont jamais stockées ni revendues.</p></div></div>"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":2},"vertical_alignment":"center"}'::jsonb,
9932
+ updated_at = NOW()
9933
+ WHERE id = 52;
9934
+
9935
+ -- Block ID 53
9936
+ UPDATE public.blocks
9937
+ SET content = '{"padding":{"top":"xl","bottom":"xl"},"background":{"type":"gradient","gradient":{"type":"linear","stops":[{"color":"#312e81","position":0},{"color":"#1e1b4b","position":100}],"direction":"135deg"}},"column_gap":"none","column_blocks":[[{"block_type":"heading","content":{"level":2,"textAlign":"center","textColor":"background","text_content":"Prêt à ajouter l''IA à votre éditeur ?"}},{"block_type":"text","content":{"html_content":"<p class=\\"text-center text-violet-100 max-w-xl mx-auto mt-2 mb-6\\">Libérez la puissance de la création de contenu avec l''IA. Connectez votre clé, protégez vos données et rédigez vite.</p>"}},{"block_type":"button","content":{"url":"https://nextblock.dev/product/nextblock-cortex-ai-cortex-ai-license","size":"lg","text":"Acheter Cortex AI","variant":"secondary","position":"center"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":1},"vertical_alignment":"center"}'::jsonb,
9938
+ updated_at = NOW()
9939
+ WHERE id = 53;
9940
+
9941
+ -- Block ID 65
9942
+ UPDATE public.blocks
9943
+ SET content = '{"padding":{"top":"xl","bottom":"xl"},"background":{"type":"gradient","gradient":{"type":"linear","stops":[{"color":"#064e3b","position":0},{"color":"#0f172a","position":100}],"direction":"135deg"}},"column_gap":"xl","column_blocks":[[{"block_type":"text","content":{"html_content":"<p class=\\"text-xs uppercase tracking-[0.3em] text-emerald-400 font-semibold mb-4\\">Enterprise E-Commerce Engine</p><h2 class=\\"text-3xl sm:text-4xl font-extrabold text-white tracking-tight mb-4\\">Turn Next.js Into a Global Storefront.</h2><p class=\\"text-base text-slate-300 leading-relaxed\\">Commerce Pro is a fast store engine built for NextBlock. It helps teams sell physical goods and digital downloads with ease. Everything runs on your own server with total data ownership and zero extra fees.</p>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"rounded-2xl border border-emerald-700 bg-slate-950 p-6 shadow-xl sm:p-8\\"><h3 class=\\"text-lg font-bold text-white mb-4\\">Why Teams Choose Commerce Pro</h3><ul class=\\"space-y-3 text-sm text-slate-300\\"><li class=\\"flex items-start gap-3\\"><span class=\\"text-emerald-400 font-bold\\">✓</span><span><strong>Multi-Currency Pricing</strong> — Live exchange rates, clear charm pricing, and automatic visitor country detection.</span></li><li class=\\"flex items-start gap-3\\"><span class=\\"text-emerald-400 font-bold\\">✓</span><span><strong>Simple Tax Rules</strong> — Native Stripe Tax support calculates local taxes automatically during checkout.</span></li><li class=\\"flex items-start gap-3\\"><span class=\\"text-emerald-400 font-bold\\">✓</span><span><strong>Hybrid Product Catalog</strong> — Sell physical goods with stock counts alongside digital software license keys.</span></li></ul></div>"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":2},"vertical_alignment":"center"}'::jsonb,
9944
+ updated_at = NOW()
9945
+ WHERE id = 65;
9946
+
9947
+ -- Block ID 67
9948
+ UPDATE public.blocks
9949
+ SET content = '{"padding":{"top":"lg","bottom":"lg"},"background":{"type":"solid","color":"transparent"},"column_gap":"lg","column_blocks":[[{"block_type":"text","content":{"html_content":"<div class=\\"h-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm transition-colors hover:border-emerald-300 dark:border-slate-800 dark:bg-slate-900\\"><div class=\\"mb-4 flex h-10 w-10 items-center justify-center rounded-xl bg-emerald-50 text-xl dark:bg-emerald-950\\">💳</div><h4 class=\\"text-lg font-bold text-foreground mb-2\\">Headless Stripe Checkout</h4><p class=\\"text-sm text-muted-foreground leading-relaxed\\">Fast checkout flows for single or multiple items. Orders process automatically through secure webhooks with zero friction.</p></div>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"h-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm transition-colors hover:border-emerald-300 dark:border-slate-800 dark:bg-slate-900\\"><div class=\\"mb-4 flex h-10 w-10 items-center justify-center rounded-xl bg-emerald-50 text-xl dark:bg-emerald-950\\">🔑</div><h4 class=\\"text-lg font-bold text-foreground mb-2\\">Freemius Digital Licensing</h4><p class=\\"text-sm text-muted-foreground leading-relaxed\\">Deliver software files, issue license keys, and manage SaaS free trials easily. Everything connects directly to Freemius.</p></div>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"h-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm transition-colors hover:border-emerald-300 dark:border-slate-800 dark:bg-slate-900\\"><div class=\\"mb-4 flex h-10 w-10 items-center justify-center rounded-xl bg-emerald-50 text-xl dark:bg-emerald-950\\">🛍️</div><h4 class=\\"text-lg font-bold text-foreground mb-2\\">Visual Merchandising</h4><p class=\\"text-sm text-muted-foreground leading-relaxed\\">Design custom product pages, highlight special deals, and build shopping grids right inside the visual block editor.</p></div>"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":2,"desktop":3},"vertical_alignment":"stretch"}'::jsonb,
9950
+ updated_at = NOW()
9951
+ WHERE id = 67;
9952
+
9953
+ -- Block ID 68
9954
+ UPDATE public.blocks
9955
+ SET content = '{"padding":{"top":"xl","bottom":"xl"},"background":{"type":"gradient","gradient":{"type":"linear","stops":[{"color":"#0f172a","position":0},{"color":"#064e3b","position":100}],"direction":"135deg"}},"column_gap":"xl","column_blocks":[[{"block_type":"text","content":{"html_content":"<p class=\\"text-xs uppercase tracking-[0.3em] text-emerald-400 font-semibold mb-4\\">Under The Hood</p><h3 class=\\"text-2xl font-bold text-white mb-4\\">Built for Production Scale</h3><p class=\\"text-sm text-slate-300 leading-relaxed mb-4\\">Commerce Pro was built from day one for busy storefronts. Every API path is cached near your users, and database queries use fast indexes.</p><p class=\\"text-sm text-slate-300 leading-relaxed\\">Whether you sell digital downloads or retail goods, your storefront loads fast. It handles high traffic spikes without slow downs or crashes.</p>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"space-y-4\\"><div class=\\"p-5 rounded-xl border border-slate-700 bg-slate-900\\"><h4 class=\\"text-sm font-bold text-white mb-1\\">Order Management</h4><p class=\\"text-xs text-slate-400 leading-relaxed\\">Track customer orders from cart to shipping. Automatic status updates, buyer receipts, and refunds work right out of the box.</p></div><div class=\\"p-5 rounded-xl border border-slate-700 bg-slate-900\\"><h4 class=\\"text-sm font-bold text-white mb-1\\">Product Categories</h4><p class=\\"text-xs text-slate-400 leading-relaxed\\">Organize products with clean web addresses, category images, and full multi-language tags. Manage it all from the CMS dashboard.</p></div><div class=\\"p-5 rounded-xl border border-slate-700 bg-slate-900\\"><h4 class=\\"text-sm font-bold text-white mb-1\\">Multi-Language Storefronts</h4><p class=\\"text-xs text-slate-400 leading-relaxed\\">Translate products and category pages into any language. Each language shares inventory while keeping its own SEO metadata.</p></div></div>"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":2},"vertical_alignment":"center"}'::jsonb,
9956
+ updated_at = NOW()
9957
+ WHERE id = 68;
9958
+
9959
+ -- Block ID 69
9960
+ UPDATE public.blocks
9961
+ SET content = '{"padding":{"top":"xl","bottom":"xl"},"background":{"type":"gradient","gradient":{"type":"linear","stops":[{"color":"#064e3b","position":0},{"color":"#022c22","position":100}],"direction":"135deg"}},"column_gap":"none","column_blocks":[[{"block_type":"heading","content":{"level":2,"textAlign":"center","textColor":"background","text_content":"Ready to launch your storefront?"}},{"block_type":"text","content":{"html_content":"<p class=\\"text-center text-emerald-100 max-w-xl mx-auto mt-2 mb-6\\">Start selling today with Commerce Pro. It is multi-currency, tax-compliant, and lightning-fast out of the box.</p>"}},{"block_type":"button","content":{"url":"#","size":"lg","text":"Purchase Commerce Pro","variant":"secondary","position":"center"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":1},"vertical_alignment":"center"}'::jsonb,
9962
+ updated_at = NOW()
9963
+ WHERE id = 69;
9964
+
9965
+ -- Block ID 70
9966
+ UPDATE public.blocks
9967
+ SET content = '{"padding":{"top":"xl","bottom":"xl"},"background":{"type":"gradient","gradient":{"type":"linear","stops":[{"color":"#1e1b4b","position":0},{"color":"#0f172a","position":100}],"direction":"135deg"}},"column_gap":"xl","column_blocks":[[{"block_type":"text","content":{"html_content":"<p class=\\"text-xs uppercase tracking-[0.3em] text-violet-400 font-semibold mb-4\\">AI Intelligence Layer</p><h2 class=\\"text-3xl sm:text-4xl font-extrabold text-white tracking-tight mb-4\\">Supercharge Your Editor with AI.</h2><p class=\\"text-base text-slate-300 leading-relaxed\\">Cortex AI brings powerful language models directly into your editor. You can create content, edit blog drafts, and translate full pages in seconds. It writes clean block data rather than raw text, keeping your layouts stable and fast.</p>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"rounded-2xl border border-violet-700 bg-slate-950 p-6 shadow-xl sm:p-8\\"><h3 class=\\"text-lg font-bold text-white mb-4\\">OpenRouter &amp; BYOK Architecture</h3><ul class=\\"space-y-3 text-sm text-slate-300\\"><li class=\\"flex items-start gap-3\\"><span class=\\"text-violet-400 font-bold\\">✓</span><span><strong>Bring Your Own Key</strong> — You control costs using your own OpenRouter tokens. There are no hidden fees or markups.</span></li><li class=\\"flex items-start gap-3\\"><span class=\\"text-violet-400 font-bold\\">✓</span><span><strong>Block-Aware Prompts</strong> — Models receive structured context. They see headings, columns, and layout rules for accurate outputs.</span></li><li class=\\"flex items-start gap-3\\"><span class=\\"text-violet-400 font-bold\\">✓</span><span><strong>Model Flexibility</strong> — Switch freely between Claude, GPT, and open-source models without changing code.</span></li></ul></div>"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":2},"vertical_alignment":"center"}'::jsonb,
9968
+ updated_at = NOW()
9969
+ WHERE id = 70;
9970
+
9971
+ -- Block ID 72
9972
+ UPDATE public.blocks
9973
+ SET content = '{"padding":{"top":"lg","bottom":"lg"},"background":{"type":"solid","color":"transparent"},"column_gap":"lg","column_blocks":[[{"block_type":"text","content":{"html_content":"<div class=\\"h-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm transition-colors hover:border-violet-300 dark:border-slate-800 dark:bg-slate-900\\"><div class=\\"mb-4 flex h-10 w-10 items-center justify-center rounded-xl bg-violet-50 text-xl dark:bg-violet-950\\">✍️</div><h4 class=\\"text-lg font-bold text-foreground mb-2\\">One-Click Copywriting</h4><p class=\\"text-sm text-muted-foreground leading-relaxed\\">Write blog posts, polish headlines, and craft calls to action. Cortex AI matches your brand voice and writes clear prose with ease.</p></div>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"h-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm transition-colors hover:border-violet-300 dark:border-slate-800 dark:bg-slate-900\\"><div class=\\"mb-4 flex h-10 w-10 items-center justify-center rounded-xl bg-violet-50 text-xl dark:bg-violet-950\\">🔄</div><h4 class=\\"text-lg font-bold text-foreground mb-2\\">Structure Refactoring</h4><p class=\\"text-sm text-muted-foreground leading-relaxed\\">Reorganize layout grids, split columns, and reorder sections. Cortex AI produces valid block schemas that render safely every time.</p></div>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"h-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm transition-colors hover:border-violet-300 dark:border-slate-800 dark:bg-slate-900\\"><div class=\\"mb-4 flex h-10 w-10 items-center justify-center rounded-xl bg-violet-50 text-xl dark:bg-violet-950\\">🌐</div><h4 class=\\"text-lg font-bold text-foreground mb-2\\">Automated Translation</h4><p class=\\"text-sm text-muted-foreground leading-relaxed\\">Translate entire pages between languages with one click. Cortex AI keeps your styles, nested sections, and media links intact.</p></div>"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":2,"desktop":3},"vertical_alignment":"stretch"}'::jsonb,
9974
+ updated_at = NOW()
9975
+ WHERE id = 72;
9976
+
9977
+ -- Block ID 73
9978
+ UPDATE public.blocks
9979
+ SET content = '{"padding":{"top":"xl","bottom":"xl"},"background":{"type":"gradient","gradient":{"type":"linear","stops":[{"color":"#0f172a","position":0},{"color":"#1e1b4b","position":100}],"direction":"135deg"}},"column_gap":"xl","column_blocks":[[{"block_type":"text","content":{"html_content":"<p class=\\"text-xs uppercase tracking-[0.3em] text-violet-400 font-semibold mb-4\\">How It Works</p><h3 class=\\"text-2xl font-bold text-white mb-4\\">AI That Understands Blocks</h3><p class=\\"text-sm text-slate-300 leading-relaxed mb-4\\">Most AI tools only generate flat text strings. Cortex AI is built specifically for NextBlock editors. It reads your full page structure, column arrays, and style options.</p><p class=\\"text-sm text-slate-300 leading-relaxed\\">This deep connection prevents broken markup and invalid data. Your team gets clean results that look great on desktop and mobile screens right away.</p>"}}],[{"block_type":"text","content":{"html_content":"<div class=\\"space-y-4\\"><div class=\\"p-5 rounded-xl border border-slate-700 bg-slate-900\\"><h4 class=\\"text-sm font-bold text-white mb-1\\">Content Generation</h4><p class=\\"text-xs text-slate-400 leading-relaxed\\">Create engaging copy for marketing pages and help docs. The assistant follows your editorial style guide and produces clean text.</p></div><div class=\\"p-5 rounded-xl border border-slate-700 bg-slate-900\\"><h4 class=\\"text-sm font-bold text-white mb-1\\">SEO Optimization</h4><p class=\\"text-xs text-slate-400 leading-relaxed\\">Draft concise meta titles and meta descriptions automatically. Cortex AI checks keyword density and reading ease before you publish.</p></div><div class=\\"p-5 rounded-xl border border-slate-700 bg-slate-900\\"><h4 class=\\"text-sm font-bold text-white mb-1\\">Privacy-First Design</h4><p class=\\"text-xs text-slate-400 leading-relaxed\\">Your content goes directly to your chosen provider via private API keys. We never store, log, or train on your private data.</p></div></div>"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":2},"vertical_alignment":"center"}'::jsonb,
9980
+ updated_at = NOW()
9981
+ WHERE id = 73;
9982
+
9983
+ -- Block ID 74
9984
+ UPDATE public.blocks
9985
+ SET content = '{"padding":{"top":"xl","bottom":"xl"},"background":{"type":"gradient","gradient":{"type":"linear","stops":[{"color":"#312e81","position":0},{"color":"#1e1b4b","position":100}],"direction":"135deg"}},"column_gap":"none","column_blocks":[[{"block_type":"heading","content":{"level":2,"textAlign":"center","textColor":"background","text_content":"Ready to add AI to your editor?"}},{"block_type":"text","content":{"html_content":"<p class=\\"text-center text-violet-100 max-w-xl mx-auto mt-2 mb-6\\">Unlock the full power of AI-driven content creation. Connect your key, protect your privacy, and edit faster today.</p>"}},{"block_type":"button","content":{"url":"#","size":"lg","text":"Purchase Cortex AI","variant":"secondary","position":"center"}}]],"container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":1},"vertical_alignment":"center"}'::jsonb,
9986
+ updated_at = NOW()
9987
+ WHERE id = 74;
9988
+
9989
+
9990
+
9991
+ -- >>> FROM: 00000000000036_seed_posts_missing_seo_metadata.sql <<<
9992
+ -- Migration: 00000000000036_seed_posts_missing_seo_metadata.sql
9993
+ -- Purpose: Set meta_title and meta_description for remaining seeded blog posts
9994
+ -- (how-nextblock-works, comment-nextblock-fonctionne, nextblock-commerce-guide, guide-commerce-nextblock)
9995
+ -- so all 9 seeded posts achieve a 100/100 SEO score.
9996
+ -- Safety: Append-only, forward-only, content-guarded updates.
9997
+
9998
+
9999
+ UPDATE public.posts
10000
+ SET meta_title = 'How NextBlock™ Works: Architecture & Under the Hood',
10001
+ meta_description = 'Explore the architecture behind NextBlock: monorepo packages, typed block registry, Supabase database, and modern Next.js editor stack.',
10002
+ updated_at = NOW()
10003
+ WHERE slug = 'how-nextblock-works'
10004
+ AND meta_title IS NULL;
10005
+
10006
+ UPDATE public.posts
10007
+ SET meta_title = 'Comment fonctionne NextBlock™ : Architecture et Moteur',
10008
+ meta_description = 'Découvrez les fondations de NextBlock : monorepo, registre de blocs typés, base de données Supabase et moteur d''édition Next.js moderne.',
10009
+ updated_at = NOW()
10010
+ WHERE slug = 'comment-nextblock-fonctionne'
10011
+ AND meta_title IS NULL;
10012
+
10013
+ UPDATE public.posts
10014
+ SET meta_title = 'The Complete NextBlock™ Commerce Guide | Headless Store',
10015
+ meta_description = 'Build global e-commerce with NextBlock: manage products, configure multi-currency pricing, and accept payments with headless Stripe checkout.',
10016
+ updated_at = NOW()
10017
+ WHERE slug = 'nextblock-commerce-guide'
10018
+ AND meta_title IS NULL;
10019
+
10020
+ UPDATE public.posts
10021
+ SET meta_title = 'Guide Complet du Commerce avec NextBlock™ | E-Commerce',
10022
+ meta_description = 'Développez votre boutique avec NextBlock : gestion de produits, tarifs multi-devises et tunnel de paiement headless avec Stripe Checkout.',
10023
+ updated_at = NOW()
10024
+ WHERE slug = 'guide-commerce-nextblock'
10025
+ AND meta_title IS NULL;
10026
+
10027
+
10028
+
10029
+ -- Step D: Record the applied migrations in history (truncated in Step B) so
10030
+ -- \`npm run db:migrate:check\` reports up to date instead of listing every file as pending.
10031
+ INSERT INTO supabase_migrations.schema_migrations (version, name) VALUES
10032
+ ('00000000000000', 'baseline_schema'),
10033
+ ('00000000000001', 'baseline_constraints_and_indexes'),
10034
+ ('00000000000002', 'baseline_security_and_grants'),
10035
+ ('00000000000003', 'baseline_seed'),
10036
+ ('00000000000004', 'default_logo_email_safe'),
10037
+ ('00000000000005', 'add_custom_canonical'),
10038
+ ('00000000000006', 'home_live_demo_promo'),
10039
+ ('00000000000007', 'home_live_demo_promo_copy_fix'),
10040
+ ('00000000000008', 'setup_article_reorder'),
10041
+ ('00000000000009', 'home_live_demo_promo_contrast'),
10042
+ ('00000000000010', 'drop_github_username'),
10043
+ ('00000000000011', 'language_detection_admin_only'),
10044
+ ('00000000000012', 'cortex_ai_stock_photo_settings'),
10045
+ ('00000000000013', 'youtube_nocookie_embeds'),
10046
+ ('00000000000014', 'site_themes'),
10047
+ ('00000000000015', 'scheduled_publishing'),
10048
+ ('00000000000016', 'product_revisions_and_revision_baseline'),
10049
+ ('00000000000017', 'cortex_ai_mcp_server'),
10050
+ ('00000000000018', 'site_scripts'),
10051
+ ('00000000000019', 'site_script_revisions'),
10052
+ ('00000000000020', 'updating_article'),
10053
+ ('00000000000021', 'updating_article_git_merge'),
10054
+ ('00000000000022', 'updating_article_accuracy'),
10055
+ ('00000000000023', 'updating_article_layout_not_host'),
10056
+ ('00000000000024', 'updating_article_newline_fix'),
10057
+ ('00000000000025', 'rebrand_nextblock_dev'),
10058
+ ('00000000000026', 'product_inquiries'),
10059
+ ('00000000000027', 'message_threads'),
10060
+ ('00000000000028', 'interaction_replies'),
10061
+ ('00000000000029', 'form_endpoints_default_empty'),
10062
+ ('00000000000030', 'seo_redirects_and_robots'),
10063
+ ('00000000000031', 'seo_robots_settings_admin_only'),
10064
+ ('00000000000032', 'seed_seo_score_optimizations'),
10065
+ ('00000000000033', 'seed_seo_score_optimizations_p2'),
10066
+ ('00000000000034', 'seed_seo_french_legal_readability'),
10067
+ ('00000000000035', 'digital_products_seo_optimizations'),
10068
+ ('00000000000036', 'seed_posts_missing_seo_metadata')
10069
+ ON CONFLICT (version) DO NOTHING;
10070
+
10071
+ -- Step E: Anchor preserved profiles
10072
+ INSERT INTO public.profiles (id, updated_at, full_name, avatar_url, website, role)
10073
+ SELECT preserved_user.id, NULL, NULL, NULL, NULL, 'ADMIN'
10074
+ FROM (
10075
+ VALUES
10076
+ ('63a8aa07-ef6e-4cc7-bafa-ece023c74366'::uuid),
10077
+ ('e3a2c121-70a4-4239-a9df-f70ce717f5a1'::uuid)
10078
+ ) AS preserved_user(id)
10079
+ WHERE EXISTS (SELECT 1 FROM auth.users WHERE id = preserved_user.id)
10080
+ AND NOT EXISTS (SELECT 1 FROM public.profiles WHERE id = preserved_user.id);
10081
+
10082
+ -- Step F: Re-assert the "first admin exists" flag. The sandbox preserves its demo
10083
+ -- ADMIN users across the wipe (Steps A & E), but the reseeded baseline resets
10084
+ -- is_admin_created to 'false' and handle_new_user() only flips it on a NEW auth.users
10085
+ -- INSERT -- which never fires for preserved users. Without this the proxy setup-gate
10086
+ -- funnels ALL sandbox traffic (including this reset cron on its next run) to /setup even
10087
+ -- though admins already exist. Guarded on an ADMIN profile actually being present.
10088
+ UPDATE public.site_settings
10089
+ SET value = 'true'::jsonb
10090
+ WHERE key = 'is_admin_created'
10091
+ AND EXISTS (SELECT 1 FROM public.profiles WHERE role = 'ADMIN'::public.user_role);
10092
+
10093
+ `;