Skip to content

Nt 3090 nextjs csr#262

Merged
Lotfi Anwar L Arif (Lotfi-Arif) merged 24 commits into
mainfrom
NT-3090-nextjs-csr
May 8, 2026
Merged

Nt 3090 nextjs csr#262
Lotfi Anwar L Arif (Lotfi-Arif) merged 24 commits into
mainfrom
NT-3090-nextjs-csr

Conversation

@Lotfi-Arif
Copy link
Copy Markdown
Contributor

@Lotfi-Arif Lotfi Anwar L Arif (Lotfi-Arif) commented May 6, 2026

Hybrid SSR + CSR Takeover personalization pattern for Next.js App Router. First paint is server-resolved via the Node SDK (zero flicker, personalized HTML in the initial response). After hydration, the React Web SDK takes over for entry resolution; identify, consent, and reset re-resolve variants immediately without a server roundtrip. Subsequent navigations via are SPA-style, with entries fetched and resolved client-side. The cookie ctfl-opt-aid bridges identity between server and client. Known gap: OptimizationRoot cannot accept pre-fetched server data, so the Web SDK makes a redundant Experience API call on hydration before client-side reactivity activates.

Use the layout-level OptimizationRoot and prime it with server-resolved defaults (profile, selectedOptimizations, changes) from a shared request-scoped getOptimizationData() helper. This keeps the Web SDK stable across navigations, avoids provider remounts, and gives the client the same optimization state the server used for first paint, making the SSR→CSR takeover seamless

Note: The root implementation:lint script runs ESLint 10 (installed at the repo root) against all implementations/ code. When it hits the Next.js implementation, ESLint 10 resolves eslint-plugin-react@7.37.5 from that implementation's node_modules. That plugin version uses context.getFilename(), an API removed in ESLint 10, causing a TypeError that crashes the entire lint run.

vercel/next.js#89764

Restructure the bare create-next-app scaffold into a proper monorepo
implementation with both React Web SDK and Node SDK dependencies,
PM2-managed mock/serve scripts, env config, and AGENTS.md aligned
with existing implementation patterns.
Replace the useState/useEffect mount guard with a dedicated
ClientProviderWrapper that uses next/dynamic({ ssr: false }). This is
the standard Next.js pattern for browser-only third-party SDKs and
keeps OptimizationProvider clean without SSR workarounds.
- Add Node SDK server singleton and Next.js middleware for cookie
  lifecycle (ctfl-opt-aid profile management).
- Add server-resolved page: Server Component fetches entries and
  resolves them via Node SDK, renders pure server HTML with zero
  client JS for content.
- Add InteractiveControls as a small 'use client' component for
  consent/identify on the server-resolved route.
- Isolate SDK setup per route: each route has its own layout with
  its own ClientProviderWrapper, root layout is neutral.
- Remove custom OptimizationProvider wrapper; use SDK's
  OptimizationRoot directly via dynamic import.
Document isolated route layouts, server-resolved vs client-resolved
patterns, design decisions, cookie-based profile management, and the
singleton dev-mode recovery tip.
… direction

Add context on why this reference implementation exists, the known
singleton conflict when navigating between routes, and plans to
gather customer architecture patterns from pre/post-sales to inform
which setups to prioritize.
Remove server-resolved route, middleware, Node SDK dependency, and
all server-side resolution code. This implementation now uses only
@contentful/optimization-react-web for pure client-side entry
resolution. The SSR hybrid pattern lives in a separate
react-web-sdk+node-sdk_nextjs implementation.
Superseded by the actual reference implementations.
The root ESLint (v10) is incompatible with eslint-plugin-react pulled
by eslint-config-next. The Next.js implementations have their own
local eslint.config.mjs and are linted via their own setup.
Convert from pure CSR to hybrid pattern: Server Component first paint
via Node SDK, Client Component interactive page via useOptimization().
Add middleware for cookie lifecycle, Node SDK singleton, and Link-based
SPA navigation between SSR and CSR routes.
Pass server-resolved profile, selectedOptimizations, and changes into
OptimizationRoot via defaults prop. Eliminates the state gap between
SSR first paint and client takeover. Provider moved to page level to
receive server data as props.
Prime the layout-level OptimizationRoot from shared request-scoped
optimization data so SSR and CSR takeover use the same evaluated state.
This keeps the provider stable across navigations while preserving a
seamless first-paint handoff.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks great!! If you're happy with it too, 🚢 👍🏻

@Lotfi-Arif Lotfi Anwar L Arif (Lotfi-Arif) merged commit ae295da into main May 8, 2026
31 checks passed
@Lotfi-Arif Lotfi Anwar L Arif (Lotfi-Arif) deleted the NT-3090-nextjs-csr branch May 8, 2026 14:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants