Disclaimer: This bug report was produced after an extended debugging session assisted by Claude (Anthropic's AI). Given the depth of context accumulated throughout the investigation, Claude was able to synthesize these findings and identify the patterns described above. I personally lack the expertise to confirm with certainty whether this is a genuine bug on Prismic's side or a misuse of the tool on my part. Having exhausted all the leads I could think of, I'm turning to the community for guidance. Any feedback — including "you're doing it wrong" — is genuinely welcome.
Bug Report: Page Builder Live Preview Fails After Multiple Edits
Summary
The Prismic Page Builder live preview fails after a series of content modifications. The issue manifests as an unexpected iframe refresh followed by a React hydration error.
Important discovery: The bug occurs on BOTH localhost AND Vercel deployments, but it takes significantly longer to appear on localhost (many more edits required). On Vercel, it happens much faster (after just a few edits).
CRITICAL: This bug has been reproduced on a minimal Next.js + Prismic project with:
- No
"use client" components
- No animations (Framer Motion, etc.)
- No complex slices
- Just the basic Prismic starter template deployed to Vercel
Environment
- Framework: Next.js 16.1.6 (App Router with Turbopack)
- Prismic packages:
@prismicio/next: 2.2.1
@prismicio/react: 3.4.0
@slicemachine/adapter-next: 0.3.95
- Hosting: Vercel (both staging and production environments tested)
- Browser: Chrome (latest), tested in incognito mode as well
Steps to Reproduce
- Deploy a Next.js App Router project with Prismic to Vercel
- Open Prismic Page Builder
- Select a slice to preview
- The slice renders correctly initially
- Make a content modification (e.g., change text)
- After a few modifications, the iframe "refreshes" (visible flash)
- The next modification after the refresh causes a React error
- Must exit and re-enter the Page Builder to recover
Expected Behavior
- Live preview should update smoothly without iframe refresh
- Content modifications should never cause React errors
- Behavior should be identical between localhost and Vercel
Actual Behavior
- On localhost: Bug eventually appears after many edits (takes longer to manifest)
- On Vercel: Bug appears much faster, after just a few edits
This suggests the bug is time/usage-based and that Vercel's environment (latency, caching) accelerates its occurrence.
Error Details
Minified React error #418
https://reactjs.org/docs/error-decoder.html?invariant=418
This error indicates a hydration mismatch between server and client rendering.
Investigation Findings
1. The Refresh is the Root Cause
The problem is NOT primarily the hydration error - it's the unexpected iframe refresh that shouldn't happen. The hydration error is a consequence of this refresh.
2. Identified Problematic Code Pattern
In @slicemachine/adapter-next/src/simulator/react-server/SliceSimulator.tsx:
// This code runs during render, not in useEffect
const state =
typeof window !== "undefined"
? new URL(window.location.href).searchParams.get(STATE_PARAMS_KEY)
: undefined;
const hasSlices = getSlices(state).length > 0;
The typeof window !== "undefined" check during render (not in useEffect) is a React anti-pattern that causes hydration mismatches. On the server, window is undefined, so state is undefined. On the client, state has a value.
3. router.refresh() Behavior Differs
The SliceSimulator uses router.refresh() to update the preview:
simulatorManager.state.on(StateEventType.Slices, (newSlices) => {
// ... URL update logic
setTimeout(() => router.refresh(), 0);
});
This router.refresh() behaves differently on Vercel vs localhost due to Next.js caching differences in production.
4. Localhost vs Vercel Differences
| Aspect |
Localhost |
Vercel |
| router.refresh() |
Soft refresh |
Can cause full page refresh |
| React mode |
Development (verbose errors) |
Production (minified) |
| Caching |
Minimal |
Aggressive (Router Cache) |
| Hydration tolerance |
More lenient |
Strict |
Attempted Fixes (All Failed)
- Stable React keys - Changed index-based keys to stable keys in all slices
- useMotionValue reset - Added reset mechanism in animation components
- Route Groups isolation - Isolated slice-simulator with its own layout
- VERCEL_FORCE_NO_BUILD_CACHE=1 - Disabled Vercel build cache
- Dynamic import with ssr: false - Loaded SliceZone only on client
- staleTimes configuration - Extended Router Cache duration
- revalidate = 0 + force-dynamic - Forced dynamic rendering
- CSP + X-Frame-Options headers - Configured iframe permissions
Hypothesis
Updated hypothesis based on the discovery that the bug also occurs on localhost (just slower):
The issue appears to be a state accumulation/degradation problem in the SliceSimulator or SimulatorManager:
- Event listener accumulation - The
simulatorManager.state.on() listeners may be stacking up without proper cleanup
- Memory leak - State or references accumulating over time
- Corrupted singleton state - The SimulatorManager singleton may be getting into a bad state after repeated
router.refresh() calls
The fact that Vercel accelerates the bug suggests that network latency or caching behavior triggers the problematic code path more frequently.
Original hypothesis (still relevant):
typeof window !== "undefined" check during render causes hydration mismatch
router.refresh() behavior differs between dev and prod
Requested Action
- Investigate event listener cleanup - Check if
simulatorManager.state.on() listeners are properly removed on component unmount
- Review SimulatorManager singleton - Check for memory leaks or state corruption over time
- Review the
typeof window !== "undefined" pattern in SliceSimulator - this should be moved to a useEffect or handled differently
- Investigate why
router.refresh() causes full page refresh instead of soft refresh
- Consider providing a pure Client Component alternative for the SliceSimulator that doesn't rely on Server Component rendering
Workaround Needed
Currently, there is no known workaround. The Page Builder is effectively unusable on Vercel deployments for this project.
Additional Context
- Bug reproduced on minimal project - No Framer Motion, no useClient, no complex code
- All slices fail eventually, not just specific ones
- The issue is 100% reproducible on both Vercel AND localhost
- On Vercel: Fails after ~3-10 content modifications
- On localhost: Fails after many more modifications (takes longer to appear)
- Refreshing the Page Builder temporarily fixes it, but the problem returns
- Tested on multiple browsers (Chrome, incognito mode)
Disclaimer: This bug report was produced after an extended debugging session assisted by Claude (Anthropic's AI). Given the depth of context accumulated throughout the investigation, Claude was able to synthesize these findings and identify the patterns described above. I personally lack the expertise to confirm with certainty whether this is a genuine bug on Prismic's side or a misuse of the tool on my part. Having exhausted all the leads I could think of, I'm turning to the community for guidance. Any feedback — including "you're doing it wrong" — is genuinely welcome.
Bug Report: Page Builder Live Preview Fails After Multiple Edits
Summary
The Prismic Page Builder live preview fails after a series of content modifications. The issue manifests as an unexpected iframe refresh followed by a React hydration error.
Important discovery: The bug occurs on BOTH localhost AND Vercel deployments, but it takes significantly longer to appear on localhost (many more edits required). On Vercel, it happens much faster (after just a few edits).
CRITICAL: This bug has been reproduced on a minimal Next.js + Prismic project with:
"use client"componentsEnvironment
@prismicio/next: 2.2.1@prismicio/react: 3.4.0@slicemachine/adapter-next: 0.3.95Steps to Reproduce
Expected Behavior
Actual Behavior
This suggests the bug is time/usage-based and that Vercel's environment (latency, caching) accelerates its occurrence.
Error Details
Investigation Findings
1. The Refresh is the Root Cause
The problem is NOT primarily the hydration error - it's the unexpected iframe refresh that shouldn't happen. The hydration error is a consequence of this refresh.
2. Identified Problematic Code Pattern
In
@slicemachine/adapter-next/src/simulator/react-server/SliceSimulator.tsx:The
typeof window !== "undefined"check during render (not in useEffect) is a React anti-pattern that causes hydration mismatches. On the server,windowis undefined, sostateisundefined. On the client,statehas a value.3. router.refresh() Behavior Differs
The SliceSimulator uses
router.refresh()to update the preview:This
router.refresh()behaves differently on Vercel vs localhost due to Next.js caching differences in production.4. Localhost vs Vercel Differences
Attempted Fixes (All Failed)
Hypothesis
Updated hypothesis based on the discovery that the bug also occurs on localhost (just slower):
The issue appears to be a state accumulation/degradation problem in the SliceSimulator or SimulatorManager:
simulatorManager.state.on()listeners may be stacking up without proper cleanuprouter.refresh()callsThe fact that Vercel accelerates the bug suggests that network latency or caching behavior triggers the problematic code path more frequently.
Original hypothesis (still relevant):
typeof window !== "undefined"check during render causes hydration mismatchrouter.refresh()behavior differs between dev and prodRequested Action
simulatorManager.state.on()listeners are properly removed on component unmounttypeof window !== "undefined"pattern in SliceSimulator - this should be moved to a useEffect or handled differentlyrouter.refresh()causes full page refresh instead of soft refreshWorkaround Needed
Currently, there is no known workaround. The Page Builder is effectively unusable on Vercel deployments for this project.
Additional Context