Repository navigation
fix(deps): update dependency @c15t/nextjs to v3 - #453
Open
renovate[bot] wants to merge 1 commit into
Open
renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
|
Important Review skippedBot user detected. To trigger a single review, invoke the
|
renovate
Bot
force-pushed
the
renovate/c15t-nextjs-3.x
branch
4 times, most recently
from
October 26, 2026 07:33
5c04f84 to
2596abf
Compare
renovate
Bot
force-pushed
the
renovate/c15t-nextjs-3.x
branch
3 times, most recently
from
November 4, 2026 20:49
de43c5f to
859437f
Compare
renovate
Bot
force-pushed
the
renovate/c15t-nextjs-3.x
branch
from
November 7, 2026 14:58
859437f to
b026621
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
2.4.1→3.2.2Release Notes
c15t/c15t (@c15t/nextjs)
v3.2.2Compare Source
Published @c15t/nextjs@3.2.2.
v3.2.1Compare Source
Published @c15t/nextjs@3.2.1.
v3.2.0Compare Source
Match the stock surfaces' text direction and IAB handling in headless UI
useConsentTextDirection()returns'rtl'or'ltr'for the languagec15t shows consent copy in. Set it as
diron a custom banner orpreference center, as the stock ones do, so a visitor whose browser
language runs right to left gets a mirrored layout.
useIABPolicyGuard()is now public. A custom surface that handles onlyopt-in and opt-out calls it and returns
nullwhenuseModel()is'iab'. The guard throwsIABUnavailableErrorwhile rendering when thepolicy needs IAB and the app never loaded
<IABProvider>.Import both from
c15t/react/headless,c15t/next/headlessorc15t/tanstack-start/headless.Set the subject ID cookie on the server
The framework adapters now give a new visitor a subject ID on their first
request. The server sets it in the
c15t-sidcookie and the server renderuses the same ID, so the browser starts with it instead of creating its own.
The cookie holds only the ID: the banner still shows until the visitor
decides.
c15tProxysets the cookie and forwards it on the request, soresolveConsentin the same request reads it.withConsentPropssets itfor Pages Router pages. Both accept
storage,trustForwardedHeadersand
subjectCookie. Without the proxy, App Router pages leave it to thebrowser.
consentRequestMiddlewaresets it and accepts the sameoptions. Prerendered pages get none.
storageConfig.middleware.trustForwardedHeadersandmiddleware.subjectCookieare new. With aconsentSource, passsubjectCookie: false.c15tHandlesets it and exposes the request cookie aslocals.c15t.cookie.storage,trustForwardedHeadersandsubjectCookieare new options. Withpersistence: falseor aconsentSourceonConsentProvider, passsubjectCookie: false.and cached routes.
Prefetch and prerender requests, and responses marked as shared, never get a
cookie, because every visitor who received it would share the ID. Neither does
the consent route, which renders no page and serves its manifest as public
data a shared cache keeps: Next.js skips the
routePrefixinc15t.config.ts, SvelteKit and Astro skip theirroutePrefix, and each fallsback to
/api/c15t. The Next.js proxy and the SvelteKit handle run beforethe response exists, so pass
subjectCookie: falsefor requests to otherroutes a shared cache keeps, such as a public API route or feed; the
consent headers are still normalized. TanStack Start sees the response: a
page whose
resolveConsentread the visitor's cookies holds the visitor'sconsent and subject ID, so it is sent
privatewith the cookie, keepingits browser directives, and without the CDN cache fields, such as
CDN-Cache-ControlandSurrogate-Control, that a CDN honouring them readsin place of
Cache-Control. A response with no such render that setspublic,s-maxage,max-age,no-cacheorExpires, or a CDN cache fieldthat lets the CDN store it, gets no cookie, and
TanStack Start sends the consent route's responses unchanged, wherever it is
mounted. Render HTML you cache for every
visitor with
shared: true. Pass the samestorageoptions as thebrowser so the cookie has the same name, domain and lifetime. With
persistence={false}or aconsentSourceonConsentRoot, passsubjectCookie: falseso the server sets no cookie.On another server,
resolveRequestSubject()fromc15t/serverreturns thevisitor's ID, the
Set-Cookievalue to send and the requestCookieheaderto render with.
A subject ID with an unpaired UTF-16 surrogate gets no subject cookie, and the
server keeps the ID its records carry. TanStack Start's server-render state
replaces that surrogate with U+FFFD on the way to the browser; see the
TanStack Start docs for when the browser keeps the changed ID.
The server helpers read a Node-style header record under any header-name
casing.
resolveRequestSubject()andreadRequestConsent()find aCookieorCOOKIEheader, and the request origin findsHost. Forwarding headers arestill read only with
trustForwardedHeaders: true.The server and the adapters never replace a
c15t-sidcookie the requestalready has. While the browser's cookie writes succeed, the server render and
the browser use the same ID. The server reads cookies only, though. If the
browser refuses to rewrite a record cookie after the subject ID changes, a
server render keeps reporting the old ID that cookie holds, and the browser
starts with the new ID from its localStorage. This happens even when the
request's
c15t-sidcookie already holds the new ID. It lasts until a laterwrite of that record reaches the cookie, which may never happen while the
browser keeps refusing it.
With
crossSubdomain, a visitor whose only record is a vendor decision can holda local vendor copy and a shared cookie copy with the same decision time but
different subject IDs, because a rekey keeps the original decision time. As
before, a page that hydrates from storage starts with the local copy's ID.
Server-rendered pages now do the same. The runtime does not write that ID over a
shared
c15t-sidcookie the record cookies agree with, but a later vendor savefrom this origin stores it in the shared vendor cookie, and after that a later
page load can store it in the shared
c15t-sidcookie too. The ID mismatch onits own grants no optional category and lifts no denial; that vendor save
changes only the vendor decisions it names.
Rename offline mode to
local()and warn that it keeps no consent recordsoffline()is nowlocal()in every framework package, inc15tand inc15t/modes.offline()still works and is marked deprecated. c15t v4 removesit.
In development builds, local mode logs one
console.warnper page: c15t keepsno server-side record of consent, and with no geolocation every visitor gets
the same policy. Production builds never log it, and it blocks nothing. Pass
local({ acknowledgeNoRecords: true })to hide it once you have decided abrowser-only record is enough. c15t v4 will require that option.
The script tag's local-mode file is now
c15t.local.js.c15t.offline.jsstill ships until v4, and on development hosts it logs its new name. Script-tag files are production builds, so
they log the warning only on development hosts such as
localhost. Adddata-acknowledge-no-recordsto the tag to hide it.c15t.local()joins thescript-tag global.
c15t setuplabels local mode "Development and tests only, no consent records"and generates
local().Lock page scroll from a headless banner
useScrollLock(shouldLock)locks page scroll the way the stock banner doeswhen its policy is blocking. Call it with
banner.isVisible && banner.blockingfromuseHeadlessConsentUI(). Locksare counted, so the page scrolls again once every surface holding one lets
go. Import it from
c15t/react/headless,c15t/next/headlessorc15t/tanstack-start/headless.Stream a headless banner with
StreamedConsentSurfaceStreamedConsentSurfacelets a banner built with the headless hooks streamlike the stock
ConsentBanner. With Next.js<ConsentRoot state={resolveConsent()}>or a streamed TanStack Start loader,it waits for the consent promise in its own
Suspenseboundary, so thebanner follows in a later chunk of the same response and shows before
hydration. Without a pending promise it renders its children as they are.
Call the hooks in a component inside it. Import it from
c15t/react/headless,c15t/next/headlessorc15t/tanstack-start/headless.Add
useConsentGatefor custom consent gatesuseConsentGate(category)returns what a gate on one consent category shouldrender:
'granted','pending','denied'or'policy-blocked'. It alsoreturns the translated title, button label and policy message, and
requestConsent, which opens the preference center. Import it fromc15t/react/headless,c15t/next/headlessorc15t/tanstack-start/headless.ConsentGatenow runs on the hook, so a custom gate follows the same rules.Granted content waits for hydration, a strict policy scope blocks categories
outside it, and server rendering never reads the clock.
ConsentGaterendersthe same markup as before.
Export banner copy and button labels for headless UIs
resolvePromptCopy(translations, prompt)returns the banner's title anddescription, and reads the notice copy when the prompt is a notice.
resolveActionLabels(translations)labels each banner action, andresolvePreferenceControlLabels(translations)labels the opt-out andpreferences buttons. All three use the active language and fall back to
English for a missing key. Import them from
c15t,@c15t/svelte,@c15t/svelte/headless,c15t/vue/vue-pluginor@c15t/browser/headless.@c15t/browser/headlessalso exportsresolveConsentPresentationnow.React adds
useBannerCopy()anduseConsentLabels()toc15t/react/headless,c15t/next/headlessandc15t/tanstack-start/headless. They return the same strings the stockbanner renders and update when the language changes. The same headless
entries now export
useVendorsListedUnder(category), which returns thevendors the stock dialog lists under a category.
When a notice offers only a dismiss button,
primaryActionsfromresolveConsentPresentationnow containsdismiss, so a headless banner canstyle it as the primary button. The browser banner now styles that button as
primary too. The React, Vue and Svelte banners already did.
Allowed scripts start from the server HTML
Next.js, TanStack Start, Nuxt and SvelteKit now start the
scriptsentries avisitor's consent already allows from the server-rendered HTML, before the page
hydrates. An inline script runs after first paint and inserts their tags; the
script loader adopts them. On a throttled mobile profile, vendors started about
800 ms sooner. This covers React 18 and 19, and every vendor helper in
@c15t/integrationsexcept Cloudflare Zaraz and Sentry.Nothing starts while the policy asks the visitor to choose, or from prerendered
or cached HTML. Set
scriptLoader: { serverStart: false }to start every entryafter hydration, as before.
Rewrite npm descriptions for search
npm search scores a phrase in the description far above the same words in
keywords or the README. Each package description now names the phrases
people search for that package: "cookie banner", "cookie consent manager",
"consent management platform" and "Google Consent Mode v2" on
c15t,"React cookie banner" on
@c15t/react, "Vue cookie consent" on@c15t/vue,and so on.
c15tkeeps "The open standard for cookie banners". Supportingpackages describe their role in c15t instead of repeating the main
package's phrases. Keyword lists are shorter. No code changes.
v3.1.0Compare Source
Get the provider's event dispatcher in every framework
Each framework now hands you one event dispatcher that sends to the provider's
registered scripts and reads consent when an event goes out:
useEventDispatcher()fromc15t/react,c15t/nextandc15t/tanstack-startuseEventDispatcher()fromc15t/vue/vue-plugin, auto-imported in NuxtgetEventDispatcher()from@c15t/sveltegetEventDispatcher()fromc15t/astro/clientgetEventDispatcher(runtime)from@c15t/browserAll dispatchers for one provider share a pageview history, so a consent change
or a remount no longer drops or resends a pageview, and an event sent right
after a visitor withdraws consent is dropped. Pass
scriptsto add moredestinations and
pageviewsto choose which integrations get single-page-apppageviews.
createEventDispatcherfrom@c15t/integrations/eventsstill worksfor code without a provider.
Clearer npm descriptions and keywords
Each package's npm description now says what it does in the words people
search for, such as cookie consent, cookie banner, GDPR, Google Consent Mode v2
and IAB TCF. Keywords add common search terms while preserving existing
framework, brand and integration terms. The schema and UI packages now link
to their directories in the repository. Framework, browser and core READMEs
now explain how consent policies handle GDPR and other privacy laws before
the setup instructions.
The preference dialog scrolls with your CSS
Visitors can scroll to every category and vendor in the preference dialog
again. Before this fix, the category list did not scroll with some app CSS.
The cause was
overflow: hiddenon the category list or on a category row,for example to clip them to rounded corners. On a phone, a category with
vendors then went past the bottom of the dialog. The visitor could not scroll
to the rest.
Vendor switches show only when you declare vendors
The preference dialog shows only category switches until you declare a
vendor. Your visitors make one choice for each category. You do not get
vendor switches that you did not ask for.
Since 3.0.0, the dialog showed a switch for the vendor of each
@c15t/integrationshelper. For example, a site that added onlyposthog()got a PostHog switch under Analytics. We did not intend this default.
To show vendor switches, declare at least one vendor in the
vendorsoptionor on the backend. The dialog then also lists the vendors of your helpers by
name, as before. This change affects only the dialog. It does not change when
a script loads.
Keep saved helper vendor denials accessible
A helper vendor the visitor previously switched off stays visible in the
preference dialog when the site declares no vendors. The visitor can turn that
vendor on without changing any category choices. Its saved denial continues to
block loading until the visitor changes it and saves. Other helper vendors stay
hidden until the site declares a vendor.
The browser dialog updates helper rows when saved vendor consent changes while
it is open.
v3.0.0Compare Source
c15t v3
c15t v3 is stable and published under the
latesttag. See the3.0.0 changelog for new features, breaking
changes and upgrade guides.
Configuration
📅 Schedule: (in timezone Europe/Berlin)
* 0-6 * * 1)🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.