Draft note: this is currently written as
v2.1.0because the release adds opt-in v3 entrypoints across core, React, Next.js, and IAB packages. If we classify it as a patch preview instead, update the frontmatter and package list before publishing.
This release introduces the first opt-in preview of the v3 API for c15t, @c15t/react, and @c15t/nextjs.
The goal of v3 is not to replace the stable v2 API in-place. The new API ships behind explicit /v3 entrypoints so teams can try the new runtime model without changing existing v2 integrations.
Highlights
- New framework-neutral kernel in
c15t/v3 - Policy-first v3 surface aligned with the current policy-pack runtime
- v3 hosted consent writes are aligned back to the backend's subject endpoint,
POST /subjects - React v3 provider and hooks isolate renders to the selected consent slice
- Next.js v3 helpers prefetch rich init data into a serializable
KernelConfig - IAB v3 handle exposes the CMP API through an observable getter
Policy-first v3 API
v3 moves the consent runtime around a small kernel:
Adapters read from the same snapshot:
The important change is that the v3 preview no longer exposes legacy jurisdiction/banner fields as part of its public contract.
Instead, the resolved policy is the source of truth:
policy.modeldetermines whether the effective model isopt-in,opt-out,iab, ornullpolicy.ui.modedetermines whether the active UI isbanner,dialog, ornone- geographic data remains an input to policy resolution, but not the main public runtime contract
This matches the direction already taken by the v2 policy-pack runtime, where jurisdiction-shaped fields are deprecated compatibility data rather than the behavior source of truth. v3 uses the preview period to make that contract explicit and avoid carrying deprecated fields into new framework adapters.
This also makes the React adapter smaller and easier to keep consistent with the framework-neutral kernel. React now subscribes to kernel state by selected slice instead of recreating consent semantics inside provider state.
Hosted saves are aligned with /subjects
The v3 hosted transport now writes consent records through the same subject-centric API used by the current backend:
This is a v3 preview alignment fix. v2 already uses the subject endpoint; the issue was that the new v3 transport had temporarily drifted to the wrong write URL while the preview API was being shaped.
The v3 save body maps the kernel snapshot into the backend schema with:
subjectIddomaintype: 'cookie_banner'preferencesgivenAtpolicySnapshotTokentcStringjurisdictionModeluiSourceconsentAction- external subject identity fields
subjectId is generated lazily before the first save and reused for future writes. Persistence hydration restores that subject ID locally without making a backend save.
Faster React runtime
The biggest user-visible improvement is in @c15t/react/v3.
The v2 React provider exposes a larger consent manager object through React state and context. That is ergonomic, but it means a consent mutation can fan out through components that do not care about the changed category.
The v3 React provider creates one kernel per mount and lets hooks subscribe to exactly the slice they need:
In the render-count benchmark, ten children read five different consent categories, then only marketing changes:
| Runtime | Mount commits | Mutation commits |
|---|---|---|
v2 ConsentManagerProvider + useConsentManager() | 20 | 20 |
v3 ConsentProvider + useConsent(category) | 10 | 2 |
That is a 50% lower mount count in the benchmark harness and a 90% reduction in mutation fanout. Only the two components reading marketing re-rendered.
The browser benchmarks also show faster visible UI and consent-triggered script loading in the local deterministic examples. These numbers come from a 50-iteration local run after rebuilding the benchmark apps and removing script-count probe overhead from the measured path:
| Benchmark | v2 median | v3 median | Change |
|---|---|---|---|
| Banner visible | 73.2 ms | 59.1 ms | -19.3% |
| Banner mount | 39.3 ms | 33.1 ms | -15.8% |
| Script loading, 5 scripts | 12.9 ms | 9.7 ms | -24.8% |
| Script loading, 10 scripts | 14.0 ms | 10.3 ms | -26.4% |
| Script loading, 25 scripts | 20.3 ms | 11.9 ms | -41.4% |
| Script loading, 50 scripts | 26.7 ms | 18.2 ms | -31.8% |
The deterministic routes preseed backend state and use local scripts, so the results should be read as runtime overhead comparisons, not third-party network latency measurements.
The bundle-size story is more nuanced. The v3 API is split by design, so common paths can import only the provider, hooks, UI, and modules they use. Synthetic routes that import every v3 feature can still be larger than a narrower v2 route. We will continue tracking common route shapes separately from full harness routes.
Next.js v3 prefetch
@c15t/nextjs/v3/server now returns a plain KernelConfig that can be awaited in a Server Component and passed to the client boundary:
The prefetch result preserves rich init fields through first render:
- location
- translations
- branding
- policy
- policy decision
- policy snapshot token
- GVL
- custom vendors
- CMP ID
This keeps first paint aligned with the backend's resolved policy while still letting the client refresh init after mount.
Compatibility
This is an opt-in API preview. Existing v2 imports keep working:
The v3 surface is available through explicit v3 entrypoints:
Because v3 is still unstable, we are using the preview period to validate framework integration patterns, React Compiler behavior, and benchmark coverage before promoting this contract to stable.
Notes
- This release is scheduled for May 3, 2026
- The v3 API is opt-in and does not require existing v2 applications to migrate
- The final version number may change before publish depending on whether we classify this as a minor preview or a patch-level opt-in feature