All questions

Where do I call fetchContent for a Storyblok-mapped slot in the App Router?

Asked by Priya Anand on

PAPriya Anand

App Router site rendering Storyblok stories, and I have mapped a hero block to a Croct slot. I want the personalized content to arrive server-rendered so there is no flash of the default block on first paint.

Where should I actually call the fetch so I get that behaviour? I would rather resolve it on the server than hydrate and swap, but I am not sure which layer this belongs in.

Was this helpful?

2 answers

Ddevon_leeAccepted answer

Do it in the server component that renders the block, with fetchContent from @croct/plug-next/server. Pass the Storyblok block content as the fallback and the context with your attributes:

import {fetchContent} from '@croct/plug-next/server';
export default async function Hero({storyblokBlock}) {    const {content} = await fetchContent('home-hero@1', {        fallback: storyblokBlock,        context: {            attributes: {                // whatever you use for targeting            },        },    });
    return <HeroView {...content} />;}

Because it resolves on the server, the HTML that reaches the browser already has the right variant, so it stays SEO-visible and there is nothing to swap client-side. One thing I would do is pin the slot version like home-hero@1 so preview matches production instead of drifting to latest. More background in serving Storyblok blocks without the flash.

Was this helpful?
PAPriya Anand

That worked, first paint is already the variant. Pinning the version also fixed a preview mismatch I had not connected to this. Thank you.

Ssam_okoro

Just flag the trade-off before you sprinkle it everywhere: fetchContent reads the request, so any route that calls it opts into dynamic rendering. That is fine for a personalized homepage, but do not put it on routes you need to keep static. The details are in how fetchContent forces dynamic rendering.

Was this helpful?
Still have questions?