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

@arc-lang/arc-cookie-bar

v0.1.2

Published

GDPR-compliant cookie consent bar for Arc public pages. Granular categories, localStorage persistence, zero dependencies.

Downloads

240

Readme

arc-cookie-bar

GDPR/CCPA-compliant cookie consent bar for Arc public pages. Three consent flows, granular per-category toggles, localStorage persistence, and an optional server-side audit log — zero dependencies, ~3.5KB inline (CSS + JS + HTML).

Features

  • Three consent flows — Accept All, Reject All, or per-category customization
  • localStorage persistence — survives reloads; configurable expiry (default 365 days)
  • arcCookieConsent event — fires on every page load with stored or fresh prefs
  • window.arcCookieBar APIopen(), getConsent(), reset() for programmatic control
  • Three positionsbottom (default), top, modal
  • Server audit log — opt-in POST /arc-cookie-bar/api/consent with IP anonymization
  • Arc theme — inherits --ui-* CSS variables automatically
  • GPU-composited animationswill-change: transform, opacity on the banner
  • Accessiblerole="dialog", aria-modal, aria-expanded, keyboard nav, Escape to dismiss
  • GDPR-safe server logging — IPv4 last octet zeroed, IPv6 truncated to 64 bits
  • Zero dependencies — no npm installs, no build step

Install

npm install @arc-lang/arc-cookie-bar

Add to arc.config.json:

{
  "packages": ["@arc-lang/arc-cookie-bar"]
}

Quick start

import CookieBar from "@arc-cookie-bar/widgets/CookieBar.arc"

page "Home"
  CookieBar(policyUrl="/privacy")
  main
    h1 "Welcome"

The bar appears on first visit, stores consent for 365 days, and fires arcCookieConsent on every subsequent load so your scripts can conditionally initialise trackers.

Widget props

| Prop | Type | Default | Description | |------|------|---------|-------------| | position | String | "bottom" | "bottom" | "top" | "modal" | | categories | String | "necessary,analytics,marketing" | Comma-separated consent categories | | policyUrl | String | "/privacy" | Link to your cookie/privacy policy | | expires | Int | 365 | Days before consent expires and bar re-appears | | title | String | "We use cookies" | Banner headline | | description | String | "…" | Banner body text | | serverPersist | Bool | false | POST each decision to /arc-cookie-bar/api/consent |

Reacting to consent

arcCookieConsent fires on every page load — immediately with stored prefs if consent already exists, or after the user acts on the banner. Wire it before any tracker initialisation:

<script>
window.addEventListener('arcCookieConsent', function(e) {
  if (e.detail.analytics) initGA4()
  if (e.detail.marketing) initMetaPixel()
})
</script>

e.detail is a flat object of booleans, one per category:

{ "necessary": true, "analytics": true, "marketing": false, "_e": 1748736000000 }

(_e is the expiry timestamp — ignore it in your handler.)

window.arcCookieBar API

window.arcCookieBar.open()         // re-open the bar (e.g. from a footer "Cookie settings" link)
window.arcCookieBar.getConsent()   // returns stored consent object, or null if not yet set / expired
window.arcCookieBar.reset()        // clear localStorage and re-show the bar (useful for testing)

Wire a footer link:

button onclick="window.arcCookieBar.open()" "Cookie settings"

Custom categories

You can define any categories:

CookieBar(
  categories="necessary,analytics,marketing,preferences,social"
  policyUrl="/cookies"
)

necessary is always locked on. Built-in descriptions exist for necessary, analytics, marketing, and preferences. Any other name renders without a description.

Server-side consent logging

For GDPR audit trails, enable server persistence:

CookieBar(serverPersist=true policyUrl="/privacy")

Each consent decision POSTs to POST /arc-cookie-bar/api/consent. The table is created lazily on first request — no migration needed.

Schema:

| Column | Type | Description | |--------|------|-------------| | id | INTEGER | Auto-increment PK | | necessary | INTEGER | Always 1 | | analytics | INTEGER | 1 if accepted | | marketing | INTEGER | 1 if accepted | | preferences | INTEGER | 1 if accepted | | ip | TEXT | Anonymized IP — IPv4 last octet zeroed (1.2.3.0), IPv6 truncated to 64 bits (2001:db8:1:2::) | | ua | TEXT | User-agent string, max 512 chars | | created_at | TEXT | UTC timestamp |

Security: The consent endpoint accepts anonymous POSTs. It records consent decisions only — no personal data beyond the anonymized IP. If you want to reject requests from outside your domain, add a CSRF check or restrict with an Arc middleware.

Positions

CookieBar(position="bottom")   // fixed to bottom (default) — slides up on show
CookieBar(position="top")      // fixed to top — slides down on show
CookieBar(position="modal")    // centered overlay with semi-transparent backdrop

Theming

The bar inherits your Arc theme's CSS variables:

| Variable | Used for | |----------|---------| | --ui-bg | Banner background | | --ui-bg-2 | "Reject all" button background | | --ui-text | Primary text | | --ui-muted | Secondary text and category descriptions | | --ui-border | Border, divider, and toggle track | | --ui-accent | "Accept all" button, links, active toggle | | --ui-radius | Border radius for bar and buttons | | --arc-font-sans | Font family |

Override specific elements by targeting .arc-cb in your own stylesheet:

.arc-cb { --ui-accent: #6366f1; }         /* custom accent */
.arc-cb__btn--accept { font-weight: 700; } /* bolder accept button */

Performance

| Metric | Value | |--------|-------| | Client payload (CSS + JS + HTML) | ~3.5 KB inline | | Consent check on repeat visit | ~0.1 ms (single localStorage.getItem + JSON.parse) | | First-paint impact | None — bar starts hidden, shown after paint | | DOM nodes (banner) | 14 | | DOM nodes (customize panel, when open) | +4 per category | | Server INSERT | O(log n) SQLite B-tree — < 0.1 ms |

GDPR compliance notes

  • necessary is always true and its toggle is disabled — no legal basis needed
  • All other categories default to false — opt-in by default
  • Consent is re-prompted after expires days
  • Server-side IP is anonymized before storage — IPv4 last octet zeroed, IPv6 truncated to first 64 bits
  • Consent records are write-only from the browser — no read endpoint is provided

Browser support

All evergreen browsers (Chrome 80+, Firefox 75+, Safari 14+, Edge 80+). No IE11 support — uses CustomEvent, fetch, localStorage, requestAnimationFrame, and optional chaining via ?. in Arc-compiled server code only.

License

MIT — see LICENSE