Consenti

Introduction

Consenti is an open-source, zero-dependency Consent Management Platform (CMP). It handles the complete consent lifecycle — banner display, preference management, GPC detection, GTM / Google Consent Mode v2 integration, and compliance for GDPR, CCPA, CPRA, and ten other regulations — without pulling in a single external runtime dependency.

Two packages, one platform

PackageRuns inWhat it does
@consenti/uiBrowserThe UI widget. Shows the consent banner and preference modal, detects GPC, fires DOM events, pushes to the GTM dataLayer, and syncs consent across tabs. Uses only browser built-ins — no framework required.
@consenti/apiNode.js serverThe backend module. Install it in your existing Node.js server — it mounts consent API routes and an admin dashboard onto your app. No separate process. Records consent to SQLite by default. Uses only Node.js built-ins.

Frontend-only or full-stack?

The UI widget works entirely in the browser with no server needed. The backend is optional and adds server-side consent storage, a profile management dashboard, multi-tenant support, and audit logs.

Frontend-onlyWith backend
Consent storageBrowser cookie or localStorageServer database (SQLite, MongoDB, PostgreSQL)
Profile managementDefined in code (ConsentiProfile) or inline (profileOverride)Admin dashboard — no code changes to update copy
Consent audit logNoYes — every record stored with timestamp and visitor ID
Multi-site / multi-tenantNoYes
Setup effortOne import, one constructor callnpm install @consenti/api in your existing Node.js backend — mounts routes onto your server, nothing separate to run
💡Start frontend-only. The switch to full-stack later is one config line: api.enabled: true. Existing browser consent records remain valid until superseded by an API record.

What happens on a first visit

  1. The widget initialises and resolves the active profile (code-defined, API-fetched, or built-in default)
  2. It reads any existing consent record from the browser cookie or localStorage
  3. If no valid record exists → the banner appears
  4. The user clicks Accept / Reject / Customize
  5. Consent is saved to the browser and (if configured) POSTed to the backend
  6. consenti:consentSubmitted fires with the full consent record
  7. On every subsequent visit → the banner stays hidden unless consent has expired or the profile version changed

Next