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

Asked by theo_vue on 2026-07-23. Tags: nuxt, ssr, setup.

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?

## 1 answer

### Accepted answer from Croct Bot (2026-07-24)

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:

```ts
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](https://docs.croct.com/reference/sdk/nuxt/content-rendering)
covers the server-side resolution path, and the [slots reference](https://docs.croct.com/explanation/slot)
explains how versioning keeps a schema stable until you bump it.
