Repository navigation
Description
Package
@storyblok/nuxt
Bug Description
On a static Nuxt website (built with nuxt generate), on a prerendered page opened in the Visual Editor live edits never reach the page. Preview stays on the published content
Some digging revealed that after updating Nuxt to 4.5, hydration behavior seem to be different: a prerendered page is treated differently when the URL has a query string. The router first hydrates on payload.path (the bare path, e.g. /about/) with replaceState, and restores the real URL only on app:suspense:resolve.
useAsyncStoryblok registers the bridge during setup, that does not seem to be the correct time during lifecycle anymore
Steps to Reproduce
nuxt generateany page that usesuseAsyncStoryblokwith the bridge enabled.- Serve the output statically and open it in the Visual Editor, or in any iframe with
?_storyblok=<story id>&_storyblok_tk[...]and a posted{ action: 'input', story }message. - The edited story is never applied. Logging inside the watch shows
location.search === ''whenuseStoryblokBridgeis called.
Environment
System:
OS: Linux 7.2 openSUSE Tumbleweed 20260921
CPU: (32) x64 AMD Ryzen 9 7945HX with Radeon Graphics
Memory: 15.40 GB / 30.52 GB
Container: Yes
Shell: 5.3.15 - /bin/bash
Binaries:
Node: 24.21.0 - /home/stefano/.nvm/versions/node/v24.21.0/bin/node
npm: 11.19.0 - /home/stefano/.nvm/versions/node/v24.21.0/bin/npm
pnpm: 12.5.1 - /home/stefano/.nvm/versions/node/v24.21.0/bin/pnpm
Deno: 2.9.0 - /usr/bin/deno
Browsers:
Brave Browser: 153.1.95.104
Chrome: 154.0.8037.57
Chromium: 153.0.8010.52
Firefox: 156.0
Firefox Developer Edition: 156.0
npmPackages:
@storyblok/nuxt: ^11.2.1 => 11.2.0
@storyblok/schema: ^0.4.2 => 0.4.2
nuxt: ^4.5.2 => 4.5.2
storyblok: 4.23.0 => 4.22.4Additional Context
I managed to fix this locally with a workaround.
This what I was using before
const { story } = await useAsyncStoryblok(slug, {
api: {
version,
resolve_relations: [...RESOLVE_RELATIONS],
},
bridge: { resolveRelations: [...RESOLVE_RELATIONS] },
})and this is the workaround
const { data, story } = await useAsyncStoryblok(slug, {
api: {
version,
resolve_relations: [...RESOLVE_RELATIONS],
},
bridge: false,
})
onNuxtReady(() => {
if (!story.value?.id) {
return
}
useStoryblokBridge(story.value.id, (editedStory) => {
if (data.value) {
data.value = { ...data.value, data: { ...data.value.data, story: editedStory } }
}
}, {
// The same relation list, or references resolve on the live site but come
// back as bare uuids inside the Visual Editor
resolveRelations: [...RESOLVE_RELATIONS],
})
})While this is working, I would expect the Storyblok module to manage this internally and set its functions during the correct lifecycle time.
Activity