Optimization

April 14, 2026

Use this guide when you care about banner visibility speed, route static-ness, and reducing backend round-trip cost.

Start Here

Apply the optimizations in this order:

SituationUseWhy
Any production Next.js appSame-origin /api/c15t rewriteLowers browser startup overhead and keeps the backend origin out of client config
Static route, but banner speed mattersC15tPrefetchStarts /init before hydration without making the route dynamic
Dynamic route, or you want the fastest first bannerfetchInitialData()Starts /init on the server and streams the result into the provider
You want the simplest setupClient-only initNo extra moving parts, but the banner appears later on cold loads

Info

C15tPrefetch is the only static-route prefetch step you need in @c15t/nextjs. Matching prefetched data is consumed automatically during first initialization.

Info

Prefetched or SSR data is reused only when the request context still matches at runtime. That includes the backend URL, credentials, overrides, and the browser's ambient GPC signal.

In production benchmarks with a same-origin rewrite, prefetching strategies show measurable improvement over client-only init:

StrategyScripts loadedData request startsBanner visible
Client-only (no prefetch)baselinebaselinebaseline
Browser prefetch~1.3x faster~2.6x earlier~1.25x faster
Server prefetch~2x fasterbefore page loads~1.9x faster

1) Prefer Same-Origin Rewrites

Proxy c15t requests through your Next.js app so the browser calls your own origin instead of a third-party domain.

Then use:

Why this helps:

  • Same-origin requests avoid extra DNS/TLS setup in many deployments
  • Ad blockers are less likely to block your init endpoint
  • You can change backend infrastructure without touching client code

Info

Set NEXT_PUBLIC_C15T_URL in .env to your backend URL, for example https://your-project.inth.app.

Info

Use rewrites for browser-side calls (ConsentManagerProvider, C15tPrefetch). For server-side fetchInitialData(), prefer a direct backend URL (for example https://your-project.inth.app) to avoid an extra server proxy hop.

2) Choose A Startup Strategy

Start with a same-origin rewrite and the default client-side provider. Add one of the preloading strategies below only when the route behavior or performance target calls for it.

Client-Only Init

Keep the default provider setup when you want the least complexity. This works on both static and dynamic routes, but the banner only appears after the client runtime starts and the initial /init request completes.

Dynamic Routes: Fetch On The Server And Stream

Use fetchInitialData() when the route is already dynamic, or when you are willing to make it dynamic in exchange for the fastest first banner.

Because it depends on next/headers, this opts the route into dynamic rendering.

Info

Do not await fetchInitialData(). Pass the unresolved Promise to the provider so Next.js can stream the route while /init runs in parallel.

Info

For fetchInitialData(), prefer a direct backend URL such as https://your-project.inth.app instead of a rewrite to avoid an extra server-side proxy hop. See Server-Side Data Fetching for the full flow.

Static Routes: Start Fetch Early In The Browser

Use C15tPrefetch when the route needs to stay static but you still want the /init request to start before hydration. Matching prefetched data is consumed automatically by the runtime during first store initialization.

Info

C15tPrefetch uses Next.js beforeInteractive script loading, so the /init request can start before hydration.

Info

If the request context changes between prefetch time and runtime, c15t falls back to a normal client /init. A common example is overrides.gpc conflicting with the browser's ambient GPC signal.

Keep The Provider Mounted Across Navigation

Mount the consent provider at the app root so route transitions do not remount it.

Why this helps:

  • Avoids re-running init work on client-side navigation
  • Prevents extra callback churn from remount cycles
  • Keeps banner/dialog state stable between route transitions

Animation Performance

The default motion tokens are tuned for speed-first product UI:

TokenDurationUsed for
fast80msBanner slide + overlay, card scale, button hover, widget entry/exit
normal150msAccordion, switch toggle
slow200msDialog trigger snap, tab indicator

These defaults follow the principle that product UI should be fast and purposeful — animations exist for spatial continuity, not decoration. In benchmarks, animation duration contributes a constant floor to "data fetched → banner visible" timing. The default tokens sit at the lower end of standard UI ranges (80-200ms) to minimize that floor.

To customize motion durations and easing, see Styling.

Reduce Network Overhead

If you must use a cross-origin backend URL, add preconnect so the browser starts DNS/TLS early: