SvelteKit Components
ConsentRoot
Mount ConsentRoot in the root layout
Export loadConsent as the root layout's server load, then pass its
consent to ConsentRoot as state:
Pass data.consent through unchanged. It holds the visitor's
server-resolved consent, the mode c15tHandle() was given, the backend URL
and the consent route's prefix. ConsentRoot renders ConsentProvider from
it, on the server and in the browser, so both render the same banner and the
browser makes no second policy request. The quickstart
explains c15tHandle and loadConsent.
ConsentRoot turns the mode into a transport that loads each policy path
only when it runs. A page the server resolved ships a small transport that
saves choices, and no resolver, policy rules, snapshot or other languages.
The code to resolve the policy again in the browser, such as after a
language change or on a prerendered page, loads when it is needed.
To use a transport of your own, pass custom() from @c15t/svelte as
ConsentRoot's mode prop. c15tHandle() takes only data modes.
Keep the provider in the root +layout.svelte. A layout stays mounted across
client-side navigation, so the runtime, the loaded scripts and the dialog
survive page changes. A provider in a page component would start again on
every navigation.
Create scripts and callbacks in the layout component, not in
+layout.server.ts. They hold functions, which a server load cannot send to
the browser.
Props
Pass each option as a top-level prop, or group them in options. When both
set the same option, the top-level prop wins. The ConsentManagerOptions type
from @c15t/svelte lists every option. SvelteKit's ConsentRoot takes the
same props, except that state replaces mode and prefetch.
| Prop | Type | Default | Behavior |
|---|---|---|---|
mode | manifest(), hosted(), offline() or custom() result, all from @c15t/svelte | required | Where policies come from and where choices are saved. Read once; remount the provider to change it. ConsentRoot builds it from state, or takes a custom() transport as mode. |
prefetch | ConsentState | none | Server-resolved state, such as the result of resolveConsent. With a resolved policy in it, the first render already knows whether to show the banner, and the browser skips its own policy request. ConsentRoot passes it from state. Read once. |
scripts | Script[] | none | Vendor scripts that load when their category is allowed. Updates after mount: new scripts go to the loader. See scripts. |
consentCategories | AllConsentNames[] | the policy's categories | Categories the preference UI offers, within the policy's scope. Updates after mount. |
theme | Theme | none | Slot classes and consentActions button styles. Design tokens in it are not applied in the browser. Updates after mount. |
presentation | ConsentPresentation | the policy's defaults | Banner and dialog shape, position, button layout and blocking for every component. Updates after mount. |
legalLinks | LegalLinks | none | Privacy policy, cookie policy and terms links shown in the banner and dialog. Updates after mount. |
i18n | Partial<I18nConfig> | bundled English | Copy overrides per language. They win key by key over the backend's copy for the same language; see translations. Read once. |
colorScheme | 'light', 'dark', 'system' or null | none | Toggles the c15t-dark class on <html>. null or unset leaves <html> alone. Updates after mount. |
noStyle | boolean | false | Renders every component without c15t's classes. A component's own noStyle wins. |
disableAnimation | boolean | follows prefers-reduced-motion | Turns off enter and exit transitions. |
scrollLock, trapFocus | boolean | from presentation | Defaults for the banner and dialog. blocking on a component sets both. |
preloadDialog | 'idle' or 'intent' | 'idle' | When ConsentDialog starts loading before its first open. See ConsentDialog. |
networkBlocker | options or false | off | Holds fetch and XHR requests to listed domains until their category is allowed. Updates after mount: new rules and enabled apply, and false removes the blocker. The blocker loads on demand. See network blocker. |
iframeBlocker | { disableAutomaticBlocking?: boolean } or false | on | Gates iframes that carry data-category. Updates after mount: false removes the blocker and a new disableAutomaticBlocking rebuilds it. See embeds. |
iab | ProviderIABOptions or false | off | IAB TCF settings. Read once. See IAB TCF. |
callbacks | ConsentProviderCallbacks | none | onChoiceRecorded, onPermissionsChanged, onError and onBeforeConsentRevocationReload. The latest functions are called. See callbacks. |
reloadOnConsentRevoked | boolean | true | Reloads the page after a save withdraws a category or vendor that was granted. |
overrides | { country?, region?, language?, gpc? } | none | Forces the location, language or Global Privacy Control signal the policy resolves for. A change after mount resolves the policy again. |
user | User | none | Identity sent with the policy request and every saved choice, so the choice is linked to your user ID. A different user after mount is identified with the backend; the user you mount with is not identified separately. |
storageConfig | StorageConfig | cookie and key c15t | Names and lifetime of the stored choice. Read once. On SvelteKit, pass the same name as cookieName to the server helpers. |
persistence | boolean or options | true | false keeps choices in memory only. Read once. |
clearOnRevocation | ClearOnRevocationConfig | off | Deletes first-party cookies and storage entries when their category is withdrawn. Loads on demand. See clearing data on revocation. Read once. |
vendors | Vendor[] | none | Vendors offered for vendor-level consent outside IAB. See vendor consent. Updates after mount: a new list replaces the declared vendors. |
nonce | string | none | Content Security Policy nonce for the <script> elements the script loader adds. See Content Security Policy. Read when the loader starts. |
enabled | boolean | true | false grants every category, hides all consent UI and skips /init. Updates after mount: turning it off renders a separate permissive state and keeps the visitor's stored choice for when it is turned back on. |
runtime | ConsentRuntime | none | A runtime you created with createConsentRuntime(). See share one runtime. |
options | ConsentManagerOptions | none | The same options as one object. |
children | Snippet | none | Your app. The provider renders no markup of its own. |
"Read once" options are read when the provider is created. Changing them later
has no effect until the provider remounts, and outside production a change to
mode, i18n or experiment logs a warning. Options that update after mount
are compared with their previous values, so a new options object that only
changes theme sends no request. The provider has no policyRules
option. For local policy rules, pass offline({ policyRules }) as mode.
What the provider does when it mounts
The provider creates the consent runtime while the component initializes, on
the server and in the browser. Creating it has no side effects, so the server
can render the banner from prefetch. In the browser, onMount starts the
runtime:
- It reads the stored choice from the cookie and local storage.
- It starts the script loader, the iframe blocker and, if configured, the network blocker and the IAB TCF add-on.
- It resolves the policy with its
mode, unlessprefetchalready holds one.
When the provider unmounts, it stops all of them. Keep one provider at the root of the app, so it stays mounted across navigation and every component can reach it.
With networkBlocker, matching requests are held from the moment the provider
is created in the browser, before its children run their own code, until the
blocker decides them.
Share one runtime
Pass runtime when two component trees that cannot share Svelte context need
the same consent state. Create it with createConsentRuntime() from
@c15t/svelte, pass it to each provider, and call runtime.start() and
runtime.dispose() yourself. A provider never starts or disposes a runtime it
did not create. Options that build the runtime, such as mode, scripts and
callbacks, come from your createConsentRuntime() call; display options such
as theme and noStyle still apply per provider.
Verify the provider
Open the page in a private window with DevTools open:
- The banner appears once the policy resolves.
window.c15tin the console showspkg: '@c15t/svelte'. - The Network panel shows the request your mode makes: none for
manifest()with a bundled snapshot, one/initforhosted(), and none when the page came with a server-resolved state. - A component that calls
getConsentManager()renders without thec15t: no v3 consent contexterror.