Skip to content

feat(consent): integrate c15t v2 cookie consent with custom styling#278

Draft
dmnktoe wants to merge 1 commit intomainfrom
cursor/c15t-cookie-consent-8095
Draft

feat(consent): integrate c15t v2 cookie consent with custom styling#278
dmnktoe wants to merge 1 commit intomainfrom
cursor/c15t-cookie-consent-8095

Conversation

@dmnktoe
Copy link
Copy Markdown
Owner

@dmnktoe dmnktoe commented Apr 20, 2026

Summary

Adds a GDPR/TTDSG-compliant cookie consent layer on top of the existing SENTIMENT design system, powered by @c15t/nextjs v2. Styling is fully driven through c15t's theme tokens/slots so the banner, dialog and inline widget match the hero and newsletter section of the site (rounded cards on primary/5, hover on primary/20, CircularStd typography, light/dark palette from tailwind.config.ts).

What the user gets

  • Cookie dialog (modal)ConsentDialog with category toggles, opened from the banner's "Customize" button or the footer's "Cookie settings" pill.
  • Cookie banner — shows up in opt-in jurisdictions; three actions (accept / reject / customize) with styling driven by theme.consentActions (accept = filled primary, customize = ghost, reject = neutral stroke).
  • Inline Cookie Control Center — embedded on the new /cookies page and on the existing privacy page (/privacy). Mirrors the newsletter CTA (NewsletterCTA) two-column rounded card, wrapping ConsentWidget on the right with explicit "Accept all / Reject non-essential / Reset my choice" actions on the left.
  • Cookie policy page (/cookies) — best-practice copy covering definition, legal basis (Art. 6 (1) lit. a/f GDPR, § 25 TTDSG), categories (necessary, measurement, marketing), third-party scripts, retention and user rights.
  • Script blocker — optional scripts are only loaded after consent (c15t script loader). Example wired in: Google Analytics via @c15t/scripts/google-tag with automatic Google Consent Mode v2 defaults (denied until measurement is granted).
  • Privacy policy update — section 3 rewritten to reference the cookie policy, explains that optional scripts are blocked until consent is granted, cites the correct TTDSG legal basis, and embeds the control center inline (section 3a).

Implementation details

New / touched files

  • src/components/helpers/ConsentManager.tsx — provider with custom theme (tokens + slots), bilingual (en/de) copy via options.i18n, legal-link wiring, optional GA4 via @c15t/scripts/google-tag, and a buildOptions() helper that lets NEXT_PUBLIC_C15T_MODE toggle between offline (default, zero-config) and hosted.
  • src/components/templates/CookiePolicy.tsx + src/app/cookies/page.tsx — dedicated /cookies route with the policy + inline control center.
  • src/components/templates/CookieControlCenter.tsx — inline widget reusing the newsletter visual language.
  • src/components/ui/CookieSettingsButton.tsx — small pill button that calls setActiveUI('dialog') to reopen preferences anywhere.
  • src/components/layout/Footer.tsx — added a "Cookie settings" button and a "Cookie Policy" link.
  • src/components/templates/Privacy.tsx — rewrote the cookies section, added section 3a with the inline control center.
  • src/constant/consent.ts — reads NEXT_PUBLIC_C15T_MODE, NEXT_PUBLIC_C15T_BACKEND_URL, NEXT_PUBLIC_GA_ID.
  • src/styles/globals.css + postcss.config.js — adds @import "@c15t/nextjs/styles.tw3.css" between @tailwind components; and @tailwind utilities; and installs postcss-import so the @import is inlined before the CSS nesting rules are generated.
  • src/app/layout.tsx — wraps the tree with <ConsentManager> below the ThemeProvider so the c15t store can observe the dark-mode class set by next-themes.
  • .env.example — documents the new env vars.
  • tsconfig.jsonmoduleResolution bumped from node to bundler so the c15t subpath exports (@c15t/scripts/google-tag) resolve.
  • src/__mocks__/c15t-nextjs.tsx + src/__mocks__/c15t-scripts.ts + jest.config.js — jest mocks so the jsdom test environment does not try to load next/cache through the real package.

Design tokens

Custom Theme uses the SENTIMENT palette:

Token Light Dark
primary #FF5C24 #FF5C24
surface #ffffff #121212
surfaceHover #f2f2f2 #222222
text #121212 #f5f5f5
textMuted #8b9094 #9ca3af

