# Our Strapi blog uses ISR, can I personalize one section without going fully dynamic?

Asked by ravi on 2026-01-14. Tags: strapi, nextjs, isr.

Strapi feeds a Next.js App Router blog, ISR with revalidate 300. Build
serves ~1200 posts, TTFB is great and I want to keep it that way.

Marketing wants a personalized CTA band on posts. I read that fetching Croct
content in a server component makes the route dynamic, which would throw away ISR
for the whole article.

Is there a pattern that keeps the article body static and personalizes just the
CTA band? What is the actual tradeoff, because going fully dynamic for one
section is not it

## 2 answers

### Accepted answer from Tobias Meier (2026-01-14)

Your reading is correct: `fetchContent` reads the request, so calling it in a
server component opts the route into dynamic rendering. Do not call it on
routes you want to keep static. There is a whole thread on that behavior:
[fetchContent forces dynamic rendering](/answers/nextjs-fetchcontent-forces-dynamic-rendering).

The underlying constraint is not Croct-specific. ISR serves the same HTML to
everyone, so any request-level personalization forces either dynamic rendering
or middleware rewrites.

The hybrid pattern for your case: keep the route static and render only the
CTA band with the client hook.

```tsx
'use client';

import {useContent} from '@croct/plug-react';

export function CtaBand() {
    const content = useContent('post-cta', {
        fallback: {title: 'Try it free', buttonLabel: 'Start now'},
    });

    return <Cta {...content} />;
}
```

The tradeoff you accept is that one section resolves on the client, so the fallback
renders first and the personalized version swaps in. The article body, layout,
and everything above the fold stay in the static HTML. For a below-the-fold CTA
band that swap is usually invisible; for a hero it would not be, and then you
would weigh dynamic rendering instead.

#### Reply from ravi (2026-01-14)

Band is below the fold, so the swap is acceptable. Shipping the hybrid.

### Answer from katien (2026-01-15)

Small addition: set a sensible fallback in `useContent` that matches your
Strapi default styling exactly. If the fallback and the personalized variant
share dimensions, the swap causes zero layout shift, which keeps CLS clean even
though the content resolves client side.
