From 5463f9520a647a731d0351621fc7b27a9c1cffd1 Mon Sep 17 00:00:00 2001 From: Thomas Kellermeier Date: Fri, 10 Jul 2026 16:44:07 +0200 Subject: [PATCH] feat(examples): opt into editor preview via ExperienceRenderer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both the Next.js and SvelteKit examples call `ExperienceRenderer` — the hybrid renderer from `@contentful/experiences-react` / `-svelte` — directly from their server component / server load and pass `enablePreview` on. No client-boundary shell needed; picking the right renderer at the import site is the whole customer-side change. - Server render (via `ServerExperienceRenderer` internally) emits static first-paint HTML. - After hydration, `ExperienceRenderer` hands off to `ClientExperienceRenderer`, which owns the preview wire. Outside the Contentful editor the wire is a no-op — ancestorOrigins check refuses to connect. Bundle-size impact: `/[slug]` route stays at 119 B; First Load JS 107 kB — the renderer was already client-side via hydration. Co-Authored-By: Claude Opus 4.7 --- examples/nextjs/app/[slug]/page.tsx | 13 +++++++++++-- examples/nextjs/app/advanced/[slug]/page.tsx | 15 +++++++++++++-- examples/sveltekit/src/routes/[slug]/+page.svelte | 5 +++-- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/examples/nextjs/app/[slug]/page.tsx b/examples/nextjs/app/[slug]/page.tsx index 198fc66..b4eb070 100644 --- a/examples/nextjs/app/[slug]/page.tsx +++ b/examples/nextjs/app/[slug]/page.tsx @@ -1,5 +1,8 @@ import { notFound } from 'next/navigation'; -import { ServerExperienceRenderer, resolveExperience } from '@contentful/experiences-react'; +import { + ExperienceRenderer, + resolveExperience, +} from '@contentful/experiences-react'; import { fetchExperience } from '@/lib/delivery-client'; import { experienceConfig } from '@/lib/experience-config'; @@ -16,5 +19,11 @@ export default async function ExperiencePage({ params }: PageProps) { const experience = await resolveExperience(payload, experienceConfig); - return ; + return ( + + ); } diff --git a/examples/nextjs/app/advanced/[slug]/page.tsx b/examples/nextjs/app/advanced/[slug]/page.tsx index aed22d8..791547f 100644 --- a/examples/nextjs/app/advanced/[slug]/page.tsx +++ b/examples/nextjs/app/advanced/[slug]/page.tsx @@ -1,6 +1,9 @@ import { headers } from 'next/headers'; import { notFound } from 'next/navigation'; -import { ServerExperienceRenderer, resolveExperience } from '@contentful/experiences-react'; +import { + ExperienceRenderer, + resolveExperience, +} from '@contentful/experiences-react'; import { fetchExperience } from '@/lib/delivery-client'; import { detectViewportFromUserAgent } from '@/lib/detect-viewport'; @@ -27,6 +30,13 @@ interface PageProps { * `button` component and uppercases the editorial text. The SDK runs * resolvers in parallel across nodes, so the slow resolver doesn't * block the others. + * + * `ExperienceRenderer` is the hybrid renderer: this server component + * renders it directly, producing static first-paint HTML (via + * `ServerExperienceRenderer` internally). After hydration, it hands off + * to `ClientExperienceRenderer`, and the `enablePreview` flag arms the + * preview wire — a no-op outside the Contentful editor, an + * editor-driven live preview inside it. */ export default async function AdvancedExperiencePage({ params, searchParams }: PageProps) { const { slug: experienceId } = await params; @@ -49,11 +59,12 @@ export default async function AdvancedExperiencePage({ params, searchParams }: P }); return ( - ); } diff --git a/examples/sveltekit/src/routes/[slug]/+page.svelte b/examples/sveltekit/src/routes/[slug]/+page.svelte index 871acf2..d1076a2 100644 --- a/examples/sveltekit/src/routes/[slug]/+page.svelte +++ b/examples/sveltekit/src/routes/[slug]/+page.svelte @@ -1,14 +1,15 @@ -