Skip to main content

Next.js Components

ConsentRoot

Mount one root

ConsentRoot wraps the React ConsentProvider and connects it to c15t.config.ts and the server-resolved state. Mount it once; it already supplies the provider used by consent components and hooks.

Follow the quickstart, App Router or Pages Router for the complete setup. Keep ConsentRoot mounted across navigation.

Render ConsentRoot straight from a Server Component layout, or from pages/_app.tsx. c15t/next gives Server Components a client reference to it, and ConsentRoot reads c15t.config.ts itself, so the layout passes only state. The state from resolveConsent, or its promise, is plain data and can cross from the server to the browser. withConsentManifest in next.config.ts is what makes the config file reachable; without it, ConsentRoot warns outside production that it found no config.

Props

PropPurpose
stateVisitor state or its promise from resolveConsent, or pageProps.consent from withConsentProps. Omit it to resolve consent in the browser
configA defineConsentConfig result to use instead of c15t.config.ts, for a root the file can't reach, such as in a test. A Server Component can't pass it, because it may hold functions
scriptsConsent-managed script configurations
vendorsVendors the preference center lists under their category, each with its own switch. Merged with vendors the backend declares. See vendor consent
clearOnRevocationCookies and Web Storage keys to remove when their category is denied. Initial-only; remount ConsentRoot to replace it
scriptLoaderScript-loader options
networkBlockerNetwork-blocker options, or false to disable it
persistenceBrowser persistence options; defaults to true
optionsProvider options such as styling, callbacks and an explicit mode override

Every prop except state and config can also be set in c15t.config.ts. A prop wins over the config's value of the same name. options merges one key at a time, and options.callbacks one callback at a time, so options={{ nonce }} keeps the config's callbacks and other options.

Which mode does ConsentRoot use?

ConsentRoot runs the config's mode, manifest() by default, or options.mode when you pass one. It loads only that mode's code:

  • manifest(): with state, the browser applies it and needs no request. Without state, or to re-init, it asks ${routePrefix}/init when the config sets routePrefix, else ${backendURL}/init.
  • manifest({ resolve: 'browser' }): the browser loads the resolver on first use and fetches ${routePrefix}/manifest, else ${backendURL}/manifest.
  • hosted(): the browser calls ${backendURL}/init when it needs a policy.
  • offline(): the browser resolves bundled rules. Choices stay in the browser and nothing is recorded. Not recommended for production environments.

Choices post to ${backendURL}/subjects in every mode but offline(). With no backend URL anywhere, ConsentRoot throws @c15t/nextjs: manifest() needs a backend URL. Set NEXT_PUBLIC_C15T_BACKEND_URL (or NEXT_PUBLIC_INTH_PROJECT_URL), or `backendURL` in c15t.config.ts. instead of running a mode you did not choose. See offline configuration and consent modes.

options.mode also takes a transport, such as custom(transport). A hosted() or offline() transport from c15t/react works there, but outside production it warns that its code is now in the first-load bundle. Use the data factories from c15t/next instead.

Provider options

ConsentRoot passes options to its provider. Keep scripts, vendors, clearOnRevocation, persistence and network-blocker configuration at the top level of the config or the props; options does not accept them.

The provider owns initialization, persistence, script loading and subscriptions. Changing its initial mode or prefetch configuration is not a supported way to switch visitors or backends after mounting.

OptionPurpose
modemanifest(), hosted() or offline() from c15t/next, or a transport such as custom(transport). Replaces the config's mode
callbacksChoice, permission and error events
theme, componentsConsent-action styles, theme slots and component slot attributes. Tokens render through ConsentTheme
presentationPrompt and preferences layout behavior
experimentA/B test of presentation, read once at mount. A state from resolveConsent({ experiment }) already carries it. See banner experiments
preloadDialogWhen the deferred ConsentDialog starts loading: 'idle' (default) or 'intent'; see ConsentDialog
i18nLanguages and message overrides
storageConfigBrowser record storage configuration
enabledSet false only when intentionally bypassing consent enforcement
reloadOnConsentRevokedReload the page after the visitor turns off a granted category or vendor; defaults to true

enabled: false grants categories and allows gated loading while suppressing consent UI. It is not a way to fix failed initialization or hide a banner in production.

onChoiceRecorded reports explicit accept, reject and save actions. onPermissionsChanged also covers changes caused by policy, expiry or privacy signals. Hydration and notice dismissal do not become explicit choices.

When would I use ConsentProvider directly?

Use ConsentProvider from c15t/next when you need to manage the runtime and transport yourself. For example, it accepts an externally owned runtime. Its owner must start and dispose that runtime.

For standard Next.js setups, keep ConsentRoot. It supports browser initialization as well as server rendering.

Reload after revocation

Removing a script cannot stop code that already ran. A vendor's listeners, timers and widgets keep working until the page unloads. When an accept, reject or save turns off a category or vendor that was granted, ConsentRoot reloads the page once the save request settles, so the next page runs only permitted code. onBeforeConsentRevocationReload runs just before the reload.

Otherwise, expiry, policy changes and privacy signals do not reload the page. Set options.reloadOnConsentRevoked to false only when every gated vendor stops itself on revocation, for example through its own opt-out API.

Set clearOnRevocation in c15t.config.ts, or pass it to ConsentRoot, to declare cookies and Web Storage keys by optional consent category. Neither accepts it inside options. If you use ConsentProvider directly, pass it in that provider's options. Cleanup runs in the browser after policy resolution, and the value is initial-only. See clear on revocation for examples, cookie scopes, and browser limits.