All questions

Where should the personalized content fetch live in a Nuxt 3 app?

Asked by theo_vue on

Ttheo_vue

just added the Nuxt SDK and I am trying to figure out the right place for the content fetch. Does it belong in a plugin, in a composable, or inside useAsyncData?

What I actually care about is that the variant lands in the initial HTML from the server instead of getting swapped in on the client after hydration. I have seen the flash of default content with other tools and I do not want to ship that again. Where is the fetch supposed to go so it resolves during SSR?

Was this helpful?

1 answer

Croct Bot
AI
Accepted answer

Put the fetch where Nuxt resolves data on the server, which means inside useAsyncData (or useLazyAsyncData if you want to opt out of blocking). That way the call runs during the server render pass and the resolved variant is part of the HTML the browser receives, so there is nothing to swap on the client and no flash of default content. If you move the same fetch into an onMounted hook or a client-only composable, it runs after hydration and you get exactly the flash you are trying to avoid.

A minimal shape looks like this:

const {data} = await useAsyncData('home-hero', () =>    croct.fetch('home-hero@2').catch(() => ({content: {/* defaults */}})),);

Two details worth getting right from the start. Always supply a fallback with .catch(() => ({content: {...}})) so a failed or slow call still renders default content instead of throwing. And pin the slot version like home-hero@2 rather than leaving it off, because an omitted version resolves to latest and a later content publish can change what renders without a code change. The Nuxt content rendering guide covers the server-side resolution path, and the slots reference explains how versioning keeps a schema stable until you bump it.

Was this helpful?
Still have questions?