# Best practice for choosing server-side vs client-side content rendering?

Asked by Paige Sutton on 2025-03-25. Tags: ssr, dx, nextjs, react.

I am standardizing a Next.js starter template for our agency and want to
settle on a sensible default before we roll it out across client projects.
Croct offers both `fetchContent` in server components and `useContent` in
client components, and I would like to understand the concrete tradeoffs of
each rather than picking one by habit.

Specifically: what does each choice cost in terms of rendering behavior,
caching, and user experience? Is there a rule of thumb for when a slot
belongs on the server versus the client?

## 2 answers

### Answer from tk_ellis (2025-03-25)

The tradeoff is rendering mode versus flicker.

Server mode, `fetchContent` from `@croct/plug-next/server`, gives you no
flicker and SEO-visible content: the HTML arrives already personalized.
The cost is that it reads the request, which opts the route into dynamic
rendering. That is the big one for a starter template. If a route is
meant to stay static, do not call `fetchContent` on it, because you will
silently lose static generation for that page.

Client mode, `useContent` in a `'use client'` component, keeps the page
static, but the content swaps in after load, which means flicker on the
personalized slots. `useContent` relies on React Suspense, so wrap the
component in a Suspense boundary with a sensible fallback, ideally
something the same size as the final content to avoid layout shift.

My rule of thumb: above-the-fold and SEO-relevant slots go server-side
and accept dynamic rendering; personalized widgets on otherwise static
marketing pages go client-side.

### Answer from Amina Diallo (2025-03-26)

One gotcha to bake into your template docs since your devs will move
between both modes: the options shape differs. On the Next server side,
evaluation attributes go under `context`, as in
`fetchContent('home-hero', {context: {attributes: {...}}})`, while the
React hooks take `attributes` at the top level. Easy to get wrong when
copy-pasting a slot from a server component into a client one, and the
failure is silent because the attributes just do not apply.
