Storyblok visual composer runs NextJS inside an IFrame. Due to this handling the cookie to enable preview mode is never set and the preview mode does not work for SSG handling.
Probably it would be a good idea if the preview mode could be enabled through URL params. The cookie solution might break other headless CMS systems as well
Alternatively I'd like to run my site in SSR mode on a specific domain. It feels like a hack because I would need to deploy every project twice for each mode.
+1! CraftCMS's preview mode is also using iFrames.
This is fixed by https://github.com/zeit/next.js/pull/11495 I guess?
From what I can see using Storyblok, this is still an issue @timneutkens after upgrading to latest canary build.
The 307 response has the set-cookie headers with SameSite set to lax

But unlike running in localhost outside of Storyblok, the actual nextjs response doesn't contain the cookies in its request headers.

@timneutkens on NextJS 9.3.4 its still an issue in Storyblok, I have the exact behaviour as @ChrisDalley pointed out. Currently I use a SSR page and share the logic between SSG and SSR to solve the issue
I tried with 9.3.6 the updated handling of the updated cms examples:
res.write(
`<!DOCTYPE html><html><head><meta http-equiv="Refresh" content="0; url=${currentSlug}" />
<script>window.location.href = '${currentSlug}'</script>
</head>`
)
res.end()
But the issue is still around, the previewData is getting lost. Did anybody got around this issue yet?
@dohomi - not yet, reverted back to using a separate server/routes for generating preview pages, though with Vercels new lambda # limits for hosting I would really like to get rid of them and onto the new preview functionality.
I am using a SSR route now but on local environment this does not work at all:
Error was not caught DOMException: Failed to read the 'localStorage' property from 'Window': Access is denied for this document.
This seems for me like a bug in the new version of NextJS (v. 9.4.x)
Just a heads up, If you're using Brave, make sure to turn off Brave Shield on storyblok.com. It will block the cookies required for preview mode.
I'm having the same issue with Storyblok. @timneutkens, is it possible to add sameSite option in res.setPreviewData?
next/next-server/server/api-utils.ts#L467
next/next-server/server/api-utils.ts#L476
It works fine when its property is empty (none), so it would be great to decide if someone wants to use lax by default.
I'm having the same issue with Storyblok. @timneutkens, is it possible to add
sameSiteoption inres.setPreviewData?
next/next-server/server/api-utils.ts#L467
next/next-server/server/api-utils.ts#L476
It works fine when its property is empty (none), so it would be great to decide if someone wants to uselaxby default.
btw here is a workaround:
const IS_PROD = process.env.NODE_ENV === "production";
const setCookieSameSite = (res, value) => {
const cookies = res.getHeader("Set-Cookie");
res.setHeader(
"Set-Cookie",
cookies?.map((cookie) =>
cookies.replace(
cookie,
"SameSite=Lax",
`SameSite=${value}; ${IS_PROD ? "Secure;" : ""}`
)
)
);
};
export const preview = async (req, res) => {
// ...
res.setPreviewData({});
setCookieSameSite(res, "None");
// ...
}
To use preview mode correctly on localhost, if you are using Chrome, disable Cookies without SameSite must be secure (chrome://flags/#cookies-without-same-site-must-be-secure) option.
btw here is a workaround:
const setCookieSameSite = (res, value) => { const cookies = res.getHeader('Set-Cookie'); res.setHeader('Set-Cookie', cookies?.map((cookie) => cookie.replace("SameSite=Lax", `SameSite=${value}`))) } export const preview = async (req, res) => { // ... res.setPreviewData({}); setCookieSameSite(res, "None"); // ... }
Unfortunately this doesn't work in the latest chrome, it complains that secure also needs to be set.
btw here is a workaround:
const setCookieSameSite = (res, value) => { const cookies = res.getHeader('Set-Cookie'); res.setHeader('Set-Cookie', cookies?.map((cookie) => cookie.replace("SameSite=Lax", `SameSite=${value}`))) } export const preview = async (req, res) => { // ... res.setPreviewData({}); setCookieSameSite(res, "None"); // ... }Unfortunately this doesn't work in the latest chrome, it complains that
securealso needs to be set.
Thanks. I updated the comment.
Most helpful comment
+1! CraftCMS's preview mode is also using iFrames.