npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

consentric

v1.0.1

Published

Self-contained, configurable GDPR cookie consent for React. Google Consent Mode v2, 10 built-in languages, zero dependencies, zero Tailwind.

Readme

consentric

CI npm version license: MIT

A self-contained, drop-in GDPR cookie consent banner for React — with Google Consent Mode v2 built in.

consentric cookie consent banner

Most cookie banners are either a paid SaaS widget that injects a third-party script into your page, or a barebones snippet you have to wire up yourself. consentric is neither: it's a single React component you import, style with a few props, and forget about. No external scripts, no account, no runtime dependencies, no Tailwind — just one component that ships its own styles and talks to Google Consent Mode for you.

It uses a familiar tabbed layout (Consent / Details / About, four categories, an accordion of per-cookie details) so it feels instantly recognisable to your visitors, while every string, colour, category and cookie table stays under your control.

import { CookieConsent } from 'consentric';

export default function App() {
  return (
    <>
      {/* your app */}
      <CookieConsent company="salecki.digital" privacyUrl="/privacy" />
    </>
  );
}

That's the whole integration. On first visit it shows the banner; after a choice it persists to a cookie and collapses to a small floating button so visitors can change their mind anytime.

Preview

The hero above is the Consent tab. The other two:

Details — every category's cookie table in an accordion.

consentric — Details tab

About — a plain-language explainer plus your policy links.

consentric — About tab

Want to poke at it live? Spin up the playground — language picker plus light/dark themes:

npm install
npm run example   # opens http://localhost:5173

Features

  • Google Consent Mode v2 — pushes default (all denied) on mount and update on the visitor's choice, mapping the four categories to the right Consent Mode signals.
  • Persistent & versioned — the choice is stored in a cookie for one year and restored on the next visit; the stored value is versioned, so a future release can re-prompt everyone after a policy change.
  • Familiar tabbed UX — Consent / Details / About tabs, four categories, a per-cookie accordion. Recognisable to visitors, nothing for you to design.
  • 10 built-in languages — English (default), German, French, Spanish, Italian, Portuguese, Dutch, Polish, Czech and Slovak, picked with one locale prop. Every category, cookie row and UI string is also overridable for any other language.
  • Accessible — focus-trapped modal, focus restored on close, arrow-key tab navigation, full ARIA wiring, and prefers-reduced-motion support.
  • No dark patterns — "Allow all" and "Deny" get equal visual weight, the way EU regulators expect a consent dialog to behave.
  • Works with Next.js — ships as a Client Component ("use client"), so it drops straight into the App Router.
  • Zero dependencies, zero Tailwind — styles are scoped and injected; colours come from props via CSS variables, so it drops into any React project and looks identical regardless of the host's styling.
  • Small & self-contained — one component with all 10 languages, ~15 KB gzipped; ships ESM + CJS with types, sideEffects: false.

Install

npm install consentric

react >= 17 is a peer dependency.

Usage

import { CookieConsent } from 'consentric';

<CookieConsent
  company="salecki.digital"
  privacyUrl="/privacy"
  termsUrl="/privacy#cookies"
  colors={{ brand: '#FAE762', surface: '#050506', text: '#EDEDEF', onBrand: '#0a0a0c' }}
/>

With no props it renders the default dark theme and English copy. Render it once, near the root of your app.

Props

| Prop | Default | What it does | |---|---|---| | manageDefault | true | Push gtag consent default (all denied) on mount. Set false if you set it in <head> before GTM (strict timing — see below). | | cookieName | 'site_consent' | Consent cookie name. Must match the head/GTM snippet if you use one. | | company | — | Operator / brand name shown in the header and About panel. | | logo | — | Optional brand mark (an <svg/> or <img/>). | | privacyUrl | '/privacy' | Privacy policy link. | | termsUrl | '/privacy#cookies' | Cookie/terms link. | | locale | 'en' | Built-in language pack (de, fr, es, it, pt, nl, pl, cs, sk). English is the default and fallback; pt-BR resolves to pt. | | defaultOpen | false | Open the dialog on mount even if a choice is stored (for previews/Storybook). | | defaultTab | 'consent' | Tab to show first: consent / details / about. | | colors | dark theme | { brand, brandDeep, surface, surfaceAlt, text, textMuted, backdrop, onBrand }. | | categories | built-in EN | Per-category content overrides — see below. | | labels | built-in EN | UI string overrides for localisation — see below. | | onChange | — | (choices) => void, fired after the user makes or changes a choice. | | autoClearCookies | true | When a category is denied or revoked, delete the cookies declared in its table (names support a trailing * wildcard). The consent cookie is never touched. |

Customising categories & cookie tables

The four category keys are fixed (they map to Consent Mode signals), but their name, descriptions and cookie list are yours. The count badge is derived from the cookie list, so it always matches. Anything you omit falls back to the default.

<CookieConsent
  categories={{
    statistics: {
      about: 'We use Plausible, a privacy-friendly analytics tool.',
      cookies: [
        { name: 'plausible_ignore', provider: 'Plausible', purpose: 'Excludes your own visits.', meta: 'localStorage' },
      ],
    },
    // necessary / preferences / marketing keep their defaults
  }}
/>

Clearing cookies on withdrawal

When a visitor denies or later revokes a category, consentric deletes the cookies you declared in that category's table — so the data actually leaves the browser, not just the Consent Mode signal. Matching is by cookie name and supports a trailing * wildcard (_ga_* clears _ga_ABC123), and the component tries the common path/domain combinations so cookies set on the registrable domain (e.g. .example.com) are caught too.

Only cookies you list are ever removed, and the consent cookie itself is always kept. It's on by default — pass autoClearCookies={false} to manage cleanup yourself.

Localisation

consentric ships with ten built-in languages — English (the default and the fallback for any missing string) plus nine more. Pick one with the locale prop and the banner, categories and cookie tables are all translated:

<CookieConsent company="salecki.digital" locale="pl" />

| Code | Language | Code | Language | |---|---|---|---| | en | English (default) | pt | Portuguese | | de | German | nl | Dutch | | fr | French | pl | Polish | | es | Spanish | cs | Czech | | it | Italian | sk | Slovak |

Region subtags are accepted — locale="pt-BR" resolves to pt. The full list is also exported as SUPPORTED_LOCALES.

Custom strings & other languages

For a language without a built-in pack — or to reword one — pass your own strings via labels (and categories). They win over the locale pack, which in turn falls back to English, so you can override just a key or two. The operatedBy and readMore templates support {company}, {privacy} and {cookie} placeholders so word order works in any language.

<CookieConsent
  locale="de"
  labels={{
    // start from the German pack, just reword these two
    heading: 'Wir verwenden Cookies',
    deny: 'Nur notwendige',
  }}
/>

Light theme

Defaults assume a dark surface. For a light theme, also set onBrand (the text/icon colour on top of the primary button) so it keeps enough contrast.

<CookieConsent
  colors={{
    brand: '#2563eb',
    brandDeep: '#1d4ed8',
    surface: '#ffffff',
    surfaceAlt: 'rgba(0,0,0,0.04)',
    text: '#0f172a',
    textMuted: '#64748b',
    backdrop: 'rgba(15,23,42,0.4)',
    onBrand: '#ffffff',
  }}
/>

Strict Consent Mode timing (recommended)

For tags to be gated before GTM loads, set the default in <head> (before the GTM snippet) and pass manageDefault={false}. The same snippet can go into a GTM Custom HTML tag on the Consent Initialization - All Pages trigger. The cookie name in that snippet must match cookieName. Full snippet is in the header of src/CookieConsent.tsx. If you skip both, leave manageDefault on — the component pushes the default on mount (fine for simple setups).

License

MIT © salecki.digital