Docs

This page isn't translated yet

next

Provider and listeners in Next.js

SysthemaProvider in the App Router, why the listeners need next/navigation, and cookie consent.

On this page

The @systhemaui/next SysthemaProvider is the recommended way to set up Systhema in a Next app. It bundles:

  1. SysthemaConfigServer (from @systhemaui/react) — server-side configuration.
  2. AosListener (Next version with usePathname()).
  3. ScrollClassesListener (Next version with usePathname()).
  4. ParallaxListener (Next version with usePathname()).
  5. CookieConsentBanner (when a non-null cookieConsent config is passed).

For the props and the React provider, see SysthemaProvider.

UsageLink to this section

app/layout.tsx
import { SysthemaProvider } from '@systhemaui/next'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <SysthemaProvider>{children}</SysthemaProvider>
      </body>
    </html>
  )
}

With cookie consent enabled — getSysthemaCookieConsentConfig() returns null when the feature is disabled, so the banner stays out of the tree at zero runtime cost:

app/layout.tsx
import { SysthemaProvider, getSysthemaCookieConsentConfig } from '@systhemaui/next'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  const cookieConsent = getSysthemaCookieConsentConfig()
  return (
    <html lang="en">
      <body data-theme="default">
        <SysthemaProvider cookieConsent={cookieConsent}>{children}</SysthemaProvider>
      </body>
    </html>
  )
}

For Payload-based projects, the <RootLayout> from @systhemaui/payload/next resolves the cookie consent config from the general-settings global server-side and forwards it through <SysthemaProvider> automatically — see Rendering pages and Cookie consent.

Existing Next projects upgrading via systhema upgrade get this wired automatically by the add-cookie-consent-to-next-layout codemod (Next-only) or add-payload-instance-to-root-layout codemod (Payload).

Mounting the parts manuallyLink to this section

If you prefer fine-grained control, render the parts manually:

app/layout.tsx
import { SysthemaConfigServer } from '@systhemaui/react'
import { AosListener, ParallaxListener, ScrollClassesListener } from '@systhemaui/next'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <SysthemaConfigServer />
        <AosListener />
        <ParallaxListener />
        <ScrollClassesListener />
        {children}
      </body>
    </html>
  )
}

But SysthemaProvider is the recommended path.

Why the listeners need next/navigationLink to this section

Standard JS event listeners work in multi-page apps:

window.addEventListener('load', initializeAnimations)
document.addEventListener('DOMContentLoaded', initializeAnimations)

But with next/link:

  1. The browser doesn't fire load or DOMContentLoaded on navigation.
  2. The page content changes, but the listeners aren't notified.
  3. Animations, parallax, and scroll classes don't re-initialise.

The fix:

import { usePathname } from 'next/navigation'
import { useEffect } from 'react'

const MyListener = () => {
  const pathname = usePathname()

  useEffect(() => {
    initializeAnimations()
  }, [pathname])

  return null
}

That's exactly how each Next listener in this package is implemented. See Listeners for each one.