Slots override consentBannerCard, consentBannerFooter, consentDialogCard, consentWidgetAccordion, consentWidgetFooter, toggle, etc. to match the rounded/soft-shadow aesthetic.

Consent categories

Three categories are exposed: necessary, measurement, marketing. Mapping to Google Consent Mode v2 happens automatically via @c15t/scripts/google-tag.

Environment

# Operating mode for c15t (offline = local-only, hosted = via consent.io or self-host)
NEXT_PUBLIC_C15T_MODE=offline
# Only used in hosted mode
NEXT_PUBLIC_C15T_BACKEND_URL=/api/c15t
# Optional — when set, GA4 loads only after the user consents to "measurement"
NEXT_PUBLIC_GA_ID=

Verification

  • pnpm typecheck — ✓
  • pnpm test — ✓ (378 tests, 30 suites)
  • npx eslint src — ✓
  • pnpm format:check — ✓
  • pnpm build fails only on the existing /articles/[slug] page because no Strapi CMS is reachable from the cloud VM; the CSS pipeline and all new routes compile cleanly.

Next steps (optional, not in this PR)

  • Switch NEXT_PUBLIC_C15T_MODE=hosted and point NEXT_PUBLIC_C15T_BACKEND_URL at a consent.io instance (or self-hosted deployment) for durable consent records and jurisdiction auto-detection.
  • Provide a NEXT_PUBLIC_GA_ID to activate GA4; no additional code change required.
Open in Web Open in Cursor 

Adds a GDPR/TTDSG-compliant cookie consent layer on top of the existing
design system, powered by @c15t/nextjs v2 and tuned to match the hero
and newsletter sections of the site.

Additions
- ConsentManager provider (src/components/helpers/ConsentManager.tsx)
  with custom theme tokens/slots mirroring tailwind.config.ts, bilingual
  (EN/DE) copy via c15t i18n, legal-link wiring and opt-in GA4/gtag
  integration through @c15t/scripts (Google Consent Mode v2).
- CookieControlCenter inline widget reusing the rounded two-column
  card from NewsletterCTA for consistent look & feel.
- Dedicated /cookies page with a best-practice cookie policy (categories,
  legal basis per TTDSG/GDPR, retention, rights).
- Script blocker is active by default: optional scripts only load after
  consent for their category; cfg via NEXT_PUBLIC_GA_ID.
- CookieSettingsButton in footer + new Cookie Policy link.
- Privacy page now cross-links to /cookies, embeds the control center
  and updates the legal basis for cookies.

Infrastructure
- Stylesheet import @c15t/nextjs/styles.tw3.css plus postcss-import so
  Tailwind 3 ordering stays valid.
- Jest mocks for @c15t/nextjs and @c15t/scripts/* so existing component
  tests keep running under jsdom.
- tsconfig moduleResolution bumped to 'bundler' to resolve the package's
  export map.

Env
- NEXT_PUBLIC_C15T_MODE, NEXT_PUBLIC_C15T_BACKEND_URL, NEXT_PUBLIC_GA_ID
  documented in .env.example (defaults to offline mode for zero-config).

Co-authored-by: Domenik Töfflinger <dmnktoe@users.noreply.github.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
sentiment Ready Ready Preview, Comment Apr 20, 2026 9:35am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f20477ca-cac7-4a93-a3d9-2eede9a0db30

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/c15t-cookie-consent-8095

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sentry
Copy link
Copy Markdown

sentry Bot commented Apr 20, 2026

Codecov Report

❌ Patch coverage is 26.53061% with 36 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.45%. Comparing base (61d01d4) to head (cf657e1).

Files with missing lines Patch % Lines
src/components/helpers/ConsentManager.tsx 0.00% 14 Missing ⚠️
src/components/templates/CookiePolicy.tsx 0.00% 8 Missing ⚠️
src/app/cookies/page.tsx 0.00% 4 Missing ⚠️
src/constant/consent.ts 0.00% 4 Missing ⚠️
src/components/templates/CookieControlCenter.tsx 66.66% 3 Missing ⚠️
src/components/ui/CookieSettingsButton.tsx 71.42% 2 Missing ⚠️
src/app/layout.tsx 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #278      +/-   ##
==========================================
- Coverage   64.77%   62.45%   -2.33%     
==========================================
  Files          67       73       +6     
  Lines         758      807      +49     
  Branches      155      163       +8     
==========================================
+ Hits          491      504      +13     
- Misses        267      303      +36     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants