create-nextblock 0.11.2 → 0.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +114 -0
- package/templates/nextblock-template/docs/13-STAYING-UP-TO-DATE.md +7 -0
- package/templates/nextblock-template/lib/setup/migrations-bundle.ts +10 -0
- package/templates/nextblock-template/package.json +1 -1
package/package.json
CHANGED
|
@@ -9092,6 +9092,120 @@ WHERE content::text LIKE '%Des questions ?%'
|
|
|
9092
9092
|
AND content::text NOT LIKE '%Déployer sur Vercel%';
|
|
9093
9093
|
|
|
9094
9094
|
|
|
9095
|
+
-- >>> FROM: 00000000000043_swap_home_hero_media_to_youtube.sql <<<
|
|
9096
|
+
-- Swap the home HERO media from the static NBcover image to an embedded YouTube video.
|
|
9097
|
+
--
|
|
9098
|
+
-- The seeded home hero (migration 010) renders a "Why teams switch / 100% Lighthouse"
|
|
9099
|
+
-- card in its right column whose last element is an <img src="/images/NBcover.webp" />.
|
|
9100
|
+
-- This replaces just that <img> with a responsive 16:9 YouTube <iframe>, keeping the
|
|
9101
|
+
-- surrounding card, its rounded/border/shadow wrapper, and every other block intact.
|
|
9102
|
+
--
|
|
9103
|
+
-- Rendering path: the hero right column is a 'text' block; TextBlockRenderer feeds the
|
|
9104
|
+
-- html_content through html-react-parser, which preserves <iframe> (it only strips on*
|
|
9105
|
+
-- handlers and swaps known CMS <img> for next/image). The proxy.ts CSP frame-src already
|
|
9106
|
+
-- allows https://www.youtube.com, so the embed is not blocked.
|
|
9107
|
+
--
|
|
9108
|
+
-- Forward-only and idempotent:
|
|
9109
|
+
-- * Each UPDATE matches the language-specific <img> alt text, so a second run finds no
|
|
9110
|
+
-- match and is a no-op (the alt text no longer exists once swapped).
|
|
9111
|
+
-- * String replace on content::text mirrors migration 042; the img markup is unique to
|
|
9112
|
+
-- the home hero, so exactly the EN and FR home hero blocks are touched.
|
|
9113
|
+
--
|
|
9114
|
+
-- The NBcover.webp media row is left untouched — it is still the feature image for the
|
|
9115
|
+
-- "how-nextblock-works" post; only the inline hero usage changes.
|
|
9116
|
+
|
|
9117
|
+
-- ---------------------------------------------------------------------------
|
|
9118
|
+
-- 1. EN home hero: replace NBcover <img> with a YouTube <iframe>
|
|
9119
|
+
-- ---------------------------------------------------------------------------
|
|
9120
|
+
UPDATE public.blocks
|
|
9121
|
+
SET content = replace(
|
|
9122
|
+
content::text,
|
|
9123
|
+
'<img src=''/images/NBcover.webp'' alt=''Nextblock cover showcasing dashboards and blocks'' class=''w-full h-auto object-cover transform group-hover:scale-105 transition-transform duration-700'' fetchpriority=''high'' />',
|
|
9124
|
+
'<div class=''relative w-full aspect-video''><iframe class=''absolute inset-0 h-full w-full border-0'' src=''https://www.youtube.com/embed/71MyfoL4YVM?si=jtlDXV6cSC8rDgz0'' title=''NextBlock demo video'' allow=''accelerated-motion; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'' referrerpolicy=''strict-origin-when-cross-origin'' loading=''lazy'' allowfullscreen></iframe></div>'
|
|
9125
|
+
)::jsonb
|
|
9126
|
+
WHERE content::text LIKE '%Nextblock cover showcasing dashboards and blocks%';
|
|
9127
|
+
|
|
9128
|
+
-- ---------------------------------------------------------------------------
|
|
9129
|
+
-- 2. FR home hero: replace NBcover <img> with a YouTube <iframe>
|
|
9130
|
+
-- ---------------------------------------------------------------------------
|
|
9131
|
+
UPDATE public.blocks
|
|
9132
|
+
SET content = replace(
|
|
9133
|
+
content::text,
|
|
9134
|
+
'<img src=''/images/NBcover.webp'' alt=''Couverture Nextblock'' class=''w-full h-auto object-cover transform group-hover:scale-105 transition-transform duration-700'' fetchpriority=''high'' />',
|
|
9135
|
+
'<div class=''relative w-full aspect-video''><iframe class=''absolute inset-0 h-full w-full border-0'' src=''https://www.youtube.com/embed/71MyfoL4YVM?si=jtlDXV6cSC8rDgz0'' title=''Vidéo de démonstration NextBlock'' allow=''accelerated-motion; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'' referrerpolicy=''strict-origin-when-cross-origin'' loading=''lazy'' allowfullscreen></iframe></div>'
|
|
9136
|
+
)::jsonb
|
|
9137
|
+
WHERE content::text LIKE '%Couverture Nextblock%';
|
|
9138
|
+
|
|
9139
|
+
|
|
9140
|
+
-- >>> FROM: 00000000000044_swap_article_nx_graph_for_youtube.sql <<<
|
|
9141
|
+
-- Swap the Nx-graph image in the "How NextBlock™ Works" article for an embedded
|
|
9142
|
+
-- YouTube video, and rebalance that two-column section to an even 50/50 split.
|
|
9143
|
+
--
|
|
9144
|
+
-- Targets the post-body 'text' block (dollar-quoted html_content seeded in migration
|
|
9145
|
+
-- 010) for both language variants of the same post:
|
|
9146
|
+
-- * EN slug how-nextblock-works (img alt "Nx project graph preview ...")
|
|
9147
|
+
-- * FR slug comment-nextblock-fonctionne (img alt "Apercu du graphe Nx ...")
|
|
9148
|
+
--
|
|
9149
|
+
-- Three forward-only, idempotent edits:
|
|
9150
|
+
-- 1. Column widths md:w-3/5 (text) and md:w-2/5 (media) -> md:w-1/2 each, and the
|
|
9151
|
+
-- flex row switches items-start -> items-center so the shorter media column sits
|
|
9152
|
+
-- centered against the taller text column. These class fragments occur only in
|
|
9153
|
+
-- this one section (EN + FR), so a single UPDATE rebalances both languages.
|
|
9154
|
+
-- 2/3. Replace the <img src="/images/nx-graph.webp" ...> with a responsive 16:9
|
|
9155
|
+
-- YouTube <iframe>, kept inside the existing white aside card above its caption.
|
|
9156
|
+
--
|
|
9157
|
+
-- Rendering/CSP identical to migration 043: TextBlockRenderer -> html-react-parser
|
|
9158
|
+
-- preserves the <iframe>; proxy.ts CSP frame-src allows www.youtube.com; every utility
|
|
9159
|
+
-- class used here lives in this .sql file, which Tailwind's content scanner
|
|
9160
|
+
-- (libs/**/*.sql) compiles into the bundle. The nx-graph.webp media row is left intact.
|
|
9161
|
+
--
|
|
9162
|
+
-- Each UPDATE is guarded by a substring that only exists pre-swap, so a second run is a
|
|
9163
|
+
-- no-op. Dollar-quoted string literals ($old$/$new$) avoid escaping the single-quoted
|
|
9164
|
+
-- HTML attributes; the sandbox reset runs this via postgres db.unsafe() (no outer
|
|
9165
|
+
-- dollar-quote wrapper), same as migration 010's dollar-quoted seed content.
|
|
9166
|
+
|
|
9167
|
+
-- ---------------------------------------------------------------------------
|
|
9168
|
+
-- 1. Both languages: 3/5 + 2/5 columns -> 50/50, and vertical-center the row
|
|
9169
|
+
-- ---------------------------------------------------------------------------
|
|
9170
|
+
UPDATE public.blocks
|
|
9171
|
+
SET content = replace(
|
|
9172
|
+
replace(
|
|
9173
|
+
replace(
|
|
9174
|
+
content::text,
|
|
9175
|
+
'flex flex-col md:flex-row gap-8 items-start my-12',
|
|
9176
|
+
'flex flex-col md:flex-row gap-8 items-center my-12'
|
|
9177
|
+
),
|
|
9178
|
+
'w-full md:w-3/5 space-y-4',
|
|
9179
|
+
'w-full md:w-1/2 space-y-4'
|
|
9180
|
+
),
|
|
9181
|
+
'md:w-2/5 rounded-[2rem]',
|
|
9182
|
+
'md:w-1/2 rounded-[2rem]'
|
|
9183
|
+
)::jsonb
|
|
9184
|
+
WHERE content::text LIKE '%w-full md:w-3/5 space-y-4%';
|
|
9185
|
+
|
|
9186
|
+
-- ---------------------------------------------------------------------------
|
|
9187
|
+
-- 2. EN post body: nx-graph <img> -> responsive YouTube <iframe>
|
|
9188
|
+
-- ---------------------------------------------------------------------------
|
|
9189
|
+
UPDATE public.blocks
|
|
9190
|
+
SET content = replace(
|
|
9191
|
+
content::text,
|
|
9192
|
+
$old$<img src='/images/nx-graph.webp' alt='Nx project graph preview showing apps and shared libraries linked together' class='w-full h-auto rounded-2xl object-cover' />$old$,
|
|
9193
|
+
$new$<div class='relative aspect-video overflow-hidden rounded-2xl'><iframe class='absolute inset-0 h-full w-full border-0' src='https://www.youtube.com/embed/DNqU8ez9qjs?si=p2oIy0f-n7wiaBmO' title='How NextBlock™ Works' allow='accelerated-motion; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share' referrerpolicy='strict-origin-when-cross-origin' loading='lazy' allowfullscreen></iframe></div>$new$
|
|
9194
|
+
)::jsonb
|
|
9195
|
+
WHERE content::text LIKE '%Nx project graph preview showing apps and shared libraries linked together%';
|
|
9196
|
+
|
|
9197
|
+
-- ---------------------------------------------------------------------------
|
|
9198
|
+
-- 3. FR post body: nx-graph <img> -> responsive YouTube <iframe>
|
|
9199
|
+
-- ---------------------------------------------------------------------------
|
|
9200
|
+
UPDATE public.blocks
|
|
9201
|
+
SET content = replace(
|
|
9202
|
+
content::text,
|
|
9203
|
+
$old$<img src='/images/nx-graph.webp' alt='Apercu du graphe Nx montrant les applications et librairies partagees' class='w-full h-auto rounded-2xl object-cover' />$old$,
|
|
9204
|
+
$new$<div class='relative aspect-video overflow-hidden rounded-2xl'><iframe class='absolute inset-0 h-full w-full border-0' src='https://www.youtube.com/embed/DNqU8ez9qjs?si=p2oIy0f-n7wiaBmO' title='Comment NextBlock™ fonctionne' allow='accelerated-motion; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share' referrerpolicy='strict-origin-when-cross-origin' loading='lazy' allowfullscreen></iframe></div>$new$
|
|
9205
|
+
)::jsonb
|
|
9206
|
+
WHERE content::text LIKE '%Apercu du graphe Nx montrant les applications et librairies partagees%';
|
|
9207
|
+
|
|
9208
|
+
|
|
9095
9209
|
-- Step D: Anchor preserved profiles
|
|
9096
9210
|
INSERT INTO public.profiles (id, updated_at, full_name, avatar_url, website, role)
|
|
9097
9211
|
SELECT preserved_user.id, NULL, NULL, NULL, NULL, 'ADMIN'
|
|
@@ -89,6 +89,13 @@ Variables, or your `.env`):
|
|
|
89
89
|
With that set, the dashboard conflict banner works on private forks too. (The workflow
|
|
90
90
|
itself still needs no extra secret — `GITHUB_TOKEN` covers it either way.)
|
|
91
91
|
|
|
92
|
+
> **⚠️ Vercel Hobby (free) plan + a private repo blocks auto-deploys.** On Hobby, Vercel only
|
|
93
|
+
> deploys **private**-repo commits authored by the project owner and rejects automated
|
|
94
|
+
> (bot/collaborator) commits — so the auto-merge push won't deploy (*"Hobby Plan does not
|
|
95
|
+
> support collaboration for private repositories"*). Either **make the repo public**
|
|
96
|
+
> (recommended — it also makes the conflict banner tokenless) or upgrade to **Vercel Pro**.
|
|
97
|
+
> Public repos have no such restriction on Hobby.
|
|
98
|
+
|
|
92
99
|
### How the dashboard stays current (no cron)
|
|
93
100
|
|
|
94
101
|
The CMS refreshes update/conflict status **in the background after a dashboard page
|
|
@@ -228,5 +228,15 @@ export const MIGRATIONS_BUNDLE: BundledMigration[] = [
|
|
|
228
228
|
"version": "00000000000042",
|
|
229
229
|
"name": "00000000000042_seed_deploy_to_vercel_ctas.sql",
|
|
230
230
|
"sql": "-- Promote the one-click \"Deploy to Vercel\" button as a CTA in the seeded homepage.\n--\n-- Two placements per language, both rendered through the normal 'button' block\n-- (ButtonBlockRenderer), so external URLs open in a new tab with rel=noopener:\n-- 1. Home HERO — replace the secondary \"View on GitHub\" / \"Voir sur GitHub\"\n-- outline button with a \"Deploy on Vercel\" / \"Déployer sur Vercel\" button\n-- (same variant/size/position; the primary \"Get Started\" button is untouched,\n-- and GitHub is still linked from the hero social row + the community section).\n-- 2. Home CLOSING CTA band (\"Have Questions?\" / \"Des questions ?\") — append a\n-- secondary (outline) \"Deploy on Vercel\" button after the contact button so\n-- the page also ends on the deploy action, styled to match the hero's Deploy\n-- button and keep the filled \"Get in Touch\" button as the band's primary.\n--\n-- The canonical deploy URL is the exact href from the README's Deploy button\n-- (native Supabase Marketplace `stores` flow). It is stored as a raw button `url`\n-- value (literal '&', not '&') because the renderer uses it directly as an href.\n--\n-- Forward-only and idempotent:\n-- * The hero swap matches the old button label, so a second run is a no-op\n-- (the label no longer exists) and it silently skips any install where the\n-- button was already customized or removed.\n-- * The closing-band append is guarded by NOT LIKE '%Deploy on Vercel%' /\n-- '%Déployer sur Vercel%', so it never appends twice.\n-- Scoping is by unique block text, so exactly the home hero / closing band match.\n\n-- ---------------------------------------------------------------------------\n-- 1a. EN home hero: \"View on GitHub\" -> \"Deploy on Vercel\"\n-- ---------------------------------------------------------------------------\nUPDATE public.blocks\nSET content = replace(\n replace(content::text, '\"View on GitHub\"', '\"Deploy on Vercel\"'),\n '\"https://github.com/nextblock-cms/nextblock\"',\n '\"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\"'\n )::jsonb\nWHERE content::text LIKE '%\"View on GitHub\"%';\n\n-- ---------------------------------------------------------------------------\n-- 1b. FR home hero: \"Voir sur GitHub\" -> \"Déployer sur Vercel\"\n-- ---------------------------------------------------------------------------\nUPDATE public.blocks\nSET content = replace(\n replace(content::text, '\"Voir sur GitHub\"', '\"Déployer sur Vercel\"'),\n '\"https://github.com/nextblock-cms/nextblock\"',\n '\"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\"'\n )::jsonb\nWHERE content::text LIKE '%\"Voir sur GitHub\"%';\n\n-- ---------------------------------------------------------------------------\n-- 2a. EN home closing band (\"Have Questions?\"): append a Deploy on Vercel button\n-- ---------------------------------------------------------------------------\nUPDATE public.blocks\nSET content = jsonb_set(\n content,\n '{column_blocks,0}',\n (content #> '{column_blocks,0}') ||\n '[{\"block_type\":\"button\",\"content\":{\"text\":\"Deploy on Vercel\",\"url\":\"https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fnextblock-cms%2Fnextblock&project-name=nextblock&repository-name=nextblock&stores=%5B%7B%22type%22%3A%22integration%22%2C%22integrationSlug%22%3A%22supabase%22%2C%22productSlug%22%3A%22supabase%22%7D%5D\",\"variant\":\"outline\",\"size\":\"lg\",\"position\":\"center\"}}]'::jsonb\n )\nWHERE content::text LIKE '%Have Questions?%'\n AND content::text NOT LIKE '%Deploy on Vercel%';\n\n-- ---------------------------------------------------------------------------\n-- 2b. FR home closing band (\"Des questions ?\"): append a Déployer sur Vercel button\n-- ---------------------------------------------------------------------------\nUPDATE public.blocks\nSET content = jsonb_set(\n content,\n '{column_blocks,0}',\n (content #> '{column_blocks,0}') ||\n '[{\"block_type\":\"button\",\"content\":{\"text\":\"Déployer sur Vercel\",\"url\":\"https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fnextblock-cms%2Fnextblock&project-name=nextblock&repository-name=nextblock&stores=%5B%7B%22type%22%3A%22integration%22%2C%22integrationSlug%22%3A%22supabase%22%2C%22productSlug%22%3A%22supabase%22%7D%5D\",\"variant\":\"outline\",\"size\":\"lg\",\"position\":\"center\"}}]'::jsonb\n )\nWHERE content::text LIKE '%Des questions ?%'\n AND content::text NOT LIKE '%Déployer sur Vercel%';\n"
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"version": "00000000000043",
|
|
234
|
+
"name": "00000000000043_swap_home_hero_media_to_youtube.sql",
|
|
235
|
+
"sql": "-- Swap the home HERO media from the static NBcover image to an embedded YouTube video.\n--\n-- The seeded home hero (migration 010) renders a \"Why teams switch / 100% Lighthouse\"\n-- card in its right column whose last element is an <img src=\"/images/NBcover.webp\" />.\n-- This replaces just that <img> with a responsive 16:9 YouTube <iframe>, keeping the\n-- surrounding card, its rounded/border/shadow wrapper, and every other block intact.\n--\n-- Rendering path: the hero right column is a 'text' block; TextBlockRenderer feeds the\n-- html_content through html-react-parser, which preserves <iframe> (it only strips on*\n-- handlers and swaps known CMS <img> for next/image). The proxy.ts CSP frame-src already\n-- allows https://www.youtube.com, so the embed is not blocked.\n--\n-- Forward-only and idempotent:\n-- * Each UPDATE matches the language-specific <img> alt text, so a second run finds no\n-- match and is a no-op (the alt text no longer exists once swapped).\n-- * String replace on content::text mirrors migration 042; the img markup is unique to\n-- the home hero, so exactly the EN and FR home hero blocks are touched.\n--\n-- The NBcover.webp media row is left untouched — it is still the feature image for the\n-- \"how-nextblock-works\" post; only the inline hero usage changes.\n\n-- ---------------------------------------------------------------------------\n-- 1. EN home hero: replace NBcover <img> with a YouTube <iframe>\n-- ---------------------------------------------------------------------------\nUPDATE public.blocks\nSET content = replace(\n content::text,\n '<img src=''/images/NBcover.webp'' alt=''Nextblock cover showcasing dashboards and blocks'' class=''w-full h-auto object-cover transform group-hover:scale-105 transition-transform duration-700'' fetchpriority=''high'' />',\n '<div class=''relative w-full aspect-video''><iframe class=''absolute inset-0 h-full w-full border-0'' src=''https://www.youtube.com/embed/71MyfoL4YVM?si=jtlDXV6cSC8rDgz0'' title=''NextBlock demo video'' allow=''accelerated-motion; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'' referrerpolicy=''strict-origin-when-cross-origin'' loading=''lazy'' allowfullscreen></iframe></div>'\n )::jsonb\nWHERE content::text LIKE '%Nextblock cover showcasing dashboards and blocks%';\n\n-- ---------------------------------------------------------------------------\n-- 2. FR home hero: replace NBcover <img> with a YouTube <iframe>\n-- ---------------------------------------------------------------------------\nUPDATE public.blocks\nSET content = replace(\n content::text,\n '<img src=''/images/NBcover.webp'' alt=''Couverture Nextblock'' class=''w-full h-auto object-cover transform group-hover:scale-105 transition-transform duration-700'' fetchpriority=''high'' />',\n '<div class=''relative w-full aspect-video''><iframe class=''absolute inset-0 h-full w-full border-0'' src=''https://www.youtube.com/embed/71MyfoL4YVM?si=jtlDXV6cSC8rDgz0'' title=''Vidéo de démonstration NextBlock'' allow=''accelerated-motion; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'' referrerpolicy=''strict-origin-when-cross-origin'' loading=''lazy'' allowfullscreen></iframe></div>'\n )::jsonb\nWHERE content::text LIKE '%Couverture Nextblock%';\n"
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"version": "00000000000044",
|
|
239
|
+
"name": "00000000000044_swap_article_nx_graph_for_youtube.sql",
|
|
240
|
+
"sql": "-- Swap the Nx-graph image in the \"How NextBlock™ Works\" article for an embedded\n-- YouTube video, and rebalance that two-column section to an even 50/50 split.\n--\n-- Targets the post-body 'text' block (dollar-quoted html_content seeded in migration\n-- 010) for both language variants of the same post:\n-- * EN slug how-nextblock-works (img alt \"Nx project graph preview ...\")\n-- * FR slug comment-nextblock-fonctionne (img alt \"Apercu du graphe Nx ...\")\n--\n-- Three forward-only, idempotent edits:\n-- 1. Column widths md:w-3/5 (text) and md:w-2/5 (media) -> md:w-1/2 each, and the\n-- flex row switches items-start -> items-center so the shorter media column sits\n-- centered against the taller text column. These class fragments occur only in\n-- this one section (EN + FR), so a single UPDATE rebalances both languages.\n-- 2/3. Replace the <img src=\"/images/nx-graph.webp\" ...> with a responsive 16:9\n-- YouTube <iframe>, kept inside the existing white aside card above its caption.\n--\n-- Rendering/CSP identical to migration 043: TextBlockRenderer -> html-react-parser\n-- preserves the <iframe>; proxy.ts CSP frame-src allows www.youtube.com; every utility\n-- class used here lives in this .sql file, which Tailwind's content scanner\n-- (libs/**/*.sql) compiles into the bundle. The nx-graph.webp media row is left intact.\n--\n-- Each UPDATE is guarded by a substring that only exists pre-swap, so a second run is a\n-- no-op. Dollar-quoted string literals ($old$/$new$) avoid escaping the single-quoted\n-- HTML attributes; the sandbox reset runs this via postgres db.unsafe() (no outer\n-- dollar-quote wrapper), same as migration 010's dollar-quoted seed content.\n\n-- ---------------------------------------------------------------------------\n-- 1. Both languages: 3/5 + 2/5 columns -> 50/50, and vertical-center the row\n-- ---------------------------------------------------------------------------\nUPDATE public.blocks\nSET content = replace(\n replace(\n replace(\n content::text,\n 'flex flex-col md:flex-row gap-8 items-start my-12',\n 'flex flex-col md:flex-row gap-8 items-center my-12'\n ),\n 'w-full md:w-3/5 space-y-4',\n 'w-full md:w-1/2 space-y-4'\n ),\n 'md:w-2/5 rounded-[2rem]',\n 'md:w-1/2 rounded-[2rem]'\n )::jsonb\nWHERE content::text LIKE '%w-full md:w-3/5 space-y-4%';\n\n-- ---------------------------------------------------------------------------\n-- 2. EN post body: nx-graph <img> -> responsive YouTube <iframe>\n-- ---------------------------------------------------------------------------\nUPDATE public.blocks\nSET content = replace(\n content::text,\n $old$<img src='/images/nx-graph.webp' alt='Nx project graph preview showing apps and shared libraries linked together' class='w-full h-auto rounded-2xl object-cover' />$old$,\n $new$<div class='relative aspect-video overflow-hidden rounded-2xl'><iframe class='absolute inset-0 h-full w-full border-0' src='https://www.youtube.com/embed/DNqU8ez9qjs?si=p2oIy0f-n7wiaBmO' title='How NextBlock™ Works' allow='accelerated-motion; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share' referrerpolicy='strict-origin-when-cross-origin' loading='lazy' allowfullscreen></iframe></div>$new$\n )::jsonb\nWHERE content::text LIKE '%Nx project graph preview showing apps and shared libraries linked together%';\n\n-- ---------------------------------------------------------------------------\n-- 3. FR post body: nx-graph <img> -> responsive YouTube <iframe>\n-- ---------------------------------------------------------------------------\nUPDATE public.blocks\nSET content = replace(\n content::text,\n $old$<img src='/images/nx-graph.webp' alt='Apercu du graphe Nx montrant les applications et librairies partagees' class='w-full h-auto rounded-2xl object-cover' />$old$,\n $new$<div class='relative aspect-video overflow-hidden rounded-2xl'><iframe class='absolute inset-0 h-full w-full border-0' src='https://www.youtube.com/embed/DNqU8ez9qjs?si=p2oIy0f-n7wiaBmO' title='Comment NextBlock™ fonctionne' allow='accelerated-motion; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share' referrerpolicy='strict-origin-when-cross-origin' loading='lazy' allowfullscreen></iframe></div>$new$\n )::jsonb\nWHERE content::text LIKE '%Apercu du graphe Nx montrant les applications et librairies partagees%';\n"
|
|
231
241
|
}
|
|
232
242
|
];
|