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

@broberg/consent-cookie

v0.1.0

Published

Headless GDPR consent / cookie-banner core: a framework-free consent state machine with category granularity (essential always-on + analytics/marketing), policy-version re-surfacing, an injectable ConsentStorage (localStorage + memory/SSR), a subscribe st

Downloads

65

Readme

@broberg/consent-cookie

The headless core for a GDPR consent / cookie banner. The banner UI is copy-owned per brand (each product owns its policy text, categories and tokens), but the consent logic — what counts as valid consent, when to re-surface after a policy change, essential-always-on, the right to withdraw — is easy to get subtly (and legally) wrong. This package owns that correct, tested state machine, framework-free and SSR-safe.

npm i @broberg/consent-cookie

Usage

import { createConsentManager } from "@broberg/consent-cookie";

const consent = createConsentManager({
  policyVersion: "2026-05",          // bump this when your policy changes → banner re-surfaces
  storageKey: "acme-consent",        // localStorage key (or pass your own `storage`)
});

if (consent.needsBanner()) showBanner();   // first visit OR policy changed

// user actions
consent.acceptAll();                        // grant every category
consent.rejectAll();                        // essential only
consent.setConsent({ analytics: true });    // granular; essential forced on, unlisted off

// gate side-effects
if (consent.has("analytics")) loadAnalytics();

// GDPR right to withdraw — clears consent, banner returns
consent.withdraw();

// react to changes anywhere
const off = consent.subscribe((record) => sync(record));

What it gets right

  • Policy-version re-surface. needsBanner() / isOutdated() return true when there is no record, when the stored policyVersion differs from the current one, or when a legacy record has no version — so a policy update re-asks users instead of silently keeping stale consent.
  • Essential is always on. Essential categories can't be toggled off; has("essential") is true even before any decision.
  • Right to withdraw. withdraw() clears the record — a legal requirement most hand-rolled banners forget.
  • SSR-safe + injectable storage. createLocalStorageConsentStorage(key) degrades to memory when there's no DOM; implement ConsentStorage to persist server-side (wire it to a profile row) without changing any call sites.

API

createConsentManager({ policyVersion, categories?, storage?, storageKey? }): ConsentManager
// getRecord · needsBanner · isOutdated · has(category) · acceptAll · rejectAll
// setConsent(selection) · withdraw · subscribe · categories

interface ConsentStorage { get(): ConsentRecord | null; set(r): void; clear(): void }
createLocalStorageConsentStorage(key)   // SSR-safe, falls back to memory
createMemoryConsentStorage()
CONSENT_CATEGORIES                       // default: essential · analytics · marketing (overridable)

The React / Preact banner + granular-toggle modal (built on shadcn Dialog/Switch, on your tokens) are copy-owned adapters shipping on top of this core.

License

MIT · part of the @broberg/* shared inventory.