@nextblock-cms/db 0.18.7 → 0.19.0

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,67 +1,67 @@
1
- -- 02009: French versions of the two Cortex AI posts that only existed in English.
2
- --
3
- -- 'cortex-ai-mcp-connection-guide' (the MCP setup guide the home page links to) and
4
- -- 'nextblock-cortex-ai-guide' had no row in the French translation group, so the
5
- -- language switcher had nothing to offer and the French home page could only link
6
- -- to English. Each post is inserted once per install, in the SAME translation group
7
- -- as its English original, with the same feature image and publish date, followed by
8
- -- its single text block: the English markup translated node by node (code samples and
9
- -- configuration snippets untouched), links pointing at the French slugs.
10
- --
11
- -- Guards: runs only where the English original exists and no French row does, so a
12
- -- re-run (or an install whose operator already translated the post) inserts nothing.
13
- -- The identity sequences are re-synced first because the seed inserts explicit ids,
14
- -- which leaves the sequence behind the table on a fresh install.
15
-
16
- DO $$
17
- DECLARE
18
- v_fr bigint;
19
- v_post bigint;
20
- BEGIN
21
- SELECT id INTO v_fr FROM public.languages WHERE code = 'fr' LIMIT 1;
22
- IF v_fr IS NULL THEN
23
- RAISE NOTICE '02009: no French language row; nothing to do.';
24
- RETURN;
25
- END IF;
26
-
27
- PERFORM setval('public.posts_id_seq', COALESCE((SELECT MAX(id) FROM public.posts), 0) + 1, false);
28
- PERFORM setval('public.blocks_id_seq', COALESCE((SELECT MAX(id) FROM public.blocks), 0) + 1, false);
29
-
30
- -- guide-connexion-mcp-cortex-ai (translation group a7c4e2d1-3b58-4f96-9e0a-6d2c8b1f5a73)
31
- IF EXISTS (SELECT 1 FROM public.posts WHERE translation_group_id = 'a7c4e2d1-3b58-4f96-9e0a-6d2c8b1f5a73'::uuid AND language_id <> v_fr)
32
- AND NOT EXISTS (SELECT 1 FROM public.posts WHERE translation_group_id = 'a7c4e2d1-3b58-4f96-9e0a-6d2c8b1f5a73'::uuid AND language_id = v_fr)
33
- AND NOT EXISTS (SELECT 1 FROM public.posts WHERE slug = 'guide-connexion-mcp-cortex-ai' AND language_id = v_fr) THEN
34
- INSERT INTO public.posts
35
- (language_id, author_id, title, slug, label, excerpt, subtitle, status, published_at,
36
- meta_title, meta_description, feature_image_id, version, translation_group_id)
37
- VALUES
38
- (v_fr, NULL, 'Connecter Claude à NextBlock CMS via MCP, depuis Cursor ou Claude Code', 'guide-connexion-mcp-cortex-ai', 'Cortex AI', 'Enregistrez /api/mcp dans Claude Code ou Cursor et laissez votre propre abonnement IA lire le schéma, ébaucher des mises en page et gérer les pages dans NextBlock.', 'Un guide pratique du serveur MCP de Cortex AI : ce qu''il règle, les outils qu''il expose et la configuration exacte pour localhost et la production.',
39
- 'published', '2026-09-10T14:20:17.461154+00:00'::timestamptz,
40
- 'Connecter Claude à NextBlock CMS via MCP | Guide Cursor', 'Apprenez à connecter Claude à NextBlock CMS avec le Model Context Protocol. Enregistrez /api/mcp dans Claude Code ou Cursor pour inspecter les schémas et bâtir des mises en page.',
41
- (SELECT id FROM public.media WHERE id = '8b2e5d1c-9a47-4f3b-8e6d-1c7a2b9d4e50'::uuid),
42
- 1, 'a7c4e2d1-3b58-4f96-9e0a-6d2c8b1f5a73'::uuid)
43
- RETURNING id INTO v_post;
44
-
45
- INSERT INTO public.blocks (post_id, language_id, block_type, content, "order")
46
- VALUES (v_post, v_fr, 'text', $nb${"html_content":"<p class='text-lg leading-8 text-slate-700 dark:text-slate-300'>Ce guide vous montre comment connecter Claude à NextBlock CMS avec un standard ouvert plutôt qu'un plugin propriétaire. Cortex AI transforme votre site en serveur Model Context Protocol. Claude Code, Cursor, ChatGPT et Gemini peuvent ensuite lire le schéma de votre base de données, ébaucher des mises en page et mettre à jour la navigation depuis leur propre fenêtre de clavardage. Vous payez l'abonnement IA que vous avez déjà, sans aucune majoration sur les jetons entre les deux.</p><div class='grid gap-4 md:grid-cols-3 my-10'><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'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-sky-700 dark:text-sky-200'>Un seul bloc de configuration</p><p class='mt-3 mb-0 text-xl font-semibold text-slate-900 dark:text-white'>Configuré en quelques minutes.</p><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Collez une seule entrée JSON dans Claude Code, Cursor ou VS Code. La carte des réglages du CMS l'écrit pour vous.</p></div><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'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-indigo-700 dark:text-indigo-200'>Essai gratuit</p><p class='mt-3 mb-0 text-xl font-semibold text-slate-900 dark:text-white'>30 jours, sans carte de crédit.</p><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Le CMS est gratuit pour toujours. Cortex AI, qui inclut le serveur MCP, commence par un essai gratuit de 30 jours.</p></div><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'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200'>Brouillons en direct</p><p class='mt-3 mb-0 text-xl font-semibold text-slate-900 dark:text-white'>Rien ne part par accident.</p><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Chaque mise en page écrite par l'agent arrive sous forme de brouillon. Un éditeur la révise et clique sur Publier.</p></div></div><p>Chaque prompt devient un enregistrement structuré en base de données plutôt qu'un tas de code généré. Vos éditeurs gardent un CMS visuel, vos développeurs gardent une application Next.js 16 propre, et rien n'est mis en ligne tant que quelqu'un ne clique pas sur Publier.</p><h2>Le problème des constructeurs web IA traditionnels</h2><p>Les constructeurs par prompt comme Lovable, Bolt et v0 impressionnent le premier jour. Vous décrivez une page et obtenez une application React fonctionnelle en quelques minutes. Les ennuis commencent le deuxième jour.</p><div class='not-prose my-8 overflow-hidden rounded-3xl border border-slate-200 bg-white shadow-sm dark:border-slate-800 dark:bg-slate-900'><div class='flex flex-wrap items-end justify-between gap-3 px-5 pt-6 pb-4'><div><p class='text-xs font-semibold uppercase tracking-[0.22em] text-slate-500 dark:text-slate-400'>Côte à côte</p><p class='mt-1 text-xl font-semibold text-slate-900 dark:text-white'>Les outils de prototype face à NextBlock.</p></div><p class='text-xs text-slate-500 dark:text-slate-400'>Ce qui se passe après le premier prompt.</p></div><div class='overflow-x-auto'><table class='w-full min-w-[640px] border-collapse'><thead><tr class='bg-slate-50 dark:bg-slate-950/60'><th scope='col' class='px-5 py-3 text-left text-xs font-semibold uppercase tracking-[0.2em] text-slate-500 dark:text-slate-400'>Ce que vous obtenez</th><th scope='col' class='px-5 py-3 text-left text-xs font-semibold uppercase tracking-[0.2em] text-rose-600 dark:text-rose-300'>Lovable, Bolt, v0</th><th scope='col' class='bg-emerald-50/60 px-5 py-3 text-left text-xs font-semibold uppercase tracking-[0.2em] text-emerald-700 dark:bg-emerald-500/10 dark:text-emerald-200'>NextBlock</th></tr></thead><tbody><tr class='border-t border-slate-200 dark:border-slate-800'><th scope='row' class='px-5 py-4 text-left align-top text-sm font-semibold text-foreground'>Jour un</th><td class='px-5 py-4 align-top text-sm text-muted-foreground'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-rose-100 text-xs font-bold text-rose-600 dark:bg-rose-500/20 dark:text-rose-300'>&#10007;</span>Du code jetable sans couche de contenu.</td><td class='bg-emerald-50/60 px-5 py-4 align-top text-sm text-foreground dark:bg-emerald-500/10'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-xs font-bold text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-200'>&#10003;</span>Un site Next.js 16 et Supabase en production, avec un CMS.</td></tr><tr class='border-t border-slate-200 dark:border-slate-800'><th scope='row' class='px-5 py-4 text-left align-top text-sm font-semibold text-foreground'>Changer un titre</th><td class='px-5 py-4 align-top text-sm text-muted-foreground'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-rose-100 text-xs font-bold text-rose-600 dark:bg-rose-500/20 dark:text-rose-300'>&#10007;</span>Un autre prompt ou une autre pull request.</td><td class='bg-emerald-50/60 px-5 py-4 align-top text-sm text-foreground dark:bg-emerald-500/10'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-xs font-bold text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-200'>&#10003;</span>Un éditeur le tape dans un éditeur de type Notion.</td></tr><tr class='border-t border-slate-200 dark:border-slate-800'><th scope='row' class='px-5 py-4 text-left align-top text-sm font-semibold text-foreground'>Brouillons et révisions</th><td class='px-5 py-4 align-top text-sm text-muted-foreground'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-rose-100 text-xs font-bold text-rose-600 dark:bg-rose-500/20 dark:text-rose-300'>&#10007;</span>Un historique du code seulement.</td><td class='bg-emerald-50/60 px-5 py-4 align-top text-sm text-foreground dark:bg-emerald-500/10'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-xs font-bold text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-200'>&#10003;</span>Brouillons en direct, révisions et restauration en un clic.</td></tr><tr class='border-t border-slate-200 dark:border-slate-800'><th scope='row' class='px-5 py-4 text-left align-top text-sm font-semibold text-foreground'>Traductions et SEO</th><td class='px-5 py-4 align-top text-sm text-muted-foreground'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-rose-100 text-xs font-bold text-rose-600 dark:bg-rose-500/20 dark:text-rose-300'>&#10007;</span>Pas inclus.</td><td class='bg-emerald-50/60 px-5 py-4 align-top text-sm text-foreground dark:bg-emerald-500/10'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-xs font-bold text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-200'>&#10003;</span>Traduction bloc par bloc et vérifications SEO pendant que vous écrivez.</td></tr><tr class='border-t border-slate-200 dark:border-slate-800'><th scope='row' class='px-5 py-4 text-left align-top text-sm font-semibold text-foreground'>Coûts de l'IA</th><td class='px-5 py-4 align-top text-sm text-muted-foreground'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-rose-100 text-xs font-bold text-rose-600 dark:bg-rose-500/20 dark:text-rose-300'>&#10007;</span>Des crédits de plateforme, achetés à l'outil.</td><td class='bg-emerald-50/60 px-5 py-4 align-top text-sm text-foreground dark:bg-emerald-500/10'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-xs font-bold text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-200'>&#10003;</span>Votre propre abonnement via MCP, sans majoration.</td></tr><tr class='border-t border-slate-200 dark:border-slate-800'><th scope='row' class='px-5 py-4 text-left align-top text-sm font-semibold text-foreground'>Prix</th><td class='px-5 py-4 align-top text-sm text-muted-foreground'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-rose-100 text-xs font-bold text-rose-600 dark:bg-rose-500/20 dark:text-rose-300'>&#10007;</span>Un forfait mensuel.</td><td class='bg-emerald-50/60 px-5 py-4 align-top text-sm text-foreground dark:bg-emerald-500/10'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-xs font-bold text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-200'>&#10003;</span>CMS gratuit. Cortex AI après un essai gratuit de 30 jours.</td></tr></tbody></table></div></div><p>NextBlock prend le contre-pied des outils de prototype. L'IA devrait ébaucher le site, et les humains devraient en être propriétaires. La connexion MCP est le point de rencontre de ces deux mondes.</p><h2>Comment Cortex AI utilise le Model Context Protocol (MCP)</h2><p>Le Model Context Protocol est un standard ouvert qui donne des outils aux agents IA. Un client comme Claude Code liste les outils offerts par un serveur, les appelle avec des arguments typés et lit des résultats typés en retour. Cortex AI embarque ce serveur dans votre installation NextBlock, à l'adresse <code>/api/mcp</code>.</p><div class='not-prose my-12 overflow-hidden rounded-[2rem] border border-slate-800 bg-slate-950 p-6 shadow-2xl sm:p-8'><p class='text-[0.65rem] font-semibold uppercase tracking-[0.3em] text-indigo-300'>Model Context Protocol · NextBlock Cortex AI</p><p class='mt-2 text-2xl font-extrabold text-white sm:text-3xl'>Du prompt à la production, sans redéploiement.</p><p class='mt-2 max-w-2xl text-sm text-slate-400'>Votre client IA parle au CMS via un standard ouvert. Le résultat atterrit sous forme de données, pas de code à héberger.</p><div class='mt-8 grid gap-4 md:grid-cols-2 xl:grid-cols-4'><div class='relative flex flex-col rounded-2xl border border-sky-400/40 bg-white/5 p-5'><span class='block h-1 w-12 rounded-full bg-sky-400'></span><p class='mt-4 text-[0.65rem] font-semibold uppercase tracking-[0.25em] text-sky-300'>Étape 1 · Votre client IA</p><p class='mt-2 text-lg font-bold leading-snug text-white'>Prompt</p><p class='mt-1 text-xs text-slate-400'>N'importe quel client MCP que vous payez déjà.</p><div class='mt-4 flex-1 text-sm text-slate-200'><div class='flex flex-wrap gap-2'><span class='rounded-full border border-sky-400/40 bg-sky-400/10 px-3 py-1 text-xs font-semibold text-slate-100'>Claude Code</span><span class='rounded-full border border-sky-400/40 bg-sky-400/10 px-3 py-1 text-xs font-semibold text-slate-100'>Cursor</span><span class='rounded-full border border-sky-400/40 bg-sky-400/10 px-3 py-1 text-xs font-semibold text-slate-100'>ChatGPT</span><span class='rounded-full border border-sky-400/40 bg-sky-400/10 px-3 py-1 text-xs font-semibold text-slate-100'>Gemini</span></div><p class='mt-4 text-xs text-slate-300'>Un seul bloc JSON dans la configuration de votre client enregistre le serveur. C'est toute la configuration.</p></div><p class='mt-5 rounded-lg bg-sky-400/10 px-3 py-2 text-center text-[0.7rem] font-semibold text-sky-300'>Votre abonnement · aucune majoration sur les jetons</p><span class='absolute -right-4 top-1/2 hidden -translate-y-1/2 text-xl text-slate-500 xl:block' aria-hidden='true'>→</span></div><div class='relative flex flex-col rounded-2xl border border-violet-400/40 bg-white/5 p-5'><span class='block h-1 w-12 rounded-full bg-violet-400'></span><p class='mt-4 text-[0.65rem] font-semibold uppercase tracking-[0.25em] text-violet-300'>Étape 2 · /api/mcp</p><p class='mt-2 text-lg font-bold leading-snug text-white'>Serveur MCP Cortex AI</p><p class='mt-1 text-xs text-slate-400'>Streamable HTTP · jeton bearer · à portée limitée.</p><div class='mt-4 flex-1 text-sm text-slate-200'><div class='space-y-1.5'><code class='block rounded-md bg-white/5 px-3 py-1.5 font-mono text-xs text-violet-100'>get_database_schema</code><code class='block rounded-md bg-white/5 px-3 py-1.5 font-mono text-xs text-violet-100'>generate_jsonb_layout</code><code class='block rounded-md bg-white/5 px-3 py-1.5 font-mono text-xs text-violet-100'>update_site_navigation</code><code class='block rounded-md bg-white/5 px-3 py-1.5 font-mono text-xs text-violet-100'>query_site_analytics</code><code class='block rounded-md bg-white/5 px-3 py-1.5 font-mono text-xs text-violet-100'>search_stock_media</code></div></div><p class='mt-5 rounded-lg bg-violet-400/10 px-3 py-2 text-center text-[0.7rem] font-semibold text-violet-300'>5 outils de contrat · 29 outils typés</p><span class='absolute -right-4 top-1/2 hidden -translate-y-1/2 text-xl text-slate-500 xl:block' aria-hidden='true'>→</span></div><div class='relative flex flex-col rounded-2xl border border-emerald-400/40 bg-white/5 p-5'><span class='block h-1 w-12 rounded-full bg-emerald-400'></span><p class='mt-4 text-[0.65rem] font-semibold uppercase tracking-[0.25em] text-emerald-300'>Étape 3 · PostgreSQL</p><p class='mt-2 text-lg font-bold leading-snug text-white'>Blocs JSONB validés</p><p class='mt-1 text-xs text-slate-400'>Supabase · un schéma Zod par bloc.</p><div class='mt-4 flex-1 text-sm text-slate-200'><div class='space-y-2'><p class='flex items-start gap-2 text-sm text-slate-200'><span class='mt-0.5 inline-flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-emerald-400/20 text-[0.6rem] font-bold text-emerald-300'>&#10003;</span><span>Mis en attente comme brouillon en direct.</span></p><p class='flex items-start gap-2 text-sm text-slate-200'><span class='mt-0.5 inline-flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-emerald-400/20 text-[0.6rem] font-bold text-emerald-300'>&#10003;</span><span>Les éditeurs peaufinent dans le CMS visuel.</span></p><p class='flex items-start gap-2 text-sm text-slate-200'><span class='mt-0.5 inline-flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-emerald-400/20 text-[0.6rem] font-bold text-emerald-300'>&#10003;</span><span>Révisions et vérifications SEO intégrées.</span></p></div></div><p class='mt-5 rounded-lg bg-emerald-400/10 px-3 py-2 text-center text-[0.7rem] font-semibold text-emerald-300'>Rien n'est en ligne avant la publication</p><span class='absolute -right-4 top-1/2 hidden -translate-y-1/2 text-xl text-slate-500 xl:block' aria-hidden='true'>→</span></div><div class='relative flex flex-col rounded-2xl border border-amber-400/40 bg-white/5 p-5'><span class='block h-1 w-12 rounded-full bg-amber-400'></span><p class='mt-4 text-[0.65rem] font-semibold uppercase tracking-[0.25em] text-amber-300'>Étape 4 · Next.js 16</p><p class='mt-2 text-lg font-bold leading-snug text-white'>Page publiée</p><p class='mt-1 text-xs text-slate-400'>Server Components · cache en périphérie.</p><div class='mt-4 flex-1 text-sm text-slate-200'><div class='space-y-2'><p class='flex items-start gap-2 text-sm text-slate-200'><span class='mt-0.5 inline-flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-amber-400/20 text-[0.6rem] font-bold text-amber-300'>&#10003;</span><span>Ni reconstruction, ni redéploiement.</span></p><p class='flex items-start gap-2 text-sm text-slate-200'><span class='mt-0.5 inline-flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-amber-400/20 text-[0.6rem] font-bold text-amber-300'>&#10003;</span><span>Scores Lighthouse de 100/100 par défaut.</span></p><p class='flex items-start gap-2 text-sm text-slate-200'><span class='mt-0.5 inline-flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-amber-400/20 text-[0.6rem] font-bold text-amber-300'>&#10003;</span><span>Le même site le deuxième jour.</span></p></div></div><p class='mt-5 rounded-lg bg-amber-400/10 px-3 py-2 text-center text-[0.7rem] font-semibold text-amber-300'>Un site web plus un CMS</p></div></div><div class='mt-6 h-1.5 rounded-full bg-gradient-to-r from-sky-400 via-violet-400 to-amber-400'></div><p class='mt-4 text-center text-sm text-slate-300'>Les éditeurs gardent un CMS visuel. Les développeurs gardent une base de code Next.js 16 propre. L'agent ne touche ni à l'un ni à l'autre.</p></div><p>Le point de terminaison parle Streamable HTTP. Votre client envoie des messages JSON-RPC dans une requête HTTPS ordinaire, et le serveur répond dans la même réponse. Aucun flux SSE de longue durée à surveiller, aucun SDK à installer côté serveur. Les mêmes 29 outils typés qui alimentent Cortex AI dans l'éditeur sont exposés sur le réseau, si bien que l'agent de votre IDE et celui de votre CMS ne divergent jamais.</p><div class='grid gap-4 md:grid-cols-2 my-8'><div class='rounded-3xl border border-violet-200/70 bg-violet-50/70 p-6 dark:border-violet-500/20 dark:bg-violet-500/10'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200'>Règle de sécurité no 1</p><p class='mt-3 mb-0 text-xl font-semibold text-slate-900 dark:text-white'>Les mises en page attendent en brouillon en direct.</p><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Les outils de mise en page écrivent des brouillons : rien n'atteint les visiteurs tant qu'un éditeur ne publie pas.</p></div><div class='rounded-3xl border border-blue-200/70 bg-blue-50/70 p-6 dark:border-blue-500/20 dark:bg-blue-500/10'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-blue-700 dark:text-blue-200'>Règle de sécurité no 2</p><p class='mt-3 mb-0 text-xl font-semibold text-slate-900 dark:text-white'>Chaque jeton porte une portée.</p><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Un jeton en lecture seule ne voit même pas les outils capables de modifier des données. Les outils de modification sont absents de sa liste.</p></div></div><h3>Outils MCP de base de données disponibles</h3><p>Cinq noms d'outils forment le contrat MCP public. Chacun renvoie vers un exécuteur Cortex AI testé.</p><div class='grid gap-4 md:grid-cols-2 my-8'><div class='rounded-3xl border border-slate-200 bg-white p-5 shadow-sm dark:border-white/10 dark:bg-white/5'><div class='flex items-center justify-between gap-3'><code class='rounded-lg bg-violet-50 px-2.5 py-1 text-sm text-violet-700 dark:bg-violet-500/15 dark:text-violet-200'>get_database_schema</code><span class='rounded-full border px-2.5 py-0.5 text-[0.65rem] font-semibold uppercase tracking-[0.18em] border-emerald-300 text-emerald-700 dark:border-emerald-500/40 dark:text-emerald-200'>lecture</span></div><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Retourne chaque table que l'agent peut lire ou modifier, avec colonnes, clés primaires et indicateurs de lecture seule.</p></div><div class='rounded-3xl border border-slate-200 bg-white p-5 shadow-sm dark:border-white/10 dark:bg-white/5'><div class='flex items-center justify-between gap-3'><code class='rounded-lg bg-violet-50 px-2.5 py-1 text-sm text-violet-700 dark:bg-violet-500/15 dark:text-violet-200'>generate_jsonb_layout</code><span class='rounded-full border px-2.5 py-0.5 text-[0.65rem] font-semibold uppercase tracking-[0.18em] border-amber-300 text-amber-700 dark:border-amber-500/40 dark:text-amber-200'>écriture</span></div><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Transforme un prompt en mise en page complète, valide chaque bloc contre le schéma NextBlock et la met en attente comme brouillon en direct.</p></div><div class='rounded-3xl border border-slate-200 bg-white p-5 shadow-sm dark:border-white/10 dark:bg-white/5'><div class='flex items-center justify-between gap-3'><code class='rounded-lg bg-violet-50 px-2.5 py-1 text-sm text-violet-700 dark:bg-violet-500/15 dark:text-violet-200'>update_site_navigation</code><span class='rounded-full border px-2.5 py-0.5 text-[0.65rem] font-semibold uppercase tracking-[0.18em] border-amber-300 text-amber-700 dark:border-amber-500/40 dark:text-amber-200'>écriture</span></div><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Ajoute, renomme ou réordonne les éléments du menu d'en-tête, par langue.</p></div><div class='rounded-3xl border border-slate-200 bg-white p-5 shadow-sm dark:border-white/10 dark:bg-white/5'><div class='flex items-center justify-between gap-3'><code class='rounded-lg bg-violet-50 px-2.5 py-1 text-sm text-violet-700 dark:bg-violet-500/15 dark:text-violet-200'>query_site_analytics</code><span class='rounded-full border px-2.5 py-0.5 text-[0.65rem] font-semibold uppercase tracking-[0.18em] border-emerald-300 text-emerald-700 dark:border-emerald-500/40 dark:text-emerald-200'>lecture</span></div><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Lit les revenus, le nombre de commandes, la répartition par statut et les meilleurs produits sur une période.</p></div><div class='rounded-3xl border border-slate-200 bg-white p-5 shadow-sm dark:border-white/10 dark:bg-white/5'><div class='flex items-center justify-between gap-3'><code class='rounded-lg bg-violet-50 px-2.5 py-1 text-sm text-violet-700 dark:bg-violet-500/15 dark:text-violet-200'>search_stock_media</code><span class='rounded-full border px-2.5 py-0.5 text-[0.65rem] font-semibold uppercase tracking-[0.18em] border-emerald-300 text-emerald-700 dark:border-emerald-500/40 dark:text-emerald-200'>lecture</span></div><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Trouve des photos libres de droits avec texte alternatif et crédit photographe, prêtes pour un bloc image.</p></div><div class='rounded-3xl border border-dashed border-slate-300 p-5 dark:border-white/20'><p class='mt-0 mb-0 text-sm font-semibold text-slate-900 dark:text-white'>Et 24 autres.</p><p class='mt-2 mb-0 text-sm text-slate-600 dark:text-slate-300'>Créer des articles et des produits, traduire des pages, téléverser des médias, gérer thèmes et scripts. Trois ressources exposent les schémas de la base de données, des blocs et des blocs personnalisés.</p></div></div><h2>Pas à pas : connecter Claude à NextBlock CMS dans Cursor et Claude Code</h2><p>Le serveur est désactivé par défaut, parce qu'il constitue une surface d'écriture à distance sur du contenu en ligne. L'activer prend trois étapes, et grâce à l'essai, le premier mois ne coûte rien.</p><div class='grid gap-4 md:grid-cols-3 my-8'><div class='rounded-3xl border border-slate-200 bg-slate-50 p-6 dark:border-white/10 dark:bg-white/5'><p class='mt-0 mb-0 font-mono text-3xl font-bold text-sky-500 dark:text-sky-300'>01</p><p class='mt-3 mb-0 text-lg font-semibold text-slate-900 dark:text-white'>Lancez l'essai gratuit.</p><p class='mt-2 mb-0 text-sm text-slate-600 dark:text-slate-300'>Ouvrez <strong>Réglages du CMS → Cortex AI</strong>, lancez l'essai de 30 jours sans carte de crédit et activez la carte d'accès au serveur MCP.</p></div><div class='rounded-3xl border border-slate-200 bg-slate-50 p-6 dark:border-white/10 dark:bg-white/5'><p class='mt-0 mb-0 font-mono text-3xl font-bold text-violet-500 dark:text-violet-300'>02</p><p class='mt-3 mb-0 text-lg font-semibold text-slate-900 dark:text-white'>Générez un jeton.</p><p class='mt-2 mb-0 text-sm text-slate-600 dark:text-slate-300'>Choisissez la portée dont vous avez besoin. La lecture seule suffit pour la planification et les audits.</p></div><div class='rounded-3xl border border-slate-200 bg-slate-50 p-6 dark:border-white/10 dark:bg-white/5'><p class='mt-0 mb-0 font-mono text-3xl font-bold text-emerald-500 dark:text-emerald-300'>03</p><p class='mt-3 mb-0 text-lg font-semibold text-slate-900 dark:text-white'>Copiez la configuration.</p><p class='mt-2 mb-0 text-sm text-slate-600 dark:text-slate-300'>La carte affiche un extrait pour chacun : Claude Code, Cursor, VS Code et Claude Desktop.</p></div></div><p>Claude Code exige <code>\"type\": \"http\"</code> dans l'entrée, sinon il ignore le serveur sans avertissement. Cursor déduit le transport à partir de l'URL et n'a pas besoin de champ type. VS Code utilise une clé <code>servers</code> de premier niveau et demande le jeton plutôt que de le stocker.</p><h3>Configuration localhost sans jeton</h3><p>Pendant le développement, activez <strong>Faire confiance à localhost sans jeton</strong> dans la même carte de réglages. Un serveur de développement sur votre machine accepte alors les appels en boucle locale sans aucun en-tête. Les installations autonomes tournent sur le port 3000, et le serveur de développement du monorepo sur le port 4200.</p><p>Ajoutez ce bloc au fichier <code>.mcp.json</code> à la racine de votre projet pour Claude Code.</p><div class='my-8 overflow-hidden rounded-[2rem] border border-slate-800 bg-slate-950 shadow-2xl'><div class='flex items-center gap-2 border-b border-white/10 px-5 py-3'><span class='h-3 w-3 rounded-full bg-red-400/70'></span><span class='h-3 w-3 rounded-full bg-yellow-400/70'></span><span class='h-3 w-3 rounded-full bg-green-400/70'></span><span class='ml-3 text-xs font-mono text-slate-400'>.mcp.json</span></div><pre class='m-0 overflow-x-auto rounded-none bg-transparent px-6 py-5 text-sm leading-6 text-slate-200'><code>{\n \"mcpServers\": {\n \"nextblock\": {\n \"type\": \"http\",\n \"url\": \"http://localhost:3000/api/mcp\"\n }\n }\n}</code></pre></div><p>La forme CLI fait la même chose en une ligne.</p><div class='my-8 overflow-hidden rounded-[2rem] border border-slate-800 bg-slate-950 shadow-2xl'><div class='flex items-center gap-2 border-b border-white/10 px-5 py-3'><span class='h-3 w-3 rounded-full bg-red-400/70'></span><span class='h-3 w-3 rounded-full bg-yellow-400/70'></span><span class='h-3 w-3 rounded-full bg-green-400/70'></span><span class='ml-3 text-xs font-mono text-slate-400'>terminal</span></div><pre class='m-0 overflow-x-auto rounded-none bg-transparent px-6 py-5 text-sm leading-6 text-slate-200'><code>claude mcp add --transport http nextblock http://localhost:3000/api/mcp</code></pre></div><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'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-amber-700 dark:text-amber-200'>Développement seulement</p><p class='mt-3 mb-0 text-sm text-slate-700 dark:text-slate-200'>La confiance envers localhost est ignorée dans les builds de production, parce qu'un proxy peut usurper l'en-tête host. La production utilise toujours un jeton.</p></div><h3>Authentification en production par jetons bearer</h3><p>En production, chaque client envoie un jeton bearer. Les jetons commencent par <code>nbmcp_</code>, ne sont affichés qu'une seule fois à leur création et ne sont stockés que sous forme de hachage SHA-256. Révoquer un jeton se fait en un clic, et la même valeur ne peut jamais être générée de nouveau.</p><p>Ajoutez ceci à <code>.cursor/mcp.json</code> pour Cursor, ou placez la même entrée dans <code>.mcp.json</code> avec un champ type pour Claude Code.</p><div class='my-8 overflow-hidden rounded-[2rem] border border-slate-800 bg-slate-950 shadow-2xl'><div class='flex items-center gap-2 border-b border-white/10 px-5 py-3'><span class='h-3 w-3 rounded-full bg-red-400/70'></span><span class='h-3 w-3 rounded-full bg-yellow-400/70'></span><span class='h-3 w-3 rounded-full bg-green-400/70'></span><span class='ml-3 text-xs font-mono text-slate-400'>.cursor/mcp.json</span></div><pre class='m-0 overflow-x-auto rounded-none bg-transparent px-6 py-5 text-sm leading-6 text-slate-200'><code>{\n \"mcpServers\": {\n \"nextblock\": {\n \"url\": \"https://your-site.com/api/mcp\",\n \"headers\": { \"Authorization\": \"Bearer nbmcp_your_token\" }\n }\n }\n}</code></pre></div><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'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200'>Essayez</p><p class='mt-3 mb-0 text-sm text-slate-700 dark:text-slate-200'>Une fois le client connecté, demandez quelque chose de concret. Essayez « inspecte le schéma de la base de données et ébauche une page de tarifs à trois paliers ». L'agent appelle l'outil de schéma, puis l'outil de mise en page, et votre CMS affiche un nouveau brouillon en direct prêt pour la révision.</p></div><h2>Rendu en production sans redéploiement</h2><p>Si ça fonctionne, c'est grâce à l'endroit où le résultat atterrit. Cortex AI écrit des enregistrements de blocs JSONB stricts dans PostgreSQL, pas des chaînes HTML ni des fichiers source. Chaque bloc possède un schéma Zod : un champ invalide est rejeté avant d'être stocké.</p><div class='grid gap-4 md:grid-cols-3 my-8'><div class='rounded-3xl border border-sky-200/70 bg-sky-50/70 p-6 text-center dark:border-sky-500/20 dark:bg-sky-500/10'><p class='mt-0 mb-0 text-4xl font-extrabold text-slate-900 dark:text-white'>0</p><p class='mt-2 mb-0 text-xs font-semibold uppercase tracking-[0.2em] text-sky-700 dark:text-sky-200'>reconstruction pour publier</p></div><div class='rounded-3xl border border-violet-200/70 bg-violet-50/70 p-6 text-center dark:border-violet-500/20 dark:bg-violet-500/10'><p class='mt-0 mb-0 text-4xl font-extrabold text-slate-900 dark:text-white'>1</p><p class='mt-2 mb-0 text-xs font-semibold uppercase tracking-[0.2em] text-violet-700 dark:text-violet-200'>schéma Zod par bloc</p></div><div class='rounded-3xl border border-emerald-200/70 bg-emerald-50/70 p-6 text-center dark:border-emerald-500/20 dark:bg-emerald-500/10'><p class='mt-0 mb-0 text-4xl font-extrabold text-slate-900 dark:text-white'>100</p><p class='mt-2 mb-0 text-xs font-semibold uppercase tracking-[0.2em] text-emerald-700 dark:text-emerald-200'>Lighthouse par défaut</p></div></div><p>À la requête, Next.js 16 rend ces enregistrements avec des Server Components et met le résultat en cache en périphérie. Il n'y a aucune étape de build entre la publication et la mise en ligne, ni de coût de nettoyage HTML à chaque rendu. Les scores Lighthouse de 100/100 d'un site vide sont les mêmes après que l'agent a ébauché cinquante pages.</p><div class='rounded-3xl border border-slate-200 bg-slate-50 p-6 my-10 dark:border-white/10 dark:bg-white/5'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-slate-600 dark:text-slate-300'>Prochaine étape</p><p class='mt-3 mb-0 text-xl font-semibold text-slate-900 dark:text-white'>En ligne en dix minutes, gratuit pendant trente jours.</p><p class='mt-3 text-sm text-slate-600 dark:text-slate-300'>Déployez le CMS gratuit sur Vercel en un clic, lancez l'essai Cortex AI sans carte de crédit et connectez Claude à NextBlock CMS dès aujourd'hui. Lisez comment le registre de blocs garde tout cela en sécurité si vous voulez le portrait complet.</p><div class='mt-5 flex flex-wrap gap-3'><a href='https://nextblock.dev/product/nextblock-cortex-ai-cortex-ai-license-fr' 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'>Commencer l'essai gratuit de 30 jours</a><a href='https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fnextblock-cms%2Fnextblock&project-name=nextblock&repository-name=nextblock&stores=%5B%7B%22type%22%3A%22integration%22%2C%22integrationSlug%22%3A%22supabase%22%2C%22productSlug%22%3A%22supabase%22%7D%5D' 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'>Déployer sur Vercel</a><a href='/article/comment-nextblock-fonctionne' 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'>Comment fonctionne NextBlock</a></div></div>"}$nb$::jsonb, 0);
47
- END IF;
48
-
49
- -- guide-cortex-ai-nextblock (translation group dbe2a06f-1a9d-48ba-bc35-0f6ef4869156)
50
- IF EXISTS (SELECT 1 FROM public.posts WHERE translation_group_id = 'dbe2a06f-1a9d-48ba-bc35-0f6ef4869156'::uuid AND language_id <> v_fr)
51
- AND NOT EXISTS (SELECT 1 FROM public.posts WHERE translation_group_id = 'dbe2a06f-1a9d-48ba-bc35-0f6ef4869156'::uuid AND language_id = v_fr)
52
- AND NOT EXISTS (SELECT 1 FROM public.posts WHERE slug = 'guide-cortex-ai-nextblock' AND language_id = v_fr) THEN
53
- INSERT INTO public.posts
54
- (language_id, author_id, title, slug, label, excerpt, subtitle, status, published_at,
55
- meta_title, meta_description, feature_image_id, version, translation_group_id)
56
- VALUES
57
- (v_fr, NULL, 'Guide NextBlock Cortex AI', 'guide-cortex-ai-nextblock', 'Cortex AI', 'Un guide pratique de Cortex AI, l''assistant conscient des blocs pour le routage des modèles, le contrôle BYOK et une production éditoriale plus rapide dans NextBlock.', 'Découvrez comment Cortex AI apporte la génération structurée, le choix du fournisseur et des flux de contenu plus sûrs directement dans l''éditeur NextBlock.',
58
- 'published', '2026-05-27T13:24:00+00:00'::timestamptz,
59
- 'Guide NextBlock Cortex AI', 'Découvrez comment NextBlock Cortex AI aide les équipes à générer, affiner et traduire du contenu par blocs structuré, avec routage des modèles et contrôle BYOK.',
60
- (SELECT id FROM public.media WHERE id = '8414dc5a-92d7-4cbf-8ecf-2fc8ec91a0a3'::uuid),
61
- 1, 'dbe2a06f-1a9d-48ba-bc35-0f6ef4869156'::uuid)
62
- RETURNING id INTO v_post;
63
-
64
- INSERT INTO public.blocks (post_id, language_id, block_type, content, "order")
65
- VALUES (v_post, v_fr, 'text', $nb${"html_content":"\n<p class='text-lg leading-8 text-slate-700 dark:text-slate-300'>NextBlock Cortex AI est l'outil de contenu intelligent conçu pour les pages web modernes. Il comprend les blocs de page, les mises en page de sections et les règles éditoriales, pour que vous créiez un meilleur contenu, plus vite.</p>\n\n<div class='grid gap-4 md:grid-cols-3 my-10'>\n <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'>\n <p class='text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200'>Routage des modèles</p>\n <h2 class='mt-3 text-xl font-semibold text-slate-900 dark:text-white'>Choisissez le bon modèle</h2>\n <p class='mt-3 text-sm text-slate-600 dark:text-slate-300'>Acheminez vos prompts via OpenRouter ou votre propre fournisseur pour équilibrer vitesse et prix.</p>\n </div>\n <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'>\n <p class='text-xs font-semibold uppercase tracking-[0.22em] text-sky-700 dark:text-sky-200'>Contrôle BYOK</p>\n <h2 class='mt-3 text-xl font-semibold text-slate-900 dark:text-white'>Utilisez vos propres clés</h2>\n <p class='mt-3 text-sm text-slate-600 dark:text-slate-300'>Gardez les clés des fournisseurs en sécurité sur votre serveur tout en offrant aux éditeurs un écran de rédaction IA tout simple.</p>\n </div>\n <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'>\n <p class='text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200'>Sortie typée</p>\n <h2 class='mt-3 text-xl font-semibold text-slate-900 dark:text-white'>Générez des blocs valides</h2>\n <p class='mt-3 text-sm text-slate-600 dark:text-slate-300'>Des schémas typés garantissent que le contenu IA s'insère directement dans vos pages sous forme de blocs propres et fonctionnels.</p>\n </div>\n</div>\n\n<h2>Pourquoi Cortex AI a sa place dans l'éditeur</h2>\n<p>Les outils de clavardage génériques peuvent rédiger du texte, mais ils ne font pas la différence entre une bannière héros, une grille de cartes et un article de blogue. Cortex AI vit directement dans votre écran d'édition. Il crée du contenu qui s'ajuste aux blocs de votre site en ligne.</p>\n<p>L'IA devient ainsi vraiment utile au quotidien. Vous pouvez ébaucher une nouvelle section d'accueil, peaufiner un résumé, enrichir une fiche produit ou traduire un article complet en toute simplicité.</p>\n\n<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'>\n <p class='text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200'>Flux éditorial</p>\n <div class='grid gap-5 md:grid-cols-2 mt-5'>\n <div class='rounded-2xl border border-slate-200 bg-white p-5 dark:border-white/10 dark:bg-slate-950/50'>\n <h3 class='mt-0 text-xl text-slate-900 dark:text-white'>Des premiers jets plus rapides</h3>\n <p class='text-sm text-slate-600 dark:text-slate-300'>Partez d'un prompt et obtenez une section, un brouillon d'article ou une histoire de produit qui respecte votre ton.</p>\n </div>\n <div class='rounded-2xl border border-slate-200 bg-white p-5 dark:border-white/10 dark:bg-slate-950/50'>\n <h3 class='mt-0 text-xl text-slate-900 dark:text-white'>Des révisions plus nettes</h3>\n <p class='text-sm text-slate-600 dark:text-slate-300'>Demandez un texte plus court, plus clair ou traduit, sans quitter votre écran d'édition.</p>\n </div>\n </div>\n</div>\n\n<h2>Routage des modèles et contrôle des coûts</h2>\n<p>Cortex AI vous donne le plein contrôle sur vos modèles. Choisissez des modèles rapides pour les brouillons express et des modèles plus puissants pour les articles techniques. Vous gérez vos clés d'API sur le serveur, pour que vos rédacteurs se concentrent sur le contenu.</p>\n<ul class='list-disc pl-6 space-y-2 text-sm'>\n <li>Utilisez des modèles rapides pour les réécritures, les titres et les résumés.</li>\n <li>Utilisez les meilleurs modèles pour les longs guides et les traductions difficiles.</li>\n <li>Gardez les clés des fournisseurs en sécurité dans vos réglages serveur privés.</li>\n <li>Maîtrisez les coûts sans changer l'affichage des pages pour les visiteurs.</li>\n</ul>\n\n<h2>Génération consciente des blocs</h2>\n<p>Cortex AI fait plus qu'écrire du texte brut. Il crée du contenu structuré qui correspond directement aux composants NextBlock. Vous obtenez des textes de section, des titres, des boutons et des blocs traduits prêts à l'emploi. Vous passez moins de temps à corriger les textes brouillons venus d'outils externes.</p>\n<p>Comme le contenu généré respecte vos règles de blocs, tout reste cohérent et rapide sur le web.</p>\n\n<h2>Des flux d'équipe plus sûrs</h2>\n<p>L'IA donne le meilleur d'elle-même quand les humains gardent le contrôle. Avec Cortex AI, les éditeurs révisent chaque brouillon avant publication. Les développeurs gèrent les clés des modèles, et le CMS conserve toutes les versions dans votre historique habituel.</p>\n\n<h2>Un flux de lancement concret</h2>\n<ol class='list-decimal pl-6 space-y-2 text-sm'>\n <li>Ébauchez un article, une section d'accueil ou une histoire de produit à partir d'un prompt clair.</li>\n <li>Affinez le texte pour qu'il colle à votre public et au ton de votre marque.</li>\n <li>Créez une version traduite ou un résumé plus court pour les cartes sociales et les balises de recherche.</li>\n <li>Révisez le contenu dans l'éditeur, publiez, puis suivez vos révisions au fil du temps.</li>\n</ol>\n\n<p>Cortex AI transforme votre CMS en atelier créatif plus rapide. Il ne remplace pas le goût humain, mais il vous aide à transformer de bonnes idées en pages finies en un temps record.</p>\n"}$nb$::jsonb, 0);
66
- END IF;
67
- END $$;
1
+ -- 02009: French versions of the two Cortex AI posts that only existed in English.
2
+ --
3
+ -- 'cortex-ai-mcp-connection-guide' (the MCP setup guide the home page links to) and
4
+ -- 'nextblock-cortex-ai-guide' had no row in the French translation group, so the
5
+ -- language switcher had nothing to offer and the French home page could only link
6
+ -- to English. Each post is inserted once per install, in the SAME translation group
7
+ -- as its English original, with the same feature image and publish date, followed by
8
+ -- its single text block: the English markup translated node by node (code samples and
9
+ -- configuration snippets untouched), links pointing at the French slugs.
10
+ --
11
+ -- Guards: runs only where the English original exists and no French row does, so a
12
+ -- re-run (or an install whose operator already translated the post) inserts nothing.
13
+ -- The identity sequences are re-synced first because the seed inserts explicit ids,
14
+ -- which leaves the sequence behind the table on a fresh install.
15
+
16
+ DO $$
17
+ DECLARE
18
+ v_fr bigint;
19
+ v_post bigint;
20
+ BEGIN
21
+ SELECT id INTO v_fr FROM public.languages WHERE code = 'fr' LIMIT 1;
22
+ IF v_fr IS NULL THEN
23
+ RAISE NOTICE '02009: no French language row; nothing to do.';
24
+ RETURN;
25
+ END IF;
26
+
27
+ PERFORM setval('public.posts_id_seq', COALESCE((SELECT MAX(id) FROM public.posts), 0) + 1, false);
28
+ PERFORM setval('public.blocks_id_seq', COALESCE((SELECT MAX(id) FROM public.blocks), 0) + 1, false);
29
+
30
+ -- guide-connexion-mcp-cortex-ai (translation group a7c4e2d1-3b58-4f96-9e0a-6d2c8b1f5a73)
31
+ IF EXISTS (SELECT 1 FROM public.posts WHERE translation_group_id = 'a7c4e2d1-3b58-4f96-9e0a-6d2c8b1f5a73'::uuid AND language_id <> v_fr)
32
+ AND NOT EXISTS (SELECT 1 FROM public.posts WHERE translation_group_id = 'a7c4e2d1-3b58-4f96-9e0a-6d2c8b1f5a73'::uuid AND language_id = v_fr)
33
+ AND NOT EXISTS (SELECT 1 FROM public.posts WHERE slug = 'guide-connexion-mcp-cortex-ai' AND language_id = v_fr) THEN
34
+ INSERT INTO public.posts
35
+ (language_id, author_id, title, slug, label, excerpt, subtitle, status, published_at,
36
+ meta_title, meta_description, feature_image_id, version, translation_group_id)
37
+ VALUES
38
+ (v_fr, NULL, 'Connecter Claude à NextBlock CMS via MCP, depuis Cursor ou Claude Code', 'guide-connexion-mcp-cortex-ai', 'Cortex AI', 'Enregistrez /api/mcp dans Claude Code ou Cursor et laissez votre propre abonnement IA lire le schéma, ébaucher des mises en page et gérer les pages dans NextBlock.', 'Un guide pratique du serveur MCP de Cortex AI : ce qu''il règle, les outils qu''il expose et la configuration exacte pour localhost et la production.',
39
+ 'published', '2026-09-10T14:20:17.461154+00:00'::timestamptz,
40
+ 'Connecter Claude à NextBlock CMS via MCP | Guide Cursor', 'Apprenez à connecter Claude à NextBlock CMS avec le Model Context Protocol. Enregistrez /api/mcp dans Claude Code ou Cursor pour inspecter les schémas et bâtir des mises en page.',
41
+ (SELECT id FROM public.media WHERE id = '8b2e5d1c-9a47-4f3b-8e6d-1c7a2b9d4e50'::uuid),
42
+ 1, 'a7c4e2d1-3b58-4f96-9e0a-6d2c8b1f5a73'::uuid)
43
+ RETURNING id INTO v_post;
44
+
45
+ INSERT INTO public.blocks (post_id, language_id, block_type, content, "order")
46
+ VALUES (v_post, v_fr, 'text', $nb${"html_content":"<p class='text-lg leading-8 text-slate-700 dark:text-slate-300'>Ce guide vous montre comment connecter Claude à NextBlock CMS avec un standard ouvert plutôt qu'un plugin propriétaire. Cortex AI transforme votre site en serveur Model Context Protocol. Claude Code, Cursor, ChatGPT et Gemini peuvent ensuite lire le schéma de votre base de données, ébaucher des mises en page et mettre à jour la navigation depuis leur propre fenêtre de clavardage. Vous payez l'abonnement IA que vous avez déjà, sans aucune majoration sur les jetons entre les deux.</p><div class='grid gap-4 md:grid-cols-3 my-10'><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'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-sky-700 dark:text-sky-200'>Un seul bloc de configuration</p><p class='mt-3 mb-0 text-xl font-semibold text-slate-900 dark:text-white'>Configuré en quelques minutes.</p><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Collez une seule entrée JSON dans Claude Code, Cursor ou VS Code. La carte des réglages du CMS l'écrit pour vous.</p></div><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'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-indigo-700 dark:text-indigo-200'>Essai gratuit</p><p class='mt-3 mb-0 text-xl font-semibold text-slate-900 dark:text-white'>30 jours, sans carte de crédit.</p><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Le CMS est gratuit pour toujours. Cortex AI, qui inclut le serveur MCP, commence par un essai gratuit de 30 jours.</p></div><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'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200'>Brouillons en direct</p><p class='mt-3 mb-0 text-xl font-semibold text-slate-900 dark:text-white'>Rien ne part par accident.</p><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Chaque mise en page écrite par l'agent arrive sous forme de brouillon. Un éditeur la révise et clique sur Publier.</p></div></div><p>Chaque prompt devient un enregistrement structuré en base de données plutôt qu'un tas de code généré. Vos éditeurs gardent un CMS visuel, vos développeurs gardent une application Next.js 16 propre, et rien n'est mis en ligne tant que quelqu'un ne clique pas sur Publier.</p><h2>Le problème des constructeurs web IA traditionnels</h2><p>Les constructeurs par prompt comme Lovable, Bolt et v0 impressionnent le premier jour. Vous décrivez une page et obtenez une application React fonctionnelle en quelques minutes. Les ennuis commencent le deuxième jour.</p><div class='not-prose my-8 overflow-hidden rounded-3xl border border-slate-200 bg-white shadow-sm dark:border-slate-800 dark:bg-slate-900'><div class='flex flex-wrap items-end justify-between gap-3 px-5 pt-6 pb-4'><div><p class='text-xs font-semibold uppercase tracking-[0.22em] text-slate-500 dark:text-slate-400'>Côte à côte</p><p class='mt-1 text-xl font-semibold text-slate-900 dark:text-white'>Les outils de prototype face à NextBlock.</p></div><p class='text-xs text-slate-500 dark:text-slate-400'>Ce qui se passe après le premier prompt.</p></div><div class='overflow-x-auto'><table class='w-full min-w-[640px] border-collapse'><thead><tr class='bg-slate-50 dark:bg-slate-950/60'><th scope='col' class='px-5 py-3 text-left text-xs font-semibold uppercase tracking-[0.2em] text-slate-500 dark:text-slate-400'>Ce que vous obtenez</th><th scope='col' class='px-5 py-3 text-left text-xs font-semibold uppercase tracking-[0.2em] text-rose-600 dark:text-rose-300'>Lovable, Bolt, v0</th><th scope='col' class='bg-emerald-50/60 px-5 py-3 text-left text-xs font-semibold uppercase tracking-[0.2em] text-emerald-700 dark:bg-emerald-500/10 dark:text-emerald-200'>NextBlock</th></tr></thead><tbody><tr class='border-t border-slate-200 dark:border-slate-800'><th scope='row' class='px-5 py-4 text-left align-top text-sm font-semibold text-foreground'>Jour un</th><td class='px-5 py-4 align-top text-sm text-muted-foreground'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-rose-100 text-xs font-bold text-rose-600 dark:bg-rose-500/20 dark:text-rose-300'>&#10007;</span>Du code jetable sans couche de contenu.</td><td class='bg-emerald-50/60 px-5 py-4 align-top text-sm text-foreground dark:bg-emerald-500/10'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-xs font-bold text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-200'>&#10003;</span>Un site Next.js 16 et Supabase en production, avec un CMS.</td></tr><tr class='border-t border-slate-200 dark:border-slate-800'><th scope='row' class='px-5 py-4 text-left align-top text-sm font-semibold text-foreground'>Changer un titre</th><td class='px-5 py-4 align-top text-sm text-muted-foreground'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-rose-100 text-xs font-bold text-rose-600 dark:bg-rose-500/20 dark:text-rose-300'>&#10007;</span>Un autre prompt ou une autre pull request.</td><td class='bg-emerald-50/60 px-5 py-4 align-top text-sm text-foreground dark:bg-emerald-500/10'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-xs font-bold text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-200'>&#10003;</span>Un éditeur le tape dans un éditeur de type Notion.</td></tr><tr class='border-t border-slate-200 dark:border-slate-800'><th scope='row' class='px-5 py-4 text-left align-top text-sm font-semibold text-foreground'>Brouillons et révisions</th><td class='px-5 py-4 align-top text-sm text-muted-foreground'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-rose-100 text-xs font-bold text-rose-600 dark:bg-rose-500/20 dark:text-rose-300'>&#10007;</span>Un historique du code seulement.</td><td class='bg-emerald-50/60 px-5 py-4 align-top text-sm text-foreground dark:bg-emerald-500/10'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-xs font-bold text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-200'>&#10003;</span>Brouillons en direct, révisions et restauration en un clic.</td></tr><tr class='border-t border-slate-200 dark:border-slate-800'><th scope='row' class='px-5 py-4 text-left align-top text-sm font-semibold text-foreground'>Traductions et SEO</th><td class='px-5 py-4 align-top text-sm text-muted-foreground'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-rose-100 text-xs font-bold text-rose-600 dark:bg-rose-500/20 dark:text-rose-300'>&#10007;</span>Pas inclus.</td><td class='bg-emerald-50/60 px-5 py-4 align-top text-sm text-foreground dark:bg-emerald-500/10'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-xs font-bold text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-200'>&#10003;</span>Traduction bloc par bloc et vérifications SEO pendant que vous écrivez.</td></tr><tr class='border-t border-slate-200 dark:border-slate-800'><th scope='row' class='px-5 py-4 text-left align-top text-sm font-semibold text-foreground'>Coûts de l'IA</th><td class='px-5 py-4 align-top text-sm text-muted-foreground'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-rose-100 text-xs font-bold text-rose-600 dark:bg-rose-500/20 dark:text-rose-300'>&#10007;</span>Des crédits de plateforme, achetés à l'outil.</td><td class='bg-emerald-50/60 px-5 py-4 align-top text-sm text-foreground dark:bg-emerald-500/10'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-xs font-bold text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-200'>&#10003;</span>Votre propre abonnement via MCP, sans majoration.</td></tr><tr class='border-t border-slate-200 dark:border-slate-800'><th scope='row' class='px-5 py-4 text-left align-top text-sm font-semibold text-foreground'>Prix</th><td class='px-5 py-4 align-top text-sm text-muted-foreground'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-rose-100 text-xs font-bold text-rose-600 dark:bg-rose-500/20 dark:text-rose-300'>&#10007;</span>Un forfait mensuel.</td><td class='bg-emerald-50/60 px-5 py-4 align-top text-sm text-foreground dark:bg-emerald-500/10'><span class='mr-2 inline-flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-xs font-bold text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-200'>&#10003;</span>CMS gratuit. Cortex AI après un essai gratuit de 30 jours.</td></tr></tbody></table></div></div><p>NextBlock prend le contre-pied des outils de prototype. L'IA devrait ébaucher le site, et les humains devraient en être propriétaires. La connexion MCP est le point de rencontre de ces deux mondes.</p><h2>Comment Cortex AI utilise le Model Context Protocol (MCP)</h2><p>Le Model Context Protocol est un standard ouvert qui donne des outils aux agents IA. Un client comme Claude Code liste les outils offerts par un serveur, les appelle avec des arguments typés et lit des résultats typés en retour. Cortex AI embarque ce serveur dans votre installation NextBlock, à l'adresse <code>/api/mcp</code>.</p><div class='not-prose my-12 overflow-hidden rounded-[2rem] border border-slate-800 bg-slate-950 p-6 shadow-2xl sm:p-8'><p class='text-[0.65rem] font-semibold uppercase tracking-[0.3em] text-indigo-300'>Model Context Protocol · NextBlock Cortex AI</p><p class='mt-2 text-2xl font-extrabold text-white sm:text-3xl'>Du prompt à la production, sans redéploiement.</p><p class='mt-2 max-w-2xl text-sm text-slate-400'>Votre client IA parle au CMS via un standard ouvert. Le résultat atterrit sous forme de données, pas de code à héberger.</p><div class='mt-8 grid gap-4 md:grid-cols-2 xl:grid-cols-4'><div class='relative flex flex-col rounded-2xl border border-sky-400/40 bg-white/5 p-5'><span class='block h-1 w-12 rounded-full bg-sky-400'></span><p class='mt-4 text-[0.65rem] font-semibold uppercase tracking-[0.25em] text-sky-300'>Étape 1 · Votre client IA</p><p class='mt-2 text-lg font-bold leading-snug text-white'>Prompt</p><p class='mt-1 text-xs text-slate-400'>N'importe quel client MCP que vous payez déjà.</p><div class='mt-4 flex-1 text-sm text-slate-200'><div class='flex flex-wrap gap-2'><span class='rounded-full border border-sky-400/40 bg-sky-400/10 px-3 py-1 text-xs font-semibold text-slate-100'>Claude Code</span><span class='rounded-full border border-sky-400/40 bg-sky-400/10 px-3 py-1 text-xs font-semibold text-slate-100'>Cursor</span><span class='rounded-full border border-sky-400/40 bg-sky-400/10 px-3 py-1 text-xs font-semibold text-slate-100'>ChatGPT</span><span class='rounded-full border border-sky-400/40 bg-sky-400/10 px-3 py-1 text-xs font-semibold text-slate-100'>Gemini</span></div><p class='mt-4 text-xs text-slate-300'>Un seul bloc JSON dans la configuration de votre client enregistre le serveur. C'est toute la configuration.</p></div><p class='mt-5 rounded-lg bg-sky-400/10 px-3 py-2 text-center text-[0.7rem] font-semibold text-sky-300'>Votre abonnement · aucune majoration sur les jetons</p><span class='absolute -right-4 top-1/2 hidden -translate-y-1/2 text-xl text-slate-500 xl:block' aria-hidden='true'>→</span></div><div class='relative flex flex-col rounded-2xl border border-violet-400/40 bg-white/5 p-5'><span class='block h-1 w-12 rounded-full bg-violet-400'></span><p class='mt-4 text-[0.65rem] font-semibold uppercase tracking-[0.25em] text-violet-300'>Étape 2 · /api/mcp</p><p class='mt-2 text-lg font-bold leading-snug text-white'>Serveur MCP Cortex AI</p><p class='mt-1 text-xs text-slate-400'>Streamable HTTP · jeton bearer · à portée limitée.</p><div class='mt-4 flex-1 text-sm text-slate-200'><div class='space-y-1.5'><code class='block rounded-md bg-white/5 px-3 py-1.5 font-mono text-xs text-violet-100'>get_database_schema</code><code class='block rounded-md bg-white/5 px-3 py-1.5 font-mono text-xs text-violet-100'>generate_jsonb_layout</code><code class='block rounded-md bg-white/5 px-3 py-1.5 font-mono text-xs text-violet-100'>update_site_navigation</code><code class='block rounded-md bg-white/5 px-3 py-1.5 font-mono text-xs text-violet-100'>query_site_analytics</code><code class='block rounded-md bg-white/5 px-3 py-1.5 font-mono text-xs text-violet-100'>search_stock_media</code></div></div><p class='mt-5 rounded-lg bg-violet-400/10 px-3 py-2 text-center text-[0.7rem] font-semibold text-violet-300'>5 outils de contrat · 29 outils typés</p><span class='absolute -right-4 top-1/2 hidden -translate-y-1/2 text-xl text-slate-500 xl:block' aria-hidden='true'>→</span></div><div class='relative flex flex-col rounded-2xl border border-emerald-400/40 bg-white/5 p-5'><span class='block h-1 w-12 rounded-full bg-emerald-400'></span><p class='mt-4 text-[0.65rem] font-semibold uppercase tracking-[0.25em] text-emerald-300'>Étape 3 · PostgreSQL</p><p class='mt-2 text-lg font-bold leading-snug text-white'>Blocs JSONB validés</p><p class='mt-1 text-xs text-slate-400'>Supabase · un schéma Zod par bloc.</p><div class='mt-4 flex-1 text-sm text-slate-200'><div class='space-y-2'><p class='flex items-start gap-2 text-sm text-slate-200'><span class='mt-0.5 inline-flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-emerald-400/20 text-[0.6rem] font-bold text-emerald-300'>&#10003;</span><span>Mis en attente comme brouillon en direct.</span></p><p class='flex items-start gap-2 text-sm text-slate-200'><span class='mt-0.5 inline-flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-emerald-400/20 text-[0.6rem] font-bold text-emerald-300'>&#10003;</span><span>Les éditeurs peaufinent dans le CMS visuel.</span></p><p class='flex items-start gap-2 text-sm text-slate-200'><span class='mt-0.5 inline-flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-emerald-400/20 text-[0.6rem] font-bold text-emerald-300'>&#10003;</span><span>Révisions et vérifications SEO intégrées.</span></p></div></div><p class='mt-5 rounded-lg bg-emerald-400/10 px-3 py-2 text-center text-[0.7rem] font-semibold text-emerald-300'>Rien n'est en ligne avant la publication</p><span class='absolute -right-4 top-1/2 hidden -translate-y-1/2 text-xl text-slate-500 xl:block' aria-hidden='true'>→</span></div><div class='relative flex flex-col rounded-2xl border border-amber-400/40 bg-white/5 p-5'><span class='block h-1 w-12 rounded-full bg-amber-400'></span><p class='mt-4 text-[0.65rem] font-semibold uppercase tracking-[0.25em] text-amber-300'>Étape 4 · Next.js 16</p><p class='mt-2 text-lg font-bold leading-snug text-white'>Page publiée</p><p class='mt-1 text-xs text-slate-400'>Server Components · cache en périphérie.</p><div class='mt-4 flex-1 text-sm text-slate-200'><div class='space-y-2'><p class='flex items-start gap-2 text-sm text-slate-200'><span class='mt-0.5 inline-flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-amber-400/20 text-[0.6rem] font-bold text-amber-300'>&#10003;</span><span>Ni reconstruction, ni redéploiement.</span></p><p class='flex items-start gap-2 text-sm text-slate-200'><span class='mt-0.5 inline-flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-amber-400/20 text-[0.6rem] font-bold text-amber-300'>&#10003;</span><span>Scores Lighthouse de 100/100 par défaut.</span></p><p class='flex items-start gap-2 text-sm text-slate-200'><span class='mt-0.5 inline-flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-amber-400/20 text-[0.6rem] font-bold text-amber-300'>&#10003;</span><span>Le même site le deuxième jour.</span></p></div></div><p class='mt-5 rounded-lg bg-amber-400/10 px-3 py-2 text-center text-[0.7rem] font-semibold text-amber-300'>Un site web plus un CMS</p></div></div><div class='mt-6 h-1.5 rounded-full bg-gradient-to-r from-sky-400 via-violet-400 to-amber-400'></div><p class='mt-4 text-center text-sm text-slate-300'>Les éditeurs gardent un CMS visuel. Les développeurs gardent une base de code Next.js 16 propre. L'agent ne touche ni à l'un ni à l'autre.</p></div><p>Le point de terminaison parle Streamable HTTP. Votre client envoie des messages JSON-RPC dans une requête HTTPS ordinaire, et le serveur répond dans la même réponse. Aucun flux SSE de longue durée à surveiller, aucun SDK à installer côté serveur. Les mêmes 29 outils typés qui alimentent Cortex AI dans l'éditeur sont exposés sur le réseau, si bien que l'agent de votre IDE et celui de votre CMS ne divergent jamais.</p><div class='grid gap-4 md:grid-cols-2 my-8'><div class='rounded-3xl border border-violet-200/70 bg-violet-50/70 p-6 dark:border-violet-500/20 dark:bg-violet-500/10'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200'>Règle de sécurité no 1</p><p class='mt-3 mb-0 text-xl font-semibold text-slate-900 dark:text-white'>Les mises en page attendent en brouillon en direct.</p><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Les outils de mise en page écrivent des brouillons : rien n'atteint les visiteurs tant qu'un éditeur ne publie pas.</p></div><div class='rounded-3xl border border-blue-200/70 bg-blue-50/70 p-6 dark:border-blue-500/20 dark:bg-blue-500/10'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-blue-700 dark:text-blue-200'>Règle de sécurité no 2</p><p class='mt-3 mb-0 text-xl font-semibold text-slate-900 dark:text-white'>Chaque jeton porte une portée.</p><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Un jeton en lecture seule ne voit même pas les outils capables de modifier des données. Les outils de modification sont absents de sa liste.</p></div></div><h3>Outils MCP de base de données disponibles</h3><p>Cinq noms d'outils forment le contrat MCP public. Chacun renvoie vers un exécuteur Cortex AI testé.</p><div class='grid gap-4 md:grid-cols-2 my-8'><div class='rounded-3xl border border-slate-200 bg-white p-5 shadow-sm dark:border-white/10 dark:bg-white/5'><div class='flex items-center justify-between gap-3'><code class='rounded-lg bg-violet-50 px-2.5 py-1 text-sm text-violet-700 dark:bg-violet-500/15 dark:text-violet-200'>get_database_schema</code><span class='rounded-full border px-2.5 py-0.5 text-[0.65rem] font-semibold uppercase tracking-[0.18em] border-emerald-300 text-emerald-700 dark:border-emerald-500/40 dark:text-emerald-200'>lecture</span></div><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Retourne chaque table que l'agent peut lire ou modifier, avec colonnes, clés primaires et indicateurs de lecture seule.</p></div><div class='rounded-3xl border border-slate-200 bg-white p-5 shadow-sm dark:border-white/10 dark:bg-white/5'><div class='flex items-center justify-between gap-3'><code class='rounded-lg bg-violet-50 px-2.5 py-1 text-sm text-violet-700 dark:bg-violet-500/15 dark:text-violet-200'>generate_jsonb_layout</code><span class='rounded-full border px-2.5 py-0.5 text-[0.65rem] font-semibold uppercase tracking-[0.18em] border-amber-300 text-amber-700 dark:border-amber-500/40 dark:text-amber-200'>écriture</span></div><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Transforme un prompt en mise en page complète, valide chaque bloc contre le schéma NextBlock et la met en attente comme brouillon en direct.</p></div><div class='rounded-3xl border border-slate-200 bg-white p-5 shadow-sm dark:border-white/10 dark:bg-white/5'><div class='flex items-center justify-between gap-3'><code class='rounded-lg bg-violet-50 px-2.5 py-1 text-sm text-violet-700 dark:bg-violet-500/15 dark:text-violet-200'>update_site_navigation</code><span class='rounded-full border px-2.5 py-0.5 text-[0.65rem] font-semibold uppercase tracking-[0.18em] border-amber-300 text-amber-700 dark:border-amber-500/40 dark:text-amber-200'>écriture</span></div><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Ajoute, renomme ou réordonne les éléments du menu d'en-tête, par langue.</p></div><div class='rounded-3xl border border-slate-200 bg-white p-5 shadow-sm dark:border-white/10 dark:bg-white/5'><div class='flex items-center justify-between gap-3'><code class='rounded-lg bg-violet-50 px-2.5 py-1 text-sm text-violet-700 dark:bg-violet-500/15 dark:text-violet-200'>query_site_analytics</code><span class='rounded-full border px-2.5 py-0.5 text-[0.65rem] font-semibold uppercase tracking-[0.18em] border-emerald-300 text-emerald-700 dark:border-emerald-500/40 dark:text-emerald-200'>lecture</span></div><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Lit les revenus, le nombre de commandes, la répartition par statut et les meilleurs produits sur une période.</p></div><div class='rounded-3xl border border-slate-200 bg-white p-5 shadow-sm dark:border-white/10 dark:bg-white/5'><div class='flex items-center justify-between gap-3'><code class='rounded-lg bg-violet-50 px-2.5 py-1 text-sm text-violet-700 dark:bg-violet-500/15 dark:text-violet-200'>search_stock_media</code><span class='rounded-full border px-2.5 py-0.5 text-[0.65rem] font-semibold uppercase tracking-[0.18em] border-emerald-300 text-emerald-700 dark:border-emerald-500/40 dark:text-emerald-200'>lecture</span></div><p class='mt-3 mb-0 text-sm text-slate-600 dark:text-slate-300'>Trouve des photos libres de droits avec texte alternatif et crédit photographe, prêtes pour un bloc image.</p></div><div class='rounded-3xl border border-dashed border-slate-300 p-5 dark:border-white/20'><p class='mt-0 mb-0 text-sm font-semibold text-slate-900 dark:text-white'>Et 24 autres.</p><p class='mt-2 mb-0 text-sm text-slate-600 dark:text-slate-300'>Créer des articles et des produits, traduire des pages, téléverser des médias, gérer thèmes et scripts. Trois ressources exposent les schémas de la base de données, des blocs et des blocs personnalisés.</p></div></div><h2>Pas à pas : connecter Claude à NextBlock CMS dans Cursor et Claude Code</h2><p>Le serveur est désactivé par défaut, parce qu'il constitue une surface d'écriture à distance sur du contenu en ligne. L'activer prend trois étapes, et grâce à l'essai, le premier mois ne coûte rien.</p><div class='grid gap-4 md:grid-cols-3 my-8'><div class='rounded-3xl border border-slate-200 bg-slate-50 p-6 dark:border-white/10 dark:bg-white/5'><p class='mt-0 mb-0 font-mono text-3xl font-bold text-sky-500 dark:text-sky-300'>01</p><p class='mt-3 mb-0 text-lg font-semibold text-slate-900 dark:text-white'>Lancez l'essai gratuit.</p><p class='mt-2 mb-0 text-sm text-slate-600 dark:text-slate-300'>Ouvrez <strong>Réglages du CMS → Cortex AI</strong>, lancez l'essai de 30 jours sans carte de crédit et activez la carte d'accès au serveur MCP.</p></div><div class='rounded-3xl border border-slate-200 bg-slate-50 p-6 dark:border-white/10 dark:bg-white/5'><p class='mt-0 mb-0 font-mono text-3xl font-bold text-violet-500 dark:text-violet-300'>02</p><p class='mt-3 mb-0 text-lg font-semibold text-slate-900 dark:text-white'>Générez un jeton.</p><p class='mt-2 mb-0 text-sm text-slate-600 dark:text-slate-300'>Choisissez la portée dont vous avez besoin. La lecture seule suffit pour la planification et les audits.</p></div><div class='rounded-3xl border border-slate-200 bg-slate-50 p-6 dark:border-white/10 dark:bg-white/5'><p class='mt-0 mb-0 font-mono text-3xl font-bold text-emerald-500 dark:text-emerald-300'>03</p><p class='mt-3 mb-0 text-lg font-semibold text-slate-900 dark:text-white'>Copiez la configuration.</p><p class='mt-2 mb-0 text-sm text-slate-600 dark:text-slate-300'>La carte affiche un extrait pour chacun : Claude Code, Cursor, VS Code et Claude Desktop.</p></div></div><p>Claude Code exige <code>\"type\": \"http\"</code> dans l'entrée, sinon il ignore le serveur sans avertissement. Cursor déduit le transport à partir de l'URL et n'a pas besoin de champ type. VS Code utilise une clé <code>servers</code> de premier niveau et demande le jeton plutôt que de le stocker.</p><h3>Configuration localhost sans jeton</h3><p>Pendant le développement, activez <strong>Faire confiance à localhost sans jeton</strong> dans la même carte de réglages. Un serveur de développement sur votre machine accepte alors les appels en boucle locale sans aucun en-tête. Les installations autonomes tournent sur le port 3000, et le serveur de développement du monorepo sur le port 4200.</p><p>Ajoutez ce bloc au fichier <code>.mcp.json</code> à la racine de votre projet pour Claude Code.</p><div class='my-8 overflow-hidden rounded-[2rem] border border-slate-800 bg-slate-950 shadow-2xl'><div class='flex items-center gap-2 border-b border-white/10 px-5 py-3'><span class='h-3 w-3 rounded-full bg-red-400/70'></span><span class='h-3 w-3 rounded-full bg-yellow-400/70'></span><span class='h-3 w-3 rounded-full bg-green-400/70'></span><span class='ml-3 text-xs font-mono text-slate-400'>.mcp.json</span></div><pre class='m-0 overflow-x-auto rounded-none bg-transparent px-6 py-5 text-sm leading-6 text-slate-200'><code>{\n \"mcpServers\": {\n \"nextblock\": {\n \"type\": \"http\",\n \"url\": \"http://localhost:3000/api/mcp\"\n }\n }\n}</code></pre></div><p>La forme CLI fait la même chose en une ligne.</p><div class='my-8 overflow-hidden rounded-[2rem] border border-slate-800 bg-slate-950 shadow-2xl'><div class='flex items-center gap-2 border-b border-white/10 px-5 py-3'><span class='h-3 w-3 rounded-full bg-red-400/70'></span><span class='h-3 w-3 rounded-full bg-yellow-400/70'></span><span class='h-3 w-3 rounded-full bg-green-400/70'></span><span class='ml-3 text-xs font-mono text-slate-400'>terminal</span></div><pre class='m-0 overflow-x-auto rounded-none bg-transparent px-6 py-5 text-sm leading-6 text-slate-200'><code>claude mcp add --transport http nextblock http://localhost:3000/api/mcp</code></pre></div><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'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-amber-700 dark:text-amber-200'>Développement seulement</p><p class='mt-3 mb-0 text-sm text-slate-700 dark:text-slate-200'>La confiance envers localhost est ignorée dans les builds de production, parce qu'un proxy peut usurper l'en-tête host. La production utilise toujours un jeton.</p></div><h3>Authentification en production par jetons bearer</h3><p>En production, chaque client envoie un jeton bearer. Les jetons commencent par <code>nbmcp_</code>, ne sont affichés qu'une seule fois à leur création et ne sont stockés que sous forme de hachage SHA-256. Révoquer un jeton se fait en un clic, et la même valeur ne peut jamais être générée de nouveau.</p><p>Ajoutez ceci à <code>.cursor/mcp.json</code> pour Cursor, ou placez la même entrée dans <code>.mcp.json</code> avec un champ type pour Claude Code.</p><div class='my-8 overflow-hidden rounded-[2rem] border border-slate-800 bg-slate-950 shadow-2xl'><div class='flex items-center gap-2 border-b border-white/10 px-5 py-3'><span class='h-3 w-3 rounded-full bg-red-400/70'></span><span class='h-3 w-3 rounded-full bg-yellow-400/70'></span><span class='h-3 w-3 rounded-full bg-green-400/70'></span><span class='ml-3 text-xs font-mono text-slate-400'>.cursor/mcp.json</span></div><pre class='m-0 overflow-x-auto rounded-none bg-transparent px-6 py-5 text-sm leading-6 text-slate-200'><code>{\n \"mcpServers\": {\n \"nextblock\": {\n \"url\": \"https://your-site.com/api/mcp\",\n \"headers\": { \"Authorization\": \"Bearer nbmcp_your_token\" }\n }\n }\n}</code></pre></div><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'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200'>Essayez</p><p class='mt-3 mb-0 text-sm text-slate-700 dark:text-slate-200'>Une fois le client connecté, demandez quelque chose de concret. Essayez « inspecte le schéma de la base de données et ébauche une page de tarifs à trois paliers ». L'agent appelle l'outil de schéma, puis l'outil de mise en page, et votre CMS affiche un nouveau brouillon en direct prêt pour la révision.</p></div><h2>Rendu en production sans redéploiement</h2><p>Si ça fonctionne, c'est grâce à l'endroit où le résultat atterrit. Cortex AI écrit des enregistrements de blocs JSONB stricts dans PostgreSQL, pas des chaînes HTML ni des fichiers source. Chaque bloc possède un schéma Zod : un champ invalide est rejeté avant d'être stocké.</p><div class='grid gap-4 md:grid-cols-3 my-8'><div class='rounded-3xl border border-sky-200/70 bg-sky-50/70 p-6 text-center dark:border-sky-500/20 dark:bg-sky-500/10'><p class='mt-0 mb-0 text-4xl font-extrabold text-slate-900 dark:text-white'>0</p><p class='mt-2 mb-0 text-xs font-semibold uppercase tracking-[0.2em] text-sky-700 dark:text-sky-200'>reconstruction pour publier</p></div><div class='rounded-3xl border border-violet-200/70 bg-violet-50/70 p-6 text-center dark:border-violet-500/20 dark:bg-violet-500/10'><p class='mt-0 mb-0 text-4xl font-extrabold text-slate-900 dark:text-white'>1</p><p class='mt-2 mb-0 text-xs font-semibold uppercase tracking-[0.2em] text-violet-700 dark:text-violet-200'>schéma Zod par bloc</p></div><div class='rounded-3xl border border-emerald-200/70 bg-emerald-50/70 p-6 text-center dark:border-emerald-500/20 dark:bg-emerald-500/10'><p class='mt-0 mb-0 text-4xl font-extrabold text-slate-900 dark:text-white'>100</p><p class='mt-2 mb-0 text-xs font-semibold uppercase tracking-[0.2em] text-emerald-700 dark:text-emerald-200'>Lighthouse par défaut</p></div></div><p>À la requête, Next.js 16 rend ces enregistrements avec des Server Components et met le résultat en cache en périphérie. Il n'y a aucune étape de build entre la publication et la mise en ligne, ni de coût de nettoyage HTML à chaque rendu. Les scores Lighthouse de 100/100 d'un site vide sont les mêmes après que l'agent a ébauché cinquante pages.</p><div class='rounded-3xl border border-slate-200 bg-slate-50 p-6 my-10 dark:border-white/10 dark:bg-white/5'><p class='mt-0 mb-0 text-xs font-semibold uppercase tracking-[0.22em] text-slate-600 dark:text-slate-300'>Prochaine étape</p><p class='mt-3 mb-0 text-xl font-semibold text-slate-900 dark:text-white'>En ligne en dix minutes, gratuit pendant trente jours.</p><p class='mt-3 text-sm text-slate-600 dark:text-slate-300'>Déployez le CMS gratuit sur Vercel en un clic, lancez l'essai Cortex AI sans carte de crédit et connectez Claude à NextBlock CMS dès aujourd'hui. Lisez comment le registre de blocs garde tout cela en sécurité si vous voulez le portrait complet.</p><div class='mt-5 flex flex-wrap gap-3'><a href='https://nextblock.dev/product/nextblock-cortex-ai-cortex-ai-license-fr' 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'>Commencer l'essai gratuit de 30 jours</a><a href='https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fnextblock-cms%2Fnextblock&project-name=nextblock&repository-name=nextblock&stores=%5B%7B%22type%22%3A%22integration%22%2C%22integrationSlug%22%3A%22supabase%22%2C%22productSlug%22%3A%22supabase%22%7D%5D' 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'>Déployer sur Vercel</a><a href='/article/comment-nextblock-fonctionne' 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'>Comment fonctionne NextBlock</a></div></div>"}$nb$::jsonb, 0);
47
+ END IF;
48
+
49
+ -- guide-cortex-ai-nextblock (translation group dbe2a06f-1a9d-48ba-bc35-0f6ef4869156)
50
+ IF EXISTS (SELECT 1 FROM public.posts WHERE translation_group_id = 'dbe2a06f-1a9d-48ba-bc35-0f6ef4869156'::uuid AND language_id <> v_fr)
51
+ AND NOT EXISTS (SELECT 1 FROM public.posts WHERE translation_group_id = 'dbe2a06f-1a9d-48ba-bc35-0f6ef4869156'::uuid AND language_id = v_fr)
52
+ AND NOT EXISTS (SELECT 1 FROM public.posts WHERE slug = 'guide-cortex-ai-nextblock' AND language_id = v_fr) THEN
53
+ INSERT INTO public.posts
54
+ (language_id, author_id, title, slug, label, excerpt, subtitle, status, published_at,
55
+ meta_title, meta_description, feature_image_id, version, translation_group_id)
56
+ VALUES
57
+ (v_fr, NULL, 'Guide NextBlock Cortex AI', 'guide-cortex-ai-nextblock', 'Cortex AI', 'Un guide pratique de Cortex AI, l''assistant conscient des blocs pour le routage des modèles, le contrôle BYOK et une production éditoriale plus rapide dans NextBlock.', 'Découvrez comment Cortex AI apporte la génération structurée, le choix du fournisseur et des flux de contenu plus sûrs directement dans l''éditeur NextBlock.',
58
+ 'published', '2026-05-27T13:24:00+00:00'::timestamptz,
59
+ 'Guide NextBlock Cortex AI', 'Découvrez comment NextBlock Cortex AI aide les équipes à générer, affiner et traduire du contenu par blocs structuré, avec routage des modèles et contrôle BYOK.',
60
+ (SELECT id FROM public.media WHERE id = '8414dc5a-92d7-4cbf-8ecf-2fc8ec91a0a3'::uuid),
61
+ 1, 'dbe2a06f-1a9d-48ba-bc35-0f6ef4869156'::uuid)
62
+ RETURNING id INTO v_post;
63
+
64
+ INSERT INTO public.blocks (post_id, language_id, block_type, content, "order")
65
+ VALUES (v_post, v_fr, 'text', $nb${"html_content":"\n<p class='text-lg leading-8 text-slate-700 dark:text-slate-300'>NextBlock Cortex AI est l'outil de contenu intelligent conçu pour les pages web modernes. Il comprend les blocs de page, les mises en page de sections et les règles éditoriales, pour que vous créiez un meilleur contenu, plus vite.</p>\n\n<div class='grid gap-4 md:grid-cols-3 my-10'>\n <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'>\n <p class='text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200'>Routage des modèles</p>\n <h2 class='mt-3 text-xl font-semibold text-slate-900 dark:text-white'>Choisissez le bon modèle</h2>\n <p class='mt-3 text-sm text-slate-600 dark:text-slate-300'>Acheminez vos prompts via OpenRouter ou votre propre fournisseur pour équilibrer vitesse et prix.</p>\n </div>\n <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'>\n <p class='text-xs font-semibold uppercase tracking-[0.22em] text-sky-700 dark:text-sky-200'>Contrôle BYOK</p>\n <h2 class='mt-3 text-xl font-semibold text-slate-900 dark:text-white'>Utilisez vos propres clés</h2>\n <p class='mt-3 text-sm text-slate-600 dark:text-slate-300'>Gardez les clés des fournisseurs en sécurité sur votre serveur tout en offrant aux éditeurs un écran de rédaction IA tout simple.</p>\n </div>\n <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'>\n <p class='text-xs font-semibold uppercase tracking-[0.22em] text-emerald-700 dark:text-emerald-200'>Sortie typée</p>\n <h2 class='mt-3 text-xl font-semibold text-slate-900 dark:text-white'>Générez des blocs valides</h2>\n <p class='mt-3 text-sm text-slate-600 dark:text-slate-300'>Des schémas typés garantissent que le contenu IA s'insère directement dans vos pages sous forme de blocs propres et fonctionnels.</p>\n </div>\n</div>\n\n<h2>Pourquoi Cortex AI a sa place dans l'éditeur</h2>\n<p>Les outils de clavardage génériques peuvent rédiger du texte, mais ils ne font pas la différence entre une bannière héros, une grille de cartes et un article de blogue. Cortex AI vit directement dans votre écran d'édition. Il crée du contenu qui s'ajuste aux blocs de votre site en ligne.</p>\n<p>L'IA devient ainsi vraiment utile au quotidien. Vous pouvez ébaucher une nouvelle section d'accueil, peaufiner un résumé, enrichir une fiche produit ou traduire un article complet en toute simplicité.</p>\n\n<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'>\n <p class='text-xs font-semibold uppercase tracking-[0.22em] text-violet-700 dark:text-violet-200'>Flux éditorial</p>\n <div class='grid gap-5 md:grid-cols-2 mt-5'>\n <div class='rounded-2xl border border-slate-200 bg-white p-5 dark:border-white/10 dark:bg-slate-950/50'>\n <h3 class='mt-0 text-xl text-slate-900 dark:text-white'>Des premiers jets plus rapides</h3>\n <p class='text-sm text-slate-600 dark:text-slate-300'>Partez d'un prompt et obtenez une section, un brouillon d'article ou une histoire de produit qui respecte votre ton.</p>\n </div>\n <div class='rounded-2xl border border-slate-200 bg-white p-5 dark:border-white/10 dark:bg-slate-950/50'>\n <h3 class='mt-0 text-xl text-slate-900 dark:text-white'>Des révisions plus nettes</h3>\n <p class='text-sm text-slate-600 dark:text-slate-300'>Demandez un texte plus court, plus clair ou traduit, sans quitter votre écran d'édition.</p>\n </div>\n </div>\n</div>\n\n<h2>Routage des modèles et contrôle des coûts</h2>\n<p>Cortex AI vous donne le plein contrôle sur vos modèles. Choisissez des modèles rapides pour les brouillons express et des modèles plus puissants pour les articles techniques. Vous gérez vos clés d'API sur le serveur, pour que vos rédacteurs se concentrent sur le contenu.</p>\n<ul class='list-disc pl-6 space-y-2 text-sm'>\n <li>Utilisez des modèles rapides pour les réécritures, les titres et les résumés.</li>\n <li>Utilisez les meilleurs modèles pour les longs guides et les traductions difficiles.</li>\n <li>Gardez les clés des fournisseurs en sécurité dans vos réglages serveur privés.</li>\n <li>Maîtrisez les coûts sans changer l'affichage des pages pour les visiteurs.</li>\n</ul>\n\n<h2>Génération consciente des blocs</h2>\n<p>Cortex AI fait plus qu'écrire du texte brut. Il crée du contenu structuré qui correspond directement aux composants NextBlock. Vous obtenez des textes de section, des titres, des boutons et des blocs traduits prêts à l'emploi. Vous passez moins de temps à corriger les textes brouillons venus d'outils externes.</p>\n<p>Comme le contenu généré respecte vos règles de blocs, tout reste cohérent et rapide sur le web.</p>\n\n<h2>Des flux d'équipe plus sûrs</h2>\n<p>L'IA donne le meilleur d'elle-même quand les humains gardent le contrôle. Avec Cortex AI, les éditeurs révisent chaque brouillon avant publication. Les développeurs gèrent les clés des modèles, et le CMS conserve toutes les versions dans votre historique habituel.</p>\n\n<h2>Un flux de lancement concret</h2>\n<ol class='list-decimal pl-6 space-y-2 text-sm'>\n <li>Ébauchez un article, une section d'accueil ou une histoire de produit à partir d'un prompt clair.</li>\n <li>Affinez le texte pour qu'il colle à votre public et au ton de votre marque.</li>\n <li>Créez une version traduite ou un résumé plus court pour les cartes sociales et les balises de recherche.</li>\n <li>Révisez le contenu dans l'éditeur, publiez, puis suivez vos révisions au fil du temps.</li>\n</ol>\n\n<p>Cortex AI transforme votre CMS en atelier créatif plus rapide. Il ne remplace pas le goût humain, mais il vous aide à transformer de bonnes idées en pages finies en un temps record.</p>\n"}$nb$::jsonb, 0);
66
+ END IF;
67
+ END $$;
@@ -1,72 +1,72 @@
1
- -- 02010: shop hero redesign -- shorter copy, a product image, and a compact benefits
2
- -- strip below the product grid (EN 'shop' and FR 'boutique').
3
- --
4
- -- The previous hero was a full-width primary-coloured block holding an h1, an intro
5
- -- line, a second heading, two long paragraphs and a four-item bullet list: ~1,000 px
6
- -- of text and no image, written to satisfy the SEO grader rather than a visitor. It
7
- -- now mirrors the home hero: dark gradient, two columns, one h1, one sentence, two
8
- -- CTAs, and the NextBlock Commerce storefront image (bundled `/images/commerce-wide.webp`,
9
- -- which the rich-text renderer serves through next/image; as the first hero image it
10
- -- is preloaded as the page's LCP element). The four purchase benefits move into a
11
- -- compact card strip after the product grid so the page keeps its supporting copy
12
- -- without it living in the hero.
13
- --
14
- -- Both languages ship together (bilingual content rule). Scoped by parent page +
15
- -- position + a signature of the OLD copy, never by blocks.id: each UPDATE runs once
16
- -- and a re-run matches nothing. The benefits strip is inserted once per page, guarded
17
- -- by its `nb-store-benefits` sentinel. Identity sequences are re-synced first because
18
- -- the seed inserts explicit ids.
19
-
20
- DO $$
21
- DECLARE
22
- v_en bigint;
23
- v_fr bigint;
24
- v_shop bigint;
25
- v_boutique bigint;
26
- BEGIN
27
- SELECT id INTO v_en FROM public.languages WHERE code = 'en' LIMIT 1;
28
- SELECT id INTO v_fr FROM public.languages WHERE code = 'fr' LIMIT 1;
29
- IF v_en IS NULL THEN
30
- RAISE NOTICE '02010: no English language row; nothing to do.';
31
- RETURN;
32
- END IF;
33
-
34
- SELECT id INTO v_shop FROM public.pages WHERE slug = 'shop' AND language_id = v_en LIMIT 1;
35
- IF v_fr IS NOT NULL THEN
36
- SELECT id INTO v_boutique FROM public.pages WHERE slug = 'boutique' AND language_id = v_fr LIMIT 1;
37
- END IF;
38
-
39
- PERFORM setval('public.blocks_id_seq', COALESCE((SELECT MAX(id) FROM public.blocks), 0) + 1, false);
40
-
41
- -- ---------------------------------------------------------------- EN: /shop
42
- IF v_shop IS NOT NULL THEN
43
- UPDATE public.blocks
44
- SET content = $nb${"is_hero":true,"padding":{"top":"lg","bottom":"lg"},"background":{"type":"gradient","gradient":{"type":"linear","direction":"135deg","stops":[{"color":"#020817","position":0},{"color":"#0f172a","position":50},{"color":"#1e293b","position":100}]}},"column_gap":"xl","container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":2},"vertical_alignment":"center","column_blocks":[[{"block_type":"text","content":{"html_content":"<p class='text-xs uppercase tracking-[0.3em] text-cyan-300 font-semibold mb-3'>Official store</p><h1 class='text-4xl md:text-5xl font-extrabold text-white leading-tight mb-4'>NextBlock™ Store</h1><p class='text-lg text-slate-300 leading-relaxed mb-2'>Official licenses for NextBlock™ Commerce and Cortex AI. Instant access, full source code and secure checkout with Stripe and Freemius.</p>"}},{"block_type":"button","content":{"text":"Get NextBlock™ Commerce","url":"/product/nextblock-commerce-pro-commerce-license","variant":"default","size":"lg","position":"left"}},{"block_type":"button","content":{"text":"Start the free Cortex AI trial","url":"/product/nextblock-cortex-ai-cortex-ai-license","variant":"outline","size":"lg","position":"left"}}],[{"block_type":"text","content":{"html_content":"<div class='rounded-3xl overflow-hidden border border-white/10 bg-white/5 p-3 shadow-2xl'><img src='/images/commerce-wide.webp' alt='NextBlock™ Commerce storefront with catalog, cart and checkout' class='w-full h-auto rounded-2xl' /></div>"}}]]}$nb$::jsonb,
45
- updated_at = now()
46
- WHERE page_id = v_shop
47
- AND "order" = 0
48
- AND block_type = 'section'
49
- AND content::text LIKE '%Discover our selection of official commercial add-ons%';
50
-
51
- IF NOT EXISTS (SELECT 1 FROM public.blocks WHERE page_id = v_shop AND content::text LIKE '%nb-store-benefits%') THEN
52
- INSERT INTO public.blocks (page_id, language_id, block_type, content, "order")
53
- VALUES (v_shop, v_en, 'section', $nb${"padding":{"top":"lg","bottom":"xl"},"background":{"type":"none"},"column_gap":"md","container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":1},"vertical_alignment":"start","column_blocks":[[{"block_type":"text","content":{"html_content":"<div class='nb-store-benefits'><h2 class='text-2xl md:text-3xl font-bold text-foreground text-center mb-8'>Why buy from the official store</h2><div class='grid gap-6 md:grid-cols-2 lg:grid-cols-4'><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>🧩</p><h3 class='text-base font-bold text-foreground mb-2'>Full source code</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Inspect, customize and adapt every module to your exact requirements.</p></div><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>♾️</p><h3 class='text-base font-bold text-foreground mb-2'>Perpetual use</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Use the software on your project with full peace of mind.</p></div><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>🔄</p><h3 class='text-base font-bold text-foreground mb-2'>Automated updates</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Smooth updates that follow each release of NextBlock and Next.js.</p></div><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>🔒</p><h3 class='text-base font-bold text-foreground mb-2'>Secure checkout</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Payments processed safely by Stripe and Freemius, invoice included.</p></div></div></div>"}}]]}$nb$::jsonb, 2);
54
- END IF;
55
- END IF;
56
-
57
- -- ---------------------------------------------------------------- FR: /boutique
58
- IF v_boutique IS NOT NULL THEN
59
- UPDATE public.blocks
60
- SET content = $nb${"is_hero":true,"padding":{"top":"lg","bottom":"lg"},"background":{"type":"gradient","gradient":{"type":"linear","direction":"135deg","stops":[{"color":"#020817","position":0},{"color":"#0f172a","position":50},{"color":"#1e293b","position":100}]}},"column_gap":"xl","container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":2},"vertical_alignment":"center","column_blocks":[[{"block_type":"text","content":{"html_content":"<p class='text-xs uppercase tracking-[0.3em] text-cyan-300 font-semibold mb-3'>Boutique officielle</p><h1 class='text-4xl md:text-5xl font-extrabold text-white leading-tight mb-4'>Boutique NextBlock™</h1><p class='text-lg text-slate-300 leading-relaxed mb-2'>Licences officielles pour NextBlock™ Commerce et Cortex AI. Accès immédiat, code source complet et paiement sécurisé avec Stripe et Freemius.</p>"}},{"block_type":"button","content":{"text":"Obtenir NextBlock™ Commerce","url":"/product/nextblock-commerce-pro-commerce-license-fr","variant":"default","size":"lg","position":"left"}},{"block_type":"button","content":{"text":"Commencer l'essai gratuit de Cortex AI","url":"/product/nextblock-cortex-ai-cortex-ai-license-fr","variant":"outline","size":"lg","position":"left"}}],[{"block_type":"text","content":{"html_content":"<div class='rounded-3xl overflow-hidden border border-white/10 bg-white/5 p-3 shadow-2xl'><img src='/images/commerce-wide.webp' alt='Vitrine NextBlock™ Commerce avec catalogue, panier et paiement' class='w-full h-auto rounded-2xl' /></div>"}}]]}$nb$::jsonb,
61
- updated_at = now()
62
- WHERE page_id = v_boutique
63
- AND "order" = 0
64
- AND block_type = 'section'
65
- AND content::text LIKE '%nos extensions officielles et nos outils%';
66
-
67
- IF NOT EXISTS (SELECT 1 FROM public.blocks WHERE page_id = v_boutique AND content::text LIKE '%nb-store-benefits%') THEN
68
- INSERT INTO public.blocks (page_id, language_id, block_type, content, "order")
69
- VALUES (v_boutique, v_fr, 'section', $nb${"padding":{"top":"lg","bottom":"xl"},"background":{"type":"none"},"column_gap":"md","container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":1},"vertical_alignment":"start","column_blocks":[[{"block_type":"text","content":{"html_content":"<div class='nb-store-benefits'><h2 class='text-2xl md:text-3xl font-bold text-foreground text-center mb-8'>Pourquoi acheter sur la boutique officielle</h2><div class='grid gap-6 md:grid-cols-2 lg:grid-cols-4'><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>🧩</p><h3 class='text-base font-bold text-foreground mb-2'>Code source complet</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Lisez, adaptez et faites évoluer chaque module selon vos besoins.</p></div><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>♾️</p><h3 class='text-base font-bold text-foreground mb-2'>Licence perpétuelle</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Utilisez le logiciel sur votre projet en toute sérénité.</p></div><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>🔄</p><h3 class='text-base font-bold text-foreground mb-2'>Mises à jour suivies</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Des mises à jour fluides qui suivent chaque version de NextBlock et de Next.js.</p></div><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>🔒</p><h3 class='text-base font-bold text-foreground mb-2'>Paiement sécurisé</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Paiements traités en toute sécurité par Stripe et Freemius, facture incluse.</p></div></div></div>"}}]]}$nb$::jsonb, 2);
70
- END IF;
71
- END IF;
72
- END $$;
1
+ -- 02010: shop hero redesign -- shorter copy, a product image, and a compact benefits
2
+ -- strip below the product grid (EN 'shop' and FR 'boutique').
3
+ --
4
+ -- The previous hero was a full-width primary-coloured block holding an h1, an intro
5
+ -- line, a second heading, two long paragraphs and a four-item bullet list: ~1,000 px
6
+ -- of text and no image, written to satisfy the SEO grader rather than a visitor. It
7
+ -- now mirrors the home hero: dark gradient, two columns, one h1, one sentence, two
8
+ -- CTAs, and the NextBlock Commerce storefront image (bundled `/images/commerce-wide.webp`,
9
+ -- which the rich-text renderer serves through next/image; as the first hero image it
10
+ -- is preloaded as the page's LCP element). The four purchase benefits move into a
11
+ -- compact card strip after the product grid so the page keeps its supporting copy
12
+ -- without it living in the hero.
13
+ --
14
+ -- Both languages ship together (bilingual content rule). Scoped by parent page +
15
+ -- position + a signature of the OLD copy, never by blocks.id: each UPDATE runs once
16
+ -- and a re-run matches nothing. The benefits strip is inserted once per page, guarded
17
+ -- by its `nb-store-benefits` sentinel. Identity sequences are re-synced first because
18
+ -- the seed inserts explicit ids.
19
+
20
+ DO $$
21
+ DECLARE
22
+ v_en bigint;
23
+ v_fr bigint;
24
+ v_shop bigint;
25
+ v_boutique bigint;
26
+ BEGIN
27
+ SELECT id INTO v_en FROM public.languages WHERE code = 'en' LIMIT 1;
28
+ SELECT id INTO v_fr FROM public.languages WHERE code = 'fr' LIMIT 1;
29
+ IF v_en IS NULL THEN
30
+ RAISE NOTICE '02010: no English language row; nothing to do.';
31
+ RETURN;
32
+ END IF;
33
+
34
+ SELECT id INTO v_shop FROM public.pages WHERE slug = 'shop' AND language_id = v_en LIMIT 1;
35
+ IF v_fr IS NOT NULL THEN
36
+ SELECT id INTO v_boutique FROM public.pages WHERE slug = 'boutique' AND language_id = v_fr LIMIT 1;
37
+ END IF;
38
+
39
+ PERFORM setval('public.blocks_id_seq', COALESCE((SELECT MAX(id) FROM public.blocks), 0) + 1, false);
40
+
41
+ -- ---------------------------------------------------------------- EN: /shop
42
+ IF v_shop IS NOT NULL THEN
43
+ UPDATE public.blocks
44
+ SET content = $nb${"is_hero":true,"padding":{"top":"lg","bottom":"lg"},"background":{"type":"gradient","gradient":{"type":"linear","direction":"135deg","stops":[{"color":"#020817","position":0},{"color":"#0f172a","position":50},{"color":"#1e293b","position":100}]}},"column_gap":"xl","container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":2},"vertical_alignment":"center","column_blocks":[[{"block_type":"text","content":{"html_content":"<p class='text-xs uppercase tracking-[0.3em] text-cyan-300 font-semibold mb-3'>Official store</p><h1 class='text-4xl md:text-5xl font-extrabold text-white leading-tight mb-4'>NextBlock™ Store</h1><p class='text-lg text-slate-300 leading-relaxed mb-2'>Official licenses for NextBlock™ Commerce and Cortex AI. Instant access, full source code and secure checkout with Stripe and Freemius.</p>"}},{"block_type":"button","content":{"text":"Get NextBlock™ Commerce","url":"/product/nextblock-commerce-pro-commerce-license","variant":"default","size":"lg","position":"left"}},{"block_type":"button","content":{"text":"Start the free Cortex AI trial","url":"/product/nextblock-cortex-ai-cortex-ai-license","variant":"outline","size":"lg","position":"left"}}],[{"block_type":"text","content":{"html_content":"<div class='rounded-3xl overflow-hidden border border-white/10 bg-white/5 p-3 shadow-2xl'><img src='/images/commerce-wide.webp' alt='NextBlock™ Commerce storefront with catalog, cart and checkout' class='w-full h-auto rounded-2xl' /></div>"}}]]}$nb$::jsonb,
45
+ updated_at = now()
46
+ WHERE page_id = v_shop
47
+ AND "order" = 0
48
+ AND block_type = 'section'
49
+ AND content::text LIKE '%Discover our selection of official commercial add-ons%';
50
+
51
+ IF NOT EXISTS (SELECT 1 FROM public.blocks WHERE page_id = v_shop AND content::text LIKE '%nb-store-benefits%') THEN
52
+ INSERT INTO public.blocks (page_id, language_id, block_type, content, "order")
53
+ VALUES (v_shop, v_en, 'section', $nb${"padding":{"top":"lg","bottom":"xl"},"background":{"type":"none"},"column_gap":"md","container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":1},"vertical_alignment":"start","column_blocks":[[{"block_type":"text","content":{"html_content":"<div class='nb-store-benefits'><h2 class='text-2xl md:text-3xl font-bold text-foreground text-center mb-8'>Why buy from the official store</h2><div class='grid gap-6 md:grid-cols-2 lg:grid-cols-4'><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>🧩</p><h3 class='text-base font-bold text-foreground mb-2'>Full source code</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Inspect, customize and adapt every module to your exact requirements.</p></div><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>♾️</p><h3 class='text-base font-bold text-foreground mb-2'>Perpetual use</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Use the software on your project with full peace of mind.</p></div><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>🔄</p><h3 class='text-base font-bold text-foreground mb-2'>Automated updates</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Smooth updates that follow each release of NextBlock and Next.js.</p></div><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>🔒</p><h3 class='text-base font-bold text-foreground mb-2'>Secure checkout</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Payments processed safely by Stripe and Freemius, invoice included.</p></div></div></div>"}}]]}$nb$::jsonb, 2);
54
+ END IF;
55
+ END IF;
56
+
57
+ -- ---------------------------------------------------------------- FR: /boutique
58
+ IF v_boutique IS NOT NULL THEN
59
+ UPDATE public.blocks
60
+ SET content = $nb${"is_hero":true,"padding":{"top":"lg","bottom":"lg"},"background":{"type":"gradient","gradient":{"type":"linear","direction":"135deg","stops":[{"color":"#020817","position":0},{"color":"#0f172a","position":50},{"color":"#1e293b","position":100}]}},"column_gap":"xl","container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":2},"vertical_alignment":"center","column_blocks":[[{"block_type":"text","content":{"html_content":"<p class='text-xs uppercase tracking-[0.3em] text-cyan-300 font-semibold mb-3'>Boutique officielle</p><h1 class='text-4xl md:text-5xl font-extrabold text-white leading-tight mb-4'>Boutique NextBlock™</h1><p class='text-lg text-slate-300 leading-relaxed mb-2'>Licences officielles pour NextBlock™ Commerce et Cortex AI. Accès immédiat, code source complet et paiement sécurisé avec Stripe et Freemius.</p>"}},{"block_type":"button","content":{"text":"Obtenir NextBlock™ Commerce","url":"/product/nextblock-commerce-pro-commerce-license-fr","variant":"default","size":"lg","position":"left"}},{"block_type":"button","content":{"text":"Commencer l'essai gratuit de Cortex AI","url":"/product/nextblock-cortex-ai-cortex-ai-license-fr","variant":"outline","size":"lg","position":"left"}}],[{"block_type":"text","content":{"html_content":"<div class='rounded-3xl overflow-hidden border border-white/10 bg-white/5 p-3 shadow-2xl'><img src='/images/commerce-wide.webp' alt='Vitrine NextBlock™ Commerce avec catalogue, panier et paiement' class='w-full h-auto rounded-2xl' /></div>"}}]]}$nb$::jsonb,
61
+ updated_at = now()
62
+ WHERE page_id = v_boutique
63
+ AND "order" = 0
64
+ AND block_type = 'section'
65
+ AND content::text LIKE '%nos extensions officielles et nos outils%';
66
+
67
+ IF NOT EXISTS (SELECT 1 FROM public.blocks WHERE page_id = v_boutique AND content::text LIKE '%nb-store-benefits%') THEN
68
+ INSERT INTO public.blocks (page_id, language_id, block_type, content, "order")
69
+ VALUES (v_boutique, v_fr, 'section', $nb${"padding":{"top":"lg","bottom":"xl"},"background":{"type":"none"},"column_gap":"md","container_type":"container","responsive_columns":{"mobile":1,"tablet":1,"desktop":1},"vertical_alignment":"start","column_blocks":[[{"block_type":"text","content":{"html_content":"<div class='nb-store-benefits'><h2 class='text-2xl md:text-3xl font-bold text-foreground text-center mb-8'>Pourquoi acheter sur la boutique officielle</h2><div class='grid gap-6 md:grid-cols-2 lg:grid-cols-4'><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>🧩</p><h3 class='text-base font-bold text-foreground mb-2'>Code source complet</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Lisez, adaptez et faites évoluer chaque module selon vos besoins.</p></div><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>♾️</p><h3 class='text-base font-bold text-foreground mb-2'>Licence perpétuelle</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Utilisez le logiciel sur votre projet en toute sérénité.</p></div><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>🔄</p><h3 class='text-base font-bold text-foreground mb-2'>Mises à jour suivies</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Des mises à jour fluides qui suivent chaque version de NextBlock et de Next.js.</p></div><div class='rounded-2xl border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900'><p class='text-2xl mb-3'>🔒</p><h3 class='text-base font-bold text-foreground mb-2'>Paiement sécurisé</h3><p class='text-sm text-slate-600 dark:text-slate-400'>Paiements traités en toute sécurité par Stripe et Freemius, facture incluse.</p></div></div></div>"}}]]}$nb$::jsonb, 2);
70
+ END IF;
71
+ END IF;
72
+ END $$;
@@ -1,26 +1,26 @@
1
- -- 02011: remove `backdrop-blur-*` from page blocks (home EN/FR cards, articles heroes).
2
- --
3
- -- Every card sitting on the dark gradient heroes used `backdrop-filter: blur()` via
4
- -- Tailwind's backdrop-blur utilities (`backdrop-blur-xl` on the home hero card and the
5
- -- live-demo promo, `backdrop-blur` on the three MCP-step cards, `backdrop-blur-sm` on
6
- -- the commerce card and the articles heroes). A backdrop blur forces the compositor to
7
- -- read back and blur everything behind the element on every frame; in Lighthouse's
8
- -- trace of the home page the GPU process spent ~390 ms drawing the very first frame,
9
- -- which is the gap between the hero being laid out and the first contentful paint.
10
- -- Behind these cards there is only a smooth gradient or a solid colour, so the blur has
11
- -- no visible effect: `bg-white/5` alone gives the same translucent card.
12
- --
13
- -- Scoped to page blocks that carry the utility (posts and products never did), both
14
- -- languages at once; `regexp_replace` strips the class token wherever it appears in a
15
- -- class list. Idempotent: once stripped, the row no longer matches. page_revisions get
16
- -- the same rewrite so restoring a revision cannot bring the blur back.
17
-
18
- UPDATE public.blocks
19
- SET content = regexp_replace(content::text, '\sbackdrop-blur(-[a-z0-9]+)?', '', 'g')::jsonb,
20
- updated_at = now()
21
- WHERE page_id IS NOT NULL
22
- AND content::text ~ 'backdrop-blur';
23
-
24
- UPDATE public.page_revisions
25
- SET content = regexp_replace(content::text, '\sbackdrop-blur(-[a-z0-9]+)?', '', 'g')::jsonb
26
- WHERE content::text ~ 'backdrop-blur';
1
+ -- 02011: remove `backdrop-blur-*` from page blocks (home EN/FR cards, articles heroes).
2
+ --
3
+ -- Every card sitting on the dark gradient heroes used `backdrop-filter: blur()` via
4
+ -- Tailwind's backdrop-blur utilities (`backdrop-blur-xl` on the home hero card and the
5
+ -- live-demo promo, `backdrop-blur` on the three MCP-step cards, `backdrop-blur-sm` on
6
+ -- the commerce card and the articles heroes). A backdrop blur forces the compositor to
7
+ -- read back and blur everything behind the element on every frame; in Lighthouse's
8
+ -- trace of the home page the GPU process spent ~390 ms drawing the very first frame,
9
+ -- which is the gap between the hero being laid out and the first contentful paint.
10
+ -- Behind these cards there is only a smooth gradient or a solid colour, so the blur has
11
+ -- no visible effect: `bg-white/5` alone gives the same translucent card.
12
+ --
13
+ -- Scoped to page blocks that carry the utility (posts and products never did), both
14
+ -- languages at once; `regexp_replace` strips the class token wherever it appears in a
15
+ -- class list. Idempotent: once stripped, the row no longer matches. page_revisions get
16
+ -- the same rewrite so restoring a revision cannot bring the blur back.
17
+
18
+ UPDATE public.blocks
19
+ SET content = regexp_replace(content::text, '\sbackdrop-blur(-[a-z0-9]+)?', '', 'g')::jsonb,
20
+ updated_at = now()
21
+ WHERE page_id IS NOT NULL
22
+ AND content::text ~ 'backdrop-blur';
23
+
24
+ UPDATE public.page_revisions
25
+ SET content = regexp_replace(content::text, '\sbackdrop-blur(-[a-z0-9]+)?', '', 'g')::jsonb
26
+ WHERE content::text ~ 'backdrop-blur';