All questions

Wiring up Next.js + Sanity + Croct, what goes where?

Asked by Kofi Mensah on

KMKofi Mensah

Fullstack dev, App Router project with Sanity as the CMS. What I have done so far:

  • installed @croct/plug-next
  • added the provider in the root layout
  • my Sanity fetches happen in server components as usual

Where I am stuck is the fetch strategy for personalized content. Do I fetch the slot content in the same server components next to my Sanity queries, or am I supposed to use the client hooks? The docs mention both and I am not sure which one is the intended default for this kind of setup.

Was this helpful?

1 answer

MPMarcos PassosAccepted answer

Server components are the intended default for your setup. Fetch the slot content right next to your Sanity queries with fetchContent from the server entry point:

import {fetchContent} from '@croct/plug-next/server';
export default async function HomePage() {    const {content} = await fetchContent('home-hero');
    return <Hero title={content.title} />;}

Server mode means the personalized content is in the HTML on first paint, so there is no flicker and it is visible to search engines. The client hooks work too, but they swap content in after the page loads, so keep them for cases where the page must stay static.

Two things to check in your environment:

  1. Set both NEXT_PUBLIC_CROCT_APP_ID and CROCT_API_KEY. The API key must have the "Issue user tokens" permission, that is the most common reason server-side auth fails.
  2. Be aware that fetchContent reads the request, which opts the route into dynamic rendering. Only call it on routes you are fine rendering per request.
Was this helpful?
KMKofi Mensah

Working now, the missing piece was the "Issue user tokens" permission on my key. One follow-up: for a marketing page we want to keep static, is the client hook the only option?

MPMarcos Passos

Yes, on a route that must stay static, fetch with the client hooks after load and provide fallback content so the default renders in the meantime. Anything fetched with fetchContent makes the route dynamic.

Still have questions?