c15t v3: one consent engine for every framework
c15t v3 is a rebuild. One consent engine, adapters for eight frameworks and a script tag, and banners that arrive with the page.
Founder
- 5 min
- Engineering
c15t v3 is out today. It is a rebuild, not a feature release.
v2 was a React library with a Next.js adapter. v3 is one consent engine with adapters for eight frameworks and a script tag. Every adapter passes the same conformance suite, so a policy behaves the same in Nuxt as it does in Next.js.
The full release notes are on c15t.com. This post covers why we rebuilt it, and what changes if you run c15t on Inth.
Why we rebuilt it
Consent is not a React problem. It is a decision about what a page may load, made for one visitor, under one set of rules. That decision has to come out the same whether the page is built with Next.js, Nuxt, Astro or a WordPress theme.
v2 couldn’t promise that. Its consent state lived in a Zustand store that set up blockers and wrote to window as soon as you created it. That made it awkward on the server and tied to React everywhere else.
v3 starts from a consent kernel that does nothing until you call a command. It is safe to import on the server, and every adapter reads it the same way. One conformance suite tests React, Vue and Svelte against the same policy, storage, event and accessibility checks, including records written by v2.
Eight frameworks and a script tag
TanStack Start, Nuxt, Vue, Astro, Svelte and SvelteKit join Next.js and React. @c15t/browser covers plain HTML, WordPress, Webflow, Shopify and other CMS sites.
Most of it ships as one package:
Then import the adapter you need: c15t/next, c15t/react, c15t/vue, c15t/tanstack-start or c15t/astro. Svelte and the script tag install separately as @c15t/svelte and @c15t/browser.
On Astro, the banner is plain .astro markup with no framework JavaScript. On Nuxt, there is a DevTools tab. On Next.js, the Pages Router now gets server-side consent too.
The banner arrives with the page
v2 always mounted the banner after hydration. Visitors saw the page, then the banner, and gated scripts waited for both.
In v3, Next.js, TanStack Start, Nuxt, Astro and SvelteKit can resolve consent while they render. The banner is in the first HTML, and a returning visitor’s allowed scripts start at hydration.
Rendering on the server only helps if the server doesn’t wait on the consent backend for every request. So the backend now serves a consent manifest: one public, cacheable document per project with no visitor data in it. Your server keeps a copy and works out each visitor’s policy from the request’s country, region, language and Global Privacy Control headers.
In a Next.js 16 production build, with 150 ms of latency added to the backend, time to first byte with the manifest was 7.4 ms. Calling the backend on every request took 157.6 ms. If the manifest can’t be read, the server falls back to the per-request call.
The banner is quick in the browser too. On CookieBench, the open benchmark we maintain, c15t’s banner is on screen in a median 27 ms on a Next.js page, and 15 ms on Astro. On Next.js it adds 8 ms to the page’s largest paint, against the same app without a consent manager, and no tracker runs before the visitor chooses. The methodology, code and raw data are public.
Policies you can read
v2 picked GDPR, CCPA or NONE from a fixed country table. v3 decides from your rules alone.
A policy rule says who sees a prompt, what kind of prompt, and which categories it covers. There are 34 presets, up from 6, covering the US privacy states, Canada, Australia, Japan, Switzerland, the UK, Brazil, India and much of Asia and the Middle East. Each preset lists its sources. A preset is a starting point, not legal advice.
Two changes matter more than the count:
- Records store what the visitor did, not what it meant. c15t works out permissions against the current rule each time it reads a record.
- Global Privacy Control is read live. It is never stored as a refusal, so the restriction ends when the browser stops sending the signal.
Finer control
- Per-vendor consent without IAB. A visitor can switch off one vendor inside a category they allowed.
- GPP 1.1 with sections for 16 US states, and IAB publisher restrictions encoded in the TC string. IAB banners now work in every framework, not just React and Next.js.
- New integrations for Cloudflare Zaraz, Klaviyo and the OpenAI pixel for ChatGPT Ads.
@c15t/scriptsis now@c15t/integrations, and every v2 helper carries over.
What changes on Inth
If your consent backend runs on Inth, three things are worth knowing.
The script tag comes from your project. Sites without a build step can load c15t straight from Inth, with the backend URL and policy already inside:
Inth-hosted backends already speak v3. You don’t need to migrate a database. If you self-host, upgrade the client and the backend together: a v3 client can’t read a v2 backend’s /init, and it will show no banner and keep optional categories denied.
Your visitors' existing choices still count. v3 reads the cookie and storage key v2 wrote. A v2 denial keeps blocking its category, and a v2 grant keeps applying until it expires.
Upgrading
The code changes are real. ConsentManagerProvider is now ConsentProvider, useConsentManager() is split into one hook per field, the callbacks are renamed, and every package is ESM only.
Each v2 package has its own upgrade guide: Next.js, React and JavaScript. Each one opens with a prompt you can paste into a coding agent. Start with the codemods:
New project? Paste this into your coding agent:
It takes the agent from an Inth account to a working banner, and moves your existing analytics and pixels behind consent. The same prompt opens every framework quickstart on c15t.com.
Thank you
c15t v3 was built in the open by @KayleeWilliams, @BurnedChris, @dan-hale, @bennajah and @prashantbhudwal. It is open source under Apache 2.0.