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

svelte-klaro

v0.1.1

Published

Svelte 5 cookie consent manager — a complete port of Klaro with reactive state, tree-shakeable translations, and CSS custom property theming.

Downloads

191

Readme

svelte-klaro

npm

A Svelte 5 port of the Klaro cookie consent manager. Fully typed, reactive, tree-shakeable, and localized (25 languages).

Features

  • Svelte 5, fully typed
  • 1:1 UI/UX match with the original Klaro
  • 12 KB gzipped (vs 66 KB for original klaro with Preact)
  • 25 tree-shakeable translations (only English bundled by default)
  • CSS custom property theming with composable position/color themes
  • Cookie deletion on consent withdrawal
  • Load config from KIProtect API or pass locally
  • SSR-safe

Install

pnpm add svelte-klaro

Quick Start

<script lang="ts">
    import { Klaro, type KlaroConfigInterface } from 'svelte-klaro';
    import 'svelte-klaro/styles';

    const config: KlaroConfigInterface = {
        acceptAll: true,
        services: [
            {
                name: 'google-analytics',
                title: 'Google Analytics',
                purposes: ['analytics'],
                cookies: [/^_ga/, '_gid']
            },
            {
                name: 'hotjar',
                title: 'Hotjar',
                purposes: ['analytics']
            }
        ]
    };
</script>

<Klaro {config} />

Configuration

The config prop accepts a KlaroConfigInterface object. Key options:

| Option | Type | Default | Description | | ------------------------ | ------------------------------------------------ | ------------ | -------------------------------------------- | | services | KlaroServiceInterface[] | required | Third-party services to manage | | acceptAll | boolean | false | Show "Accept all" button | | mustConsent | boolean | false | Block page until user consents | | hideDeclineAll | boolean | false | Hide the decline button | | groupByPurpose | boolean | true | Group services by purpose in modal | | storageMethod | 'cookie' \| 'localStorage' \| 'sessionStorage' | 'cookie' | How to persist consent | | storageName | string | 'klaro' | Cookie/storage key name | | cookieExpiresAfterDays | number | 120 | Cookie expiry | | htmlTexts | boolean | false | Allow HTML in translation strings | | noticeAsModal | boolean | false | Show notice as modal overlay | | embedded | boolean | false | Render inline instead of fixed | | privacyPolicy | string \| Record<string, string> | -- | Privacy policy URL (or per-language) | | styling | object | -- | Theme and CSS variable overrides | | translations | object | -- | Translation overrides (merged with defaults) | | purposeOrder | string[] | -- | Sort order for purposes |

Service Configuration

Each service in the services array:

{
  name: 'google-analytics',       // unique identifier
  title: 'Google Analytics',       // display name
  purposes: ['analytics'],         // groups in modal
  description: 'Web analytics',    // shown in modal
  cookies: [/^_ga/, '_gid'],       // deleted on consent withdrawal
  required: false,                 // cannot be disabled
  optOut: false,                   // enabled by default, user can opt out
  onlyOnce: false,                 // execute handler only once
  onAccept: (opts) => {},          // called when consent granted
  onDecline: (opts) => {},         // called when consent withdrawn
  callback: (consent, service) => {} // called on any change
}

Translations

English translations are bundled by default. Import additional languages from svelte-klaro/translations and pass them via the translations prop or inside config.translations:

<script>
    import { Klaro } from 'svelte-klaro';
    import { de, fr } from 'svelte-klaro/translations';
</script>

<!-- Via translations prop (useful when config is loaded remotely) -->
<Klaro {config} translations={{ de, fr }} />

<!-- Or via config.translations -->
<Klaro config={{ ...config, translations: { de, fr }, lang: 'de' }} />

Available languages: ca, cs, da, de, el, en, es, fi, fr, gl, hr, hu, it, nl, no, oc, pl, pt, ro, ru, sr, sr_cyrl, sv, tr, zh

Override individual keys:

const config = {
    translations: {
        en: {
            consentNotice: { description: 'We use cookies for {purposes}.' },
            purposes: { analytics: 'Analytics & Metrics' }
        }
    }
    // ...
};

Styling

Import styles

// Compiled CSS (recommended)
import 'svelte-klaro/styles';

// Or raw SCSS (requires a Sass compiler)
import 'svelte-klaro/styles/scss';

Themes

Compose themes via config.styling.theme:

const config = {
    styling: { theme: ['top', 'wide', 'light'] }
    // ...
};

| Theme | Effect | | -------- | ------------------------------------ | | top | Notice at top | | bottom | Notice at bottom (default) | | left | Notice on the left | | right | Notice on the right (default) | | wide | Notice spans full viewport width | | light | Light color scheme (default is dark) |

CSS Custom Properties

Override via config.styling or plain CSS:

const config = {
    styling: {
        theme: ['bottom'],
        green1: '#0a6e5c',
        'border-radius': '8px',
        'font-size': '13px'
    }
    // ...
};
.klaro {
    --green1: #0a6e5c;
    --dark1: #333;
    --light1: #fafafa;
    --font-size: 14px;
    --border-radius: 4px;
    --notice-max-width: 400px;
}

Events

Svelte 5 callback props on the <Klaro> component. onconsentchange fires once per service after the user commits (accept/decline/save), not on individual toggles in the modal. It also fires on initial load with the current consent state.

| Prop | Signature | When | | ----------------- | ------------------------------------ | ------------------------------------------- | | onconsentchange | (consents, service, value) => void | Per service after save, and on initial load | | onsave | (manager, eventType) => void | User saves (accept/decline/save) | | onapply | (manager, changedCount) => void | Consents applied to DOM | | onshow | () => void | Notice/modal becomes visible | | onhide | () => void | Notice/modal is hidden | | oninit | (manager) => void | Manager initialized (client-side) |

<Klaro
    {config}
    onconsentchange={(consents, service, value) => {
        console.log(`${service}: ${value}`);
    }}
    onsave={(manager, eventType) => {
        // eventType: 'accept' | 'decline' | 'save'
        analytics.track('consent_' + eventType);
    }}
/>

Programmatic API

<script>
    import { Klaro, showKlaro, hideKlaro, getManager } from 'svelte-klaro';
</script>

<!-- showKlaro() re-shows the notice, showKlaro(true) opens the modal directly -->
<button onclick={() => showKlaro()}>Cookie Settings</button>

<Klaro {config} />

Also available globally:

window.klaro.show(); // show notice
window.klaro.show(true); // show modal directly
window.klaro.hide();
window.klaro.getManager();

Loading Config from API

Load config from the KIProtect API. Two approaches:

SSR-compatible (recommended for SvelteKit)

// +layout.ts
import { loadKlaroConfig } from 'svelte-klaro';

export async function load({ fetch }) {
    const config = await loadKlaroConfig('your-privacy-manager-id', { fetch });
    return { config };
}
<!-- +layout.svelte -->
<script>
    import { Klaro } from 'svelte-klaro';
    import { de } from 'svelte-klaro/translations';
    const { data } = $props();
</script>

<Klaro config={data.config} translations={{ de }} />

Client-side (simple)

<Klaro klaroId="your-privacy-manager-id" />

Consent Tracking

When klaroId is set, svelte-klaro automatically submits consent receipts to the KIProtect API — matching the behavior of the original Klaro script. Each time the user saves their choices, a POST to /v1/privacy-managers/{id}/submit is sent with:

  • consent_data: which services were accepted/declined and what changed
  • location_data: hostname, protocol, port, and pathname (configurable)
  • user_data: client name and version

To disable this while still using klaroId for config loading:

<Klaro klaroId="your-privacy-manager-id" disableConsentTracking />

You can control whether the page pathname is included via config.records:

const config = {
    records: { savePathname: false }, // default: true
    // ...
};

SSR

svelte-klaro is SSR-safe. During server-side rendering it outputs nothing (the consent manager requires browser APIs). The consent notice appears on client hydration.

Bundle Size

The original klaro ships Preact as a runtime dependency. svelte-klaro has almost no runtime framework overhead since Svelte compiles to vanilla JS:

| | Minified | Gzipped | | ------------------------------ | -------- | ------- | | Original klaro (Preact) | 216 KB | 66 KB | | svelte-klaro (en only) | 39 KB | 12 KB | | svelte-klaro + 3 languages | 46 KB | 14 KB |

Translations are tree-shakeable — only imported languages are bundled. Each additional language adds ~2 KB minified / <1 KB gzipped.

Types

All types are exported:

import type { KlaroConfigInterface, KlaroServiceInterface, ConsentManager } from 'svelte-klaro';
import type { LoadKlaroConfigOptions } from 'svelte-klaro';

License

MIT. Based on Klaro by KIProtect.