@c15t/nextjs 2.2.1 → 3.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +103 -142
- package/README.md +4 -4
- package/dist/api.js +1 -0
- package/dist/config.js +1 -0
- package/dist/devtools.js +2 -0
- package/dist/headers.js +1 -0
- package/dist/iab/styles.css +1 -1
- package/dist/iab/styles.tw3.css +27 -19
- package/dist/index.js +1 -1
- package/dist/middleware.js +1 -0
- package/dist/node-bridge.js +1 -0
- package/dist/pages.js +1 -0
- package/dist/proxy.js +1 -0
- package/dist/root.js +2 -0
- package/dist/server.js +1 -0
- package/dist/static.js +1 -0
- package/dist/styles.css +1 -1
- package/dist/styles.tw3.css +67 -29
- package/dist/version.js +1 -1
- package/dist-types/api.d.ts +88 -0
- package/dist-types/config.d.ts +110 -0
- package/dist-types/devtools.d.ts +1 -0
- package/dist-types/headers.d.ts +4 -0
- package/dist-types/index.d.ts +28 -10
- package/dist-types/middleware.d.ts +15 -0
- package/dist-types/node-bridge.d.ts +57 -0
- package/dist-types/pages.d.ts +88 -0
- package/dist-types/proxy.d.ts +34 -0
- package/dist-types/root.d.ts +92 -0
- package/dist-types/server.d.ts +164 -0
- package/dist-types/static.d.ts +42 -0
- package/dist-types/types.d.ts +5 -36
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +103 -142
- package/docs/assets/v3/brand-bar.png +0 -0
- package/docs/assets/v3/brand-card.png +0 -0
- package/docs/assets/v3/choice-wall.png +0 -0
- package/docs/assets/v3/mobile-card.png +0 -0
- package/docs/assets/v3/preferences.png +0 -0
- package/docs/customization/overview.md +45 -0
- package/docs/customization/recipes.md +79 -0
- package/docs/customization/slots.md +55 -0
- package/docs/customization/tokens.md +76 -0
- package/docs/customization/translations.md +49 -0
- package/docs/frameworks/next/api-reference/data-fetching.md +416 -0
- package/docs/frameworks/next/app-router.md +403 -0
- package/docs/frameworks/next/client-side.md +118 -0
- package/docs/frameworks/next/components/consent-banner.md +251 -211
- package/docs/frameworks/next/components/consent-dialog-link.md +96 -35
- package/docs/frameworks/next/components/consent-dialog-trigger.md +74 -149
- package/docs/frameworks/next/components/consent-dialog.md +189 -134
- package/docs/frameworks/next/components/consent-manager-provider.md +68 -318
- package/docs/frameworks/next/components/consent-widget.md +172 -114
- package/docs/frameworks/next/components/dev-tools.md +199 -40
- package/docs/frameworks/next/components/frame.md +137 -42
- package/docs/frameworks/next/concepts/consent-categories.md +24 -89
- package/docs/frameworks/next/concepts/policy-presets.md +142 -0
- package/docs/frameworks/next/content-security-policy.md +189 -0
- package/docs/frameworks/next/data-fetching.md +74 -0
- package/docs/frameworks/next/geography-headers.md +251 -0
- package/docs/frameworks/next/headless.md +95 -185
- package/docs/frameworks/next/hooks/use-consent-manager/overview.md +42 -163
- package/docs/frameworks/next/iab/overview.md +37 -107
- package/docs/frameworks/next/optimization.md +158 -194
- package/docs/frameworks/next/pages-router.md +296 -0
- package/docs/frameworks/next/quickstart.md +31 -132
- package/docs/frameworks/next/script-loader.md +140 -465
- package/docs/frameworks/next/server-side.md +97 -130
- package/docs/frameworks/next/static-export.md +164 -0
- package/docs/frameworks/next/styling/overview.md +174 -248
- package/docs/frameworks/next/troubleshooting.md +134 -144
- package/docs/guides/consent-state.md +60 -0
- package/docs/guides/data-fetching.md +163 -0
- package/docs/guides/deployment-modes.md +63 -0
- package/docs/guides/troubleshooting.md +68 -0
- package/docs/guides/verify-consent.md +62 -0
- package/docs/integrations/adobe-analytics.md +239 -105
- package/docs/integrations/ahrefs-analytics.md +238 -104
- package/docs/integrations/amplitude.md +219 -157
- package/docs/integrations/building-integrations.md +32 -224
- package/docs/integrations/clear-on-revocation.md +167 -0
- package/docs/integrations/clearbit.md +247 -86
- package/docs/integrations/cloudflare-web-analytics.md +250 -84
- package/docs/integrations/crisp.md +251 -97
- package/docs/integrations/databuddy.md +259 -153
- package/docs/integrations/fathom-analytics.md +239 -96
- package/docs/integrations/google-maps.md +328 -207
- package/docs/integrations/google-tag-manager.md +248 -96
- package/docs/integrations/google-tag.md +261 -90
- package/docs/integrations/heap.md +222 -149
- package/docs/integrations/hightouch.md +225 -131
- package/docs/integrations/hotjar.md +239 -90
- package/docs/integrations/intercom.md +239 -98
- package/docs/integrations/linkedin-insights.md +243 -113
- package/docs/integrations/logrocket.md +241 -123
- package/docs/integrations/matomo-analytics.md +256 -111
- package/docs/integrations/meta-pixel.md +197 -324
- package/docs/integrations/microsoft-clarity.md +233 -114
- package/docs/integrations/microsoft-uet.md +245 -110
- package/docs/integrations/mixpanel-analytics.md +252 -87
- package/docs/integrations/openai-pixel.md +441 -0
- package/docs/integrations/overview.md +95 -133
- package/docs/integrations/pirsch.md +249 -96
- package/docs/integrations/plausible-analytics.md +241 -100
- package/docs/integrations/posthog.md +353 -214
- package/docs/integrations/promptwatch.md +251 -81
- package/docs/integrations/reddit-pixel.md +226 -173
- package/docs/integrations/rudderstack.md +244 -187
- package/docs/integrations/rybbit-analytics.md +244 -91
- package/docs/integrations/segment.md +238 -92
- package/docs/integrations/snapchat-pixel.md +240 -110
- package/docs/integrations/tiktok-pixel.md +249 -81
- package/docs/integrations/umami-analytics.md +242 -95
- package/docs/integrations/vercel-analytics.md +242 -90
- package/docs/integrations/x-pixel.md +238 -104
- package/docs/integrations/youtube.md +354 -142
- package/docs/upgrade-v3.md +334 -0
- package/iab/styles.css +1 -1
- package/iab/styles.tw3.css +1 -1
- package/package.json +106 -65
- package/readme.json +3 -3
- package/src/iab/styles.css +1 -1
- package/src/iab/styles.tw3.css +1 -1
- package/src/styles.css +1 -1
- package/src/styles.tw3.css +1 -1
- package/styles.css +1 -1
- package/styles.tw3.css +1 -1
- package/client/components/consent-dialog-link.js +0 -3
- package/client/components/integrations.js +0 -3
- package/dist/components/integrations/index.cjs +0 -1
- package/dist/components/integrations/index.js +0 -1
- package/dist/headless.cjs +0 -1
- package/dist/index.cjs +0 -1
- package/dist/libs/browser-initial-data.cjs +0 -1
- package/dist/libs/browser-initial-data.js +0 -1
- package/dist/libs/initial-data.cjs +0 -1
- package/dist/libs/initial-data.js +0 -1
- package/dist/types.cjs +0 -1
- package/dist/version.cjs +0 -1
- package/dist-types/components/integrations/index.d.ts +0 -1
- package/dist-types/libs/browser-initial-data.d.ts +0 -9
- package/dist-types/libs/initial-data.d.ts +0 -33
- package/docs/frameworks/next/building-headless-components.md +0 -379
- package/docs/frameworks/next/callbacks.md +0 -186
- package/docs/frameworks/next/concepts/client-modes.md +0 -177
- package/docs/frameworks/next/concepts/consent-models.md +0 -117
- package/docs/frameworks/next/concepts/cookie-management.md +0 -122
- package/docs/frameworks/next/concepts/glossary.md +0 -24
- package/docs/frameworks/next/concepts/initialization-flow.md +0 -149
- package/docs/frameworks/next/concepts/policy-packs.md +0 -230
- package/docs/frameworks/next/hooks/use-color-scheme.md +0 -41
- package/docs/frameworks/next/hooks/use-consent-manager/checking-consent.md +0 -96
- package/docs/frameworks/next/hooks/use-consent-manager/location-info.md +0 -97
- package/docs/frameworks/next/hooks/use-consent-manager/setting-consent.md +0 -94
- package/docs/frameworks/next/hooks/use-draggable.md +0 -59
- package/docs/frameworks/next/hooks/use-focus-trap.md +0 -42
- package/docs/frameworks/next/hooks/use-reduced-motion.md +0 -37
- package/docs/frameworks/next/hooks/use-ssr-status.md +0 -32
- package/docs/frameworks/next/hooks/use-text-direction.md +0 -50
- package/docs/frameworks/next/hooks/use-translations.md +0 -55
- package/docs/frameworks/next/iab/consent-banner.md +0 -91
- package/docs/frameworks/next/iab/consent-dialog.md +0 -129
- package/docs/frameworks/next/iab/use-gvl-data.md +0 -21
- package/docs/frameworks/next/iframe-blocking.md +0 -106
- package/docs/frameworks/next/internationalization.md +0 -207
- package/docs/frameworks/next/network-blocker.md +0 -140
- package/docs/frameworks/next/policy-packs.md +0 -248
- package/docs/frameworks/next/styling/classnames.md +0 -94
- package/docs/frameworks/next/styling/color-scheme.md +0 -84
- package/docs/frameworks/next/styling/css-variables.md +0 -53
- package/docs/frameworks/next/styling/slots.md +0 -94
- package/docs/frameworks/next/styling/tailwind.md +0 -137
- package/docs/frameworks/next/styling/tokens.md +0 -156
- package/docs/shared/concepts/client-modes.md +0 -103
- package/docs/shared/concepts/consent-categories.md +0 -41
- package/docs/shared/concepts/consent-models.md +0 -72
- package/docs/shared/concepts/cookie-management.md +0 -88
- package/docs/shared/concepts/glossary.md +0 -24
- package/docs/shared/concepts/initialization-flow.md +0 -105
- package/docs/shared/concepts/policy-packs.md +0 -225
- package/docs/shared/react/components/consent-banner.md +0 -242
- package/docs/shared/react/components/consent-dialog-link.md +0 -45
- package/docs/shared/react/components/consent-dialog-trigger.md +0 -185
- package/docs/shared/react/components/consent-dialog.md +0 -119
- package/docs/shared/react/components/consent-manager-provider.md +0 -225
- package/docs/shared/react/components/consent-widget.md +0 -121
- package/docs/shared/react/components/dev-tools.md +0 -81
- package/docs/shared/react/components/frame.md +0 -52
- package/docs/shared/react/guides/building-headless-components.md +0 -110
- package/docs/shared/react/guides/callbacks.md +0 -89
- package/docs/shared/react/guides/headless.md +0 -31
- package/docs/shared/react/guides/iframe-blocking.md +0 -65
- package/docs/shared/react/guides/internationalization.md +0 -123
- package/docs/shared/react/guides/network-blocker.md +0 -72
- package/docs/shared/react/guides/optimization.md +0 -44
- package/docs/shared/react/guides/policy-packs.md +0 -173
- package/docs/shared/react/guides/script-loader.md +0 -311
- package/docs/shared/react/hooks/use-color-scheme.md +0 -31
- package/docs/shared/react/hooks/use-consent-manager/checking-consent.md +0 -95
- package/docs/shared/react/hooks/use-consent-manager/location-info.md +0 -96
- package/docs/shared/react/hooks/use-consent-manager/overview.md +0 -74
- package/docs/shared/react/hooks/use-consent-manager/setting-consent.md +0 -93
- package/docs/shared/react/hooks/use-draggable.md +0 -30
- package/docs/shared/react/hooks/use-focus-trap.md +0 -20
- package/docs/shared/react/hooks/use-reduced-motion.md +0 -33
- package/docs/shared/react/hooks/use-ssr-status.md +0 -16
- package/docs/shared/react/hooks/use-text-direction.md +0 -38
- package/docs/shared/react/hooks/use-translations.md +0 -15
- package/docs/shared/react/iab/consent-banner.md +0 -60
- package/docs/shared/react/iab/consent-dialog.md +0 -76
- package/docs/shared/react/iab/overview.md +0 -80
- package/docs/shared/react/iab/use-gvl-data.md +0 -21
- package/docs/shared/react/styling/classnames.md +0 -93
- package/docs/shared/react/styling/color-scheme.md +0 -35
- package/docs/shared/react/styling/css-variables.md +0 -53
- package/docs/shared/react/styling/overview.md +0 -261
- package/docs/shared/react/styling/slots.md +0 -93
- package/docs/shared/react/styling/stylesheet-entrypoint.md +0 -8
- package/docs/shared/react/styling/tailwind.md +0 -88
- package/docs/shared/react/styling/tokens.md +0 -155
- package/docs/shared/troubleshooting.md +0 -82
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Network Blocker
|
|
3
|
-
description: Block outgoing network requests to third-party domains until the
|
|
4
|
-
user grants consent for the appropriate category.
|
|
5
|
-
group: frameworks
|
|
6
|
-
---
|
|
7
|
-
The network blocker intercepts outgoing `fetch` and `XMLHttpRequest` calls and blocks them based on consent state and domain rules. This catches tracking requests that happen outside of script loading - for example, beacon calls, API requests to analytics endpoints, or pixel fires from already-loaded scripts.
|
|
8
|
-
|
|
9
|
-
## Configuration
|
|
10
|
-
|
|
11
|
-
Add `networkBlocker` to your provider options:
|
|
12
|
-
|
|
13
|
-
```tsx
|
|
14
|
-
import { type ReactNode } from 'react';
|
|
15
|
-
import { ConsentManagerProvider } from '@c15t/nextjs';
|
|
16
|
-
|
|
17
|
-
export function ConsentManager({ children }: { children: ReactNode }) {
|
|
18
|
-
return (
|
|
19
|
-
<ConsentManagerProvider
|
|
20
|
-
options={{
|
|
21
|
-
mode: 'hosted',
|
|
22
|
-
backendURL: '/api/c15t',
|
|
23
|
-
networkBlocker: {
|
|
24
|
-
rules: [
|
|
25
|
-
{
|
|
26
|
-
id: 'google-analytics',
|
|
27
|
-
domain: 'google-analytics.com',
|
|
28
|
-
category: 'measurement',
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
id: 'facebook-pixel',
|
|
32
|
-
domain: 'facebook.com',
|
|
33
|
-
pathIncludes: '/tr',
|
|
34
|
-
category: 'marketing',
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
id: 'analytics-post',
|
|
38
|
-
domain: 'analytics.example.com',
|
|
39
|
-
methods: ['POST'],
|
|
40
|
-
category: 'measurement',
|
|
41
|
-
},
|
|
42
|
-
],
|
|
43
|
-
},
|
|
44
|
-
}}
|
|
45
|
-
>
|
|
46
|
-
{children}
|
|
47
|
-
</ConsentManagerProvider>
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Rule Matching
|
|
53
|
-
|
|
54
|
-
Rules match requests using three criteria:
|
|
55
|
-
|
|
56
|
-
### Domain matching
|
|
57
|
-
|
|
58
|
-
The `domain` field matches the request hostname. Subdomains are automatically included - a rule for `google-analytics.com` also matches `www.google-analytics.com` and `stats.google-analytics.com`.
|
|
59
|
-
|
|
60
|
-
### Path matching
|
|
61
|
-
|
|
62
|
-
The optional `pathIncludes` field requires the request URL path to contain the specified substring. This lets you target specific endpoints without blocking the entire domain.
|
|
63
|
-
|
|
64
|
-
### Method matching
|
|
65
|
-
|
|
66
|
-
The optional `methods` array restricts the rule to specific HTTP methods. If omitted, the rule applies to all methods.
|
|
67
|
-
|
|
68
|
-
## Consent Conditions
|
|
69
|
-
|
|
70
|
-
Like the script loader, `category` accepts a `HasCondition`:
|
|
71
|
-
|
|
72
|
-
```tsx
|
|
73
|
-
// Simple
|
|
74
|
-
{ category: 'measurement' }
|
|
75
|
-
|
|
76
|
-
// Must have both
|
|
77
|
-
{ category: { and: ['measurement', 'marketing'] } }
|
|
78
|
-
|
|
79
|
-
// Must have either
|
|
80
|
-
{ category: { or: ['measurement', 'marketing'] } }
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## Monitoring Blocked Requests
|
|
84
|
-
|
|
85
|
-
### Console logging
|
|
86
|
-
|
|
87
|
-
Blocked requests are logged to the console by default. Disable with `logBlockedRequests: false`.
|
|
88
|
-
|
|
89
|
-
### Callback
|
|
90
|
-
|
|
91
|
-
Use `onRequestBlocked` to handle blocked requests programmatically:
|
|
92
|
-
|
|
93
|
-
```tsx
|
|
94
|
-
networkBlocker: {
|
|
95
|
-
rules: [...],
|
|
96
|
-
onRequestBlocked: ({ method, url, rule }) => {
|
|
97
|
-
console.log(`Blocked ${method} ${url} (rule: ${rule?.id})`);
|
|
98
|
-
},
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Runtime Updates
|
|
103
|
-
|
|
104
|
-
Update the network blocker configuration at runtime:
|
|
105
|
-
|
|
106
|
-
```tsx
|
|
107
|
-
import { useConsentManager } from '@c15t/nextjs';
|
|
108
|
-
|
|
109
|
-
function NetworkBlockerManager() {
|
|
110
|
-
const { setNetworkBlocker } = useConsentManager();
|
|
111
|
-
|
|
112
|
-
const addRule = () => {
|
|
113
|
-
setNetworkBlocker({
|
|
114
|
-
rules: [
|
|
115
|
-
{
|
|
116
|
-
id: 'new-tracker',
|
|
117
|
-
domain: 'tracker.example.com',
|
|
118
|
-
category: 'marketing',
|
|
119
|
-
},
|
|
120
|
-
],
|
|
121
|
-
});
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
## API Reference
|
|
127
|
-
|
|
128
|
-
|Property|Value|
|
|
129
|
-
|:--|:--|
|
|
130
|
-
|Type Name|\`NetworkBlockerRule\`|
|
|
131
|
-
|Source Path|\`./packages/core/src/libs/network-blocker/types.ts\`|
|
|
132
|
-
|
|
133
|
-
\*ExtractedTypeTable: Could not extract "NetworkBlockerRule" from "./packages/core/src/libs/network-blocker/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
134
|
-
|
|
135
|
-
|Property|Value|
|
|
136
|
-
|:--|:--|
|
|
137
|
-
|Type Name|\`NetworkBlockerConfig\`|
|
|
138
|
-
|Source Path|\`./packages/core/src/libs/network-blocker/types.ts\`|
|
|
139
|
-
|
|
140
|
-
\*ExtractedTypeTable: Could not extract "NetworkBlockerConfig" from "./packages/core/src/libs/network-blocker/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Policy Packs
|
|
3
|
-
description: Configure regional consent policies in Next.js — hosted mode,
|
|
4
|
-
presets, and offline fallback.
|
|
5
|
-
group: frameworks
|
|
6
|
-
---
|
|
7
|
-
Policy packs configure how c15t handles regional consent — which model (opt-in, opt-out, none), which categories, and what UI to show. The backend resolves the right policy automatically based on the visitor's location.
|
|
8
|
-
|
|
9
|
-
**For most apps, you just need a `ConsentManagerProvider` pointing at your backend with presets configured there.** The frontend receives the resolved policy via the `/init` response — no client-side policy config required.
|
|
10
|
-
|
|
11
|
-
When a backend isn't available — local development, static previews, Storybook, automated tests, or as a resilience fallback during a temporary outage — you can pass policies directly to the provider via `offlinePolicy.policyPacks` and c15t resolves them locally.
|
|
12
|
-
|
|
13
|
-
> ℹ️ **Info:**
|
|
14
|
-
> For QA and testing, use the c15t DevTools to simulate different regions and policy responses against your real backend, rather than switching to offline mode.
|
|
15
|
-
|
|
16
|
-
## Hosted Mode (Recommended)
|
|
17
|
-
|
|
18
|
-
When using inth.com or a self-hosted backend, the provider connects automatically. No policy configuration is needed on the frontend:
|
|
19
|
-
|
|
20
|
-
```tsx
|
|
21
|
-
<ConsentManagerProvider
|
|
22
|
-
options={{
|
|
23
|
-
backendURL: 'https://your-instance.c15t.dev',
|
|
24
|
-
}}
|
|
25
|
-
>
|
|
26
|
-
<ConsentBanner />
|
|
27
|
-
<ConsentDialog />
|
|
28
|
-
{children}
|
|
29
|
-
</ConsentManagerProvider>
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
The backend resolves the correct policy based on the visitor's geo data and returns it in the `/init` response. Configure your presets on the backend side.
|
|
33
|
-
|
|
34
|
-
## Offline Presets (Development and Fallback)
|
|
35
|
-
|
|
36
|
-
Use offline presets mainly for local development, Storybook, deterministic tests, or temporary backend outages:
|
|
37
|
-
|
|
38
|
-
```tsx
|
|
39
|
-
import { policyPackPresets } from '@c15t/react';
|
|
40
|
-
|
|
41
|
-
offlinePolicy: {
|
|
42
|
-
i18n: {
|
|
43
|
-
defaultProfile: 'default',
|
|
44
|
-
messages: {
|
|
45
|
-
default: {
|
|
46
|
-
translations: {
|
|
47
|
-
en: { cookieBanner: { title: 'Privacy choices' } },
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
eu: {
|
|
51
|
-
fallbackLanguage: 'en',
|
|
52
|
-
translations: {
|
|
53
|
-
en: { cookieBanner: { title: 'EU GDPR Consent' } },
|
|
54
|
-
fr: { cookieBanner: { title: 'Consentement RGPD' } },
|
|
55
|
-
de: { cookieBanner: { title: 'GDPR-Einwilligung' } },
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
policyPacks: [
|
|
61
|
-
{
|
|
62
|
-
...policyPackPresets.europeOptIn(),
|
|
63
|
-
i18n: { messageProfile: 'eu' },
|
|
64
|
-
},
|
|
65
|
-
policyPackPresets.californiaOptOut(),
|
|
66
|
-
policyPackPresets.worldNoBanner(),
|
|
67
|
-
],
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Available presets:
|
|
72
|
-
|
|
73
|
-
|Preset|Model|Matches|
|
|
74
|
-
|--|--|--|
|
|
75
|
-
|`europeOptIn()`|`opt-in`|EEA + UK countries + geo fallback|
|
|
76
|
-
|`europeIab()`|`iab`|EEA + UK countries + geo fallback (TCF 2.3)|
|
|
77
|
-
|`californiaOptOut()`|`opt-out`|US-CA region|
|
|
78
|
-
|`quebecOptIn()`|`opt-in`|CA-QC region|
|
|
79
|
-
|`worldNoBanner()`|`none`|default fallback|
|
|
80
|
-
|
|
81
|
-
## Next.js Example (Hosted)
|
|
82
|
-
|
|
83
|
-
Point the provider at your backend — policy resolution happens server-side:
|
|
84
|
-
|
|
85
|
-
```tsx title="components/consent-manager/provider.tsx"
|
|
86
|
-
'use client';
|
|
87
|
-
|
|
88
|
-
import type { ReactNode } from 'react';
|
|
89
|
-
import {
|
|
90
|
-
ConsentBanner,
|
|
91
|
-
ConsentDialog,
|
|
92
|
-
ConsentManagerProvider,
|
|
93
|
-
} from '@c15t/nextjs';
|
|
94
|
-
|
|
95
|
-
export function ConsentManager({ children }: { children: ReactNode }) {
|
|
96
|
-
return (
|
|
97
|
-
<ConsentManagerProvider
|
|
98
|
-
options={{
|
|
99
|
-
backendURL: 'https://your-instance.c15t.dev',
|
|
100
|
-
}}
|
|
101
|
-
>
|
|
102
|
-
<ConsentBanner />
|
|
103
|
-
<ConsentDialog />
|
|
104
|
-
{children}
|
|
105
|
-
</ConsentManagerProvider>
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
For production Next.js apps, you can optionally hydrate the first `/init` response with the [server-side utilities](/docs/frameworks/next/server-side).
|
|
111
|
-
|
|
112
|
-
## Offline / Fallback
|
|
113
|
-
|
|
114
|
-
For local development, previews, automated tests, or when the backend is temporarily unreachable, pass policies directly:
|
|
115
|
-
|
|
116
|
-
```tsx title="components/consent-manager/provider.tsx"
|
|
117
|
-
'use client';
|
|
118
|
-
|
|
119
|
-
import type { ReactNode } from 'react';
|
|
120
|
-
import {
|
|
121
|
-
ConsentBanner,
|
|
122
|
-
ConsentDialog,
|
|
123
|
-
ConsentManagerProvider,
|
|
124
|
-
policyPackPresets,
|
|
125
|
-
} from '@c15t/nextjs';
|
|
126
|
-
|
|
127
|
-
export function ConsentManager({ children }: { children: ReactNode }) {
|
|
128
|
-
return (
|
|
129
|
-
<ConsentManagerProvider
|
|
130
|
-
options={{
|
|
131
|
-
mode: 'offline',
|
|
132
|
-
offlinePolicy: {
|
|
133
|
-
policyPacks: [
|
|
134
|
-
policyPackPresets.europeOptIn(),
|
|
135
|
-
policyPackPresets.californiaOptOut(),
|
|
136
|
-
policyPackPresets.worldNoBanner(),
|
|
137
|
-
],
|
|
138
|
-
},
|
|
139
|
-
overrides: {
|
|
140
|
-
country: 'DE', // Preview as a German visitor
|
|
141
|
-
},
|
|
142
|
-
}}
|
|
143
|
-
>
|
|
144
|
-
<ConsentBanner />
|
|
145
|
-
<ConsentDialog />
|
|
146
|
-
{children}
|
|
147
|
-
</ConsentManagerProvider>
|
|
148
|
-
);
|
|
149
|
-
}
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
## Provider Shape
|
|
153
|
-
|
|
154
|
-
Configure packs through `offlinePolicy.policyPacks`. Add `offlinePolicy.i18n`
|
|
155
|
-
when you want local previews or fallback behavior to mirror hosted policy-profile language behavior:
|
|
156
|
-
|
|
157
|
-
```tsx
|
|
158
|
-
<ConsentManagerProvider
|
|
159
|
-
options={{
|
|
160
|
-
mode: 'offline',
|
|
161
|
-
offlinePolicy: {
|
|
162
|
-
i18n: {
|
|
163
|
-
defaultProfile: 'default',
|
|
164
|
-
messages: {
|
|
165
|
-
default: {
|
|
166
|
-
translations: {
|
|
167
|
-
en: { cookieBanner: { title: 'Privacy choices' } },
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
qc: {
|
|
171
|
-
fallbackLanguage: 'fr',
|
|
172
|
-
translations: {
|
|
173
|
-
en: { cookieBanner: { title: 'Quebec Privacy Settings' } },
|
|
174
|
-
fr: { cookieBanner: { title: 'Paramètres de confidentialité du Québec' } },
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
},
|
|
178
|
-
},
|
|
179
|
-
policyPacks: [
|
|
180
|
-
{
|
|
181
|
-
id: 'qc_opt_in',
|
|
182
|
-
match: { regions: [{ country: 'CA', region: 'QC' }] },
|
|
183
|
-
i18n: { messageProfile: 'qc' },
|
|
184
|
-
consent: { model: 'opt-in', expiryDays: 365 },
|
|
185
|
-
ui: { mode: 'banner' },
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
id: 'default',
|
|
189
|
-
match: { isDefault: true },
|
|
190
|
-
consent: { model: 'none' },
|
|
191
|
-
ui: { mode: 'none' },
|
|
192
|
-
},
|
|
193
|
-
],
|
|
194
|
-
},
|
|
195
|
-
overrides: { country: 'CA', region: 'QC' },
|
|
196
|
-
}}
|
|
197
|
-
>
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
With that setup, offline mode resolves language the same way as hosted mode:
|
|
201
|
-
|
|
202
|
-
* the active policy profile defines the allowed language set
|
|
203
|
-
* each profile can define its own `fallbackLanguage`
|
|
204
|
-
* built-in translations only fill missing keys for the selected language
|
|
205
|
-
|
|
206
|
-
## Fallback Behavior
|
|
207
|
-
|
|
208
|
-
|Configuration|Result|
|
|
209
|
-
|--|--|
|
|
210
|
-
|`offlinePolicy.policyPacks` omitted|Synthetic opt-in fallback banner (also used for hosted network fallback)|
|
|
211
|
-
|`offlinePolicy: { policyPacks: [] }`|Explicit no-banner mode|
|
|
212
|
-
|Non-empty pack, no match, no default|Explicit no-banner mode|
|
|
213
|
-
|
|
214
|
-
Omitting the option gives you a safe opt-in default for local development and outage scenarios. Providing it tells c15t you want deterministic preview or fallback behavior exactly as configured.
|
|
215
|
-
|
|
216
|
-
## QA and Debugging
|
|
217
|
-
|
|
218
|
-
The best way to test regional consent behavior is with the [c15t DevTools](/docs/frameworks/react/dev-tools). The DevTools Policy panel lets you simulate different countries, regions, and GPC signals against your real backend — no code changes needed.
|
|
219
|
-
|
|
220
|
-
For deeper inspection:
|
|
221
|
-
|
|
222
|
-
* Read `policy` and `policyDecision` from `useConsentManager()` to see the resolved config
|
|
223
|
-
* Open the DevTools Policy panel to inspect matcher resolution and fingerprints
|
|
224
|
-
* Compare your frontend preview with the backend `/init` response before shipping
|
|
225
|
-
|
|
226
|
-
If you need fully deterministic resolution without a backend during testing or preview work (for example, in automated tests or Storybook), pair `offlinePolicy.policyPacks` with `overrides`:
|
|
227
|
-
|
|
228
|
-
```tsx
|
|
229
|
-
options={{
|
|
230
|
-
mode: 'offline',
|
|
231
|
-
offlinePolicy: {
|
|
232
|
-
policyPacks: [
|
|
233
|
-
policyPackPresets.europeOptIn(),
|
|
234
|
-
policyPackPresets.californiaOptOut(),
|
|
235
|
-
policyPackPresets.worldNoBanner(),
|
|
236
|
-
],
|
|
237
|
-
},
|
|
238
|
-
overrides: {
|
|
239
|
-
country: 'US',
|
|
240
|
-
region: 'CA',
|
|
241
|
-
language: 'en-US',
|
|
242
|
-
gpc: true, // Simulate Global Privacy Control
|
|
243
|
-
},
|
|
244
|
-
}}
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
> ℹ️ **Info:**
|
|
248
|
-
> For the full concept model (matchers, scope modes, re-prompting), see Policy Packs concepts. For backend setup, see the self-host guide.
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Class Names
|
|
3
|
-
description: Style consent components using className props and per-slot
|
|
4
|
-
className targeting via the theme.
|
|
5
|
-
group: frameworks
|
|
6
|
-
---
|
|
7
|
-
## Prefer Slots for Stock Components
|
|
8
|
-
|
|
9
|
-
There is no single top-level `className` contract across every pre-built consent component.
|
|
10
|
-
|
|
11
|
-
For the stock `ConsentBanner`, `ConsentDialog`, and `ConsentWidget`, prefer `theme.slots` first. That keeps the markup intact and lets you target the exact part you need.
|
|
12
|
-
|
|
13
|
-
## Per-Slot className
|
|
14
|
-
|
|
15
|
-
Target individual component parts via the theme's `slots` object. Each slot accepts a string (className) or an object with `className` and `style`:
|
|
16
|
-
|
|
17
|
-
```tsx
|
|
18
|
-
const theme = {
|
|
19
|
-
slots: {
|
|
20
|
-
consentBannerTitle: 'text-xl font-semibold',
|
|
21
|
-
consentBannerDescription: 'text-sm text-gray-600',
|
|
22
|
-
consentBannerFooter: 'flex gap-3',
|
|
23
|
-
buttonPrimary: 'rounded-full px-6',
|
|
24
|
-
},
|
|
25
|
-
} satisfies Theme;
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Combining with CSS Modules
|
|
29
|
-
|
|
30
|
-
```tsx
|
|
31
|
-
import styles from './consent.module.css';
|
|
32
|
-
|
|
33
|
-
const theme = {
|
|
34
|
-
slots: {
|
|
35
|
-
consentBannerCard: styles.bannerCard,
|
|
36
|
-
consentBannerTitle: styles.bannerTitle,
|
|
37
|
-
buttonPrimary: styles.primaryButton,
|
|
38
|
-
},
|
|
39
|
-
} satisfies Theme;
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
```css title="consent.module.css"
|
|
43
|
-
.bannerCard {
|
|
44
|
-
backdrop-filter: blur(12px);
|
|
45
|
-
background: rgba(255, 255, 255, 0.9);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
.bannerTitle {
|
|
49
|
-
font-size: 1.25rem;
|
|
50
|
-
font-weight: 700;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
.primaryButton {
|
|
54
|
-
border-radius: 9999px;
|
|
55
|
-
text-transform: uppercase;
|
|
56
|
-
letter-spacing: 0.05em;
|
|
57
|
-
}
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## When to Use Raw className
|
|
61
|
-
|
|
62
|
-
Use raw className-level styling when:
|
|
63
|
-
|
|
64
|
-
* your styling system is already class-driven
|
|
65
|
-
* tokens are too broad for the change
|
|
66
|
-
* slots already identify the correct element
|
|
67
|
-
|
|
68
|
-
If the request is "make the banner footer darker", prefer `theme.colors.surfaceHover` first. If the request is "add a border and spacing only to the footer", prefer `theme.slots.consentBannerFooter`.
|
|
69
|
-
|
|
70
|
-
## Advanced: `noStyle`
|
|
71
|
-
|
|
72
|
-
Use `noStyle` only when you want to remove defaults and style from scratch while still keeping c15t's component structure:
|
|
73
|
-
|
|
74
|
-
```tsx
|
|
75
|
-
{/* Remove all styles from a specific component */}
|
|
76
|
-
<ConsentBanner noStyle />
|
|
77
|
-
|
|
78
|
-
{/* Remove all styles globally */}
|
|
79
|
-
<ConsentManagerProvider options={{ noStyle: true, ... }}>
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
You can also set `noStyle` per-slot:
|
|
83
|
-
|
|
84
|
-
```tsx
|
|
85
|
-
const theme = {
|
|
86
|
-
slots: {
|
|
87
|
-
consentBannerCard: { noStyle: true, className: 'my-custom-card' },
|
|
88
|
-
},
|
|
89
|
-
} satisfies Theme;
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Treat `noStyle` as an advanced escape hatch. Do not jump to it just because a token or slot needs debugging.
|
|
93
|
-
|
|
94
|
-
For full custom markup and behavior, continue to [Headless Mode](../headless).
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Color Scheme
|
|
3
|
-
description: Support light mode, dark mode, and system preference detection in
|
|
4
|
-
consent components.
|
|
5
|
-
group: frameworks
|
|
6
|
-
---
|
|
7
|
-
c15t supports light and dark mode through the theme's `colors` and `dark` token groups. The active color scheme is determined by one of three methods:
|
|
8
|
-
|
|
9
|
-
1. **Explicit setting** via the `colorScheme` option
|
|
10
|
-
2. **CSS class detection** - c15t checks for `.dark` on the document element
|
|
11
|
-
3. **System preference** - matches `prefers-color-scheme` media query
|
|
12
|
-
|
|
13
|
-
## Configuration
|
|
14
|
-
|
|
15
|
-
Set the color scheme on the provider:
|
|
16
|
-
|
|
17
|
-
```tsx
|
|
18
|
-
import { type ReactNode } from 'react';
|
|
19
|
-
import { ConsentManagerProvider } from '@c15t/nextjs';
|
|
20
|
-
|
|
21
|
-
function ConsentManager({ children }: { children: ReactNode }) {
|
|
22
|
-
return (
|
|
23
|
-
<ConsentManagerProvider
|
|
24
|
-
options={{
|
|
25
|
-
mode: 'hosted',
|
|
26
|
-
backendURL: '/api/c15t',
|
|
27
|
-
colorScheme: 'system', // 'light' | 'dark' | 'system'
|
|
28
|
-
theme: {
|
|
29
|
-
colors: {
|
|
30
|
-
primary: '#6366f1',
|
|
31
|
-
surface: '#ffffff',
|
|
32
|
-
text: '#1f2937',
|
|
33
|
-
},
|
|
34
|
-
dark: {
|
|
35
|
-
primary: '#818cf8',
|
|
36
|
-
surface: '#1f2937',
|
|
37
|
-
text: '#f9fafb',
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
}}
|
|
41
|
-
>
|
|
42
|
-
{children}
|
|
43
|
-
</ConsentManagerProvider>
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## useColorScheme Hook
|
|
49
|
-
|
|
50
|
-
For programmatic control over the color scheme:
|
|
51
|
-
|
|
52
|
-
```tsx
|
|
53
|
-
import { useColorScheme } from '@c15t/nextjs';
|
|
54
|
-
|
|
55
|
-
function ThemeToggle() {
|
|
56
|
-
// Pass the desired scheme - 'light', 'dark', 'system', or null (disable)
|
|
57
|
-
useColorScheme('system');
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
|Value|Behavior|
|
|
62
|
-
|--|--|
|
|
63
|
-
|`'light'`|Force light mode|
|
|
64
|
-
|`'dark'`|Force dark mode|
|
|
65
|
-
|`'system'`|Follow `prefers-color-scheme` media query|
|
|
66
|
-
|`null`|Disable - c15t won't manage color scheme|
|
|
67
|
-
|
|
68
|
-
## How Dark Mode Works
|
|
69
|
-
|
|
70
|
-
When dark mode is active, c15t applies the `dark` token values as CSS variable overrides. Only tokens specified in `dark` are overridden - unset tokens fall back to the `colors` values. This also applies to `textOnPrimary`: if you omit it, c15t derives a readable foreground from the active `primary` color in that scheme.
|
|
71
|
-
|
|
72
|
-
```tsx
|
|
73
|
-
const theme = {
|
|
74
|
-
colors: {
|
|
75
|
-
surface: '#ffffff', // Light mode
|
|
76
|
-
text: '#1f2937', // Light mode
|
|
77
|
-
},
|
|
78
|
-
dark: {
|
|
79
|
-
surface: '#1f2937', // Dark mode override
|
|
80
|
-
text: '#f9fafb', // Dark mode override
|
|
81
|
-
// primary is NOT set - inherits from colors.primary
|
|
82
|
-
},
|
|
83
|
-
} satisfies Theme;
|
|
84
|
-
```
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: CSS Variables
|
|
3
|
-
description: Reference for all --c15t-* CSS custom properties generated by the theme system.
|
|
4
|
-
group: frameworks
|
|
5
|
-
---
|
|
6
|
-
Every theme token is converted to a `--c15t-*` CSS custom property at runtime. You can override these variables in your stylesheet without using the JavaScript theme API.
|
|
7
|
-
|
|
8
|
-
## Variable Reference
|
|
9
|
-
|
|
10
|
-
|Property|Value|
|
|
11
|
-
|:--|:--|
|
|
12
|
-
|Type Name|\`ThemeCSSVariables\`|
|
|
13
|
-
|Source Path|\`./packages/ui/src/theme/types.ts\`|
|
|
14
|
-
|
|
15
|
-
\*ExtractedTypeTable: Could not extract "ThemeCSSVariables" from "./packages/ui/src/theme/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
16
|
-
|
|
17
|
-
## Overriding Variables
|
|
18
|
-
|
|
19
|
-
Override in your stylesheet:
|
|
20
|
-
|
|
21
|
-
```css
|
|
22
|
-
:root {
|
|
23
|
-
--c15t-primary: #8b5cf6;
|
|
24
|
-
--c15t-surface: #fafafa;
|
|
25
|
-
--c15t-radius-md: 1rem;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/* Dark mode overrides */
|
|
29
|
-
.dark,
|
|
30
|
-
.c15t-dark {
|
|
31
|
-
--c15t-primary: #a78bfa;
|
|
32
|
-
--c15t-surface: #18181b;
|
|
33
|
-
--c15t-text: #fafafa;
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Scoped Overrides
|
|
38
|
-
|
|
39
|
-
Target specific components by scoping variables:
|
|
40
|
-
|
|
41
|
-
```tsx
|
|
42
|
-
<div className="checkout-consent">
|
|
43
|
-
<ConsentBanner />
|
|
44
|
-
</div>
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
```css
|
|
48
|
-
/* Only affect c15t components inside .checkout-consent */
|
|
49
|
-
.checkout-consent {
|
|
50
|
-
--c15t-surface: #f0f9ff;
|
|
51
|
-
--c15t-radius-lg: 1.5rem;
|
|
52
|
-
}
|
|
53
|
-
```
|