@katla.app/sdk
v0.4.3
Published
TypeScript SDK for building custom cookie consent flows with Katla.
Downloads
723
Readme
@katla.app/sdk
TypeScript SDK for building custom cookie consent flows with Katla.
Get started:
- Create your account and site at katla.app
- Read full guides at docs.katla.app
Install
npm install @katla.app/sdkRequirements:
- Node.js 24+
- React 18+ or 19+ (only for React/Next integrations)
Basic usage
import { createKatlaClient } from '@katla.app/sdk';
const client = createKatlaClient({
siteId: 'your-site-id',
// baseUrl: 'https://dist.katla.app', // optional override
});
const cookies = await client.getCookies();
const manifest = await client.getManifest();
const unsubscribe = client.onConsentChange((consent) => {
console.log('Updated consent:', consent);
});
await client.injectGuard();
unsubscribe();React usage
import {
KatlaProvider,
useKatlaCookies,
} from '@katla.app/sdk/react';
function CookieList() {
const { cookies, loading, error } = useKatlaCookies();
if (loading) return <p>Loading...</p>;
if (error) return <p>Failed: {error.message}</p>;
if (!cookies) return null;
return <pre>{JSON.stringify(cookies.cookies, null, 2)}</pre>;
}
export function App() {
return (
<KatlaProvider siteId="your-site-id">
<CookieList />
</KatlaProvider>
);
}KatlaProvider includes KatlaGuard and ConsentBridge automatically. Individual components are still exported for advanced use cases where you need full control.
Consent UI components
The SDK ships ready-to-use <CookieBanner> and <CookieCatalog> components plus a useConsentManager hook. All components are unstyled — they render semantic HTML with stable katla-* class names so you can apply your own CSS.
Quick start
Drop in a banner and catalog with zero configuration:
import {
KatlaProvider,
CookieBanner,
CookieCatalog,
useKatlaCookies,
} from '@katla.app/sdk/react';
function CookiePage() {
const { cookies, loading, error } = useKatlaCookies();
return (
<>
<CookieCatalog data={cookies} loading={loading} error={error} />
<CookieBanner />
</>
);
}
export function App() {
return (
<KatlaProvider siteId="your-site-id">
<CookiePage />
</KatlaProvider>
);
}CookieBanner
Renders a consent banner with accept/reject/customize controls.
<CookieBanner
title="We use cookies"
description="Choose which categories you'd like to allow."
labels={{
acceptAll: 'Accept all',
rejectAll: 'Reject non-essential',
saveSelection: 'Save selection',
functionalBadge: 'Functional always on',
privacyTrigger: 'Privacy preferences',
}}
className="my-banner"
/>Props:
| Prop | Type | Default |
|------|------|---------|
| title | string | "Cookie preferences" |
| description | ReactNode | Brief consent copy |
| labels | object | See above defaults |
| className | string | — |
| children | (state: ConsentManagerState) => ReactNode | — |
When children is provided as a render prop, the default UI is replaced entirely and you receive the full ConsentManagerState:
<CookieBanner>
{({ acceptAll, rejectAll, open, setOpen, selected, toggleCategory, saveSelection }) => (
<div className="my-custom-banner">
<button onClick={acceptAll}>OK</button>
<button onClick={rejectAll}>No thanks</button>
<button onClick={() => setOpen(!open)}>Customize</button>
{/* ... */}
</div>
)}
</CookieBanner>CSS class names (for styling the default UI):
katla-banner— root<aside>katla-banner-copy— title + description wrapperkatla-banner-controls— button area in preferences panelkatla-toggle-grid— category toggle containerkatla-toggle-card— individual category togglekatla-pill— "always on" badgekatla-button-row— row of action buttonskatla-button-accept,katla-button-reject,katla-button-save,katla-button-customize— individual buttonskatla-privacy-trigger— re-open button shown after consent
CookieCatalog
Displays cookies grouped by category.
import { useKatlaCookies, CookieCatalog } from '@katla.app/sdk/react';
function CookieList() {
const { cookies, loading, error } = useKatlaCookies();
return <CookieCatalog data={cookies} loading={loading} error={error} />;
}Props:
| Prop | Type | Default |
|------|------|---------|
| data | CookieData \| null | — |
| loading | boolean | false |
| error | Error \| string \| null | — |
| maxPerCategory | number | 5 |
| className | string | — |
| emptyMessage | string | "No cookies found." |
| renderCategory | (category, cookies) => ReactNode | — |
| renderCookie | (cookie, category) => ReactNode | — |
Customize per-cookie rendering while keeping the grid layout:
<CookieCatalog
data={cookies}
loading={loading}
error={error}
maxPerCategory={10}
renderCookie={(cookie) => (
<div>
<code>{cookie.name}</code> — {cookie.domain}
</div>
)}
/>CSS class names:
katla-catalog-grid— root grid containerkatla-catalog-card— category cardkatla-catalog-card-header— card header with category name + countkatla-empty-card— shown when no cookies exist
useConsentManager
Headless hook for building fully custom consent UIs. Both CookieBanner and CookieCatalog are built on top of this.
import { useConsentManager } from '@katla.app/sdk/react';
function MyConsentUI() {
const {
ready, // true once window.KatlaConsent is available
hasDecision, // true after user has accepted/rejected
open, // preferences panel visibility
setOpen,
selected, // currently toggled-on categories
availableCategories, // categories with cookies (excludes functional/unknown)
toggleCategory,
acceptAll, // calls KatlaConsent.acceptAll() + closes panel
rejectAll, // calls KatlaConsent.rejectAll() + closes panel
saveSelection, // calls KatlaConsent.acceptCategories() + closes panel
cookies, // { data, loading, error }
} = useConsentManager();
if (!ready) return null;
return (
<div>
{!hasDecision && (
<div>
<p>We use cookies.</p>
<button onClick={acceptAll}>Accept all</button>
<button onClick={rejectAll}>Reject all</button>
</div>
)}
{open && (
<div>
{availableCategories.map((cat) => (
<label key={cat}>
<input
type="checkbox"
checked={selected.includes(cat)}
onChange={() => toggleCategory(cat)}
/>
{cat}
</label>
))}
<button onClick={saveSelection}>Save</button>
</div>
)}
</div>
);
}The ManageableCategory type ('personalization' | 'analytics' | 'marketing' | 'security') is also exported for type-safe category handling.
Next.js usage
Client provider:
import { KatlaNextProvider } from '@katla.app/sdk/next';
export default function Providers({ children }: { children: React.ReactNode }) {
return <KatlaNextProvider siteId="your-site-id">{children}</KatlaNextProvider>;
}Server-side cached fetch:
import { getCachedCookies } from '@katla.app/sdk/next/server';
export default async function Page() {
const data = await getCachedCookies({ siteId: 'your-site-id' });
return <pre>{JSON.stringify(data.cookies, null, 2)}</pre>;
}All consent UI components (CookieBanner, CookieCatalog, useConsentManager) are available from @katla.app/sdk/next and work identically to the React versions:
"use client";
import {
CookieBanner,
CookieCatalog,
useKatlaCookies,
} from '@katla.app/sdk/next';
export default function ConsentPage() {
const { cookies, loading, error } = useKatlaCookies();
return (
<>
<h1>Cookie information</h1>
<CookieCatalog data={cookies} loading={loading} error={error} />
<CookieBanner />
</>
);
}Configuration file
Create a katla.config.mjs (ESM) or katla.config.js (CJS) in your project root to set defaults for katla pull:
// katla.config.mjs
export default {
siteId: 'your-site-id',
dir: '.katla',
// locale: 'en-GB',
// format: 'full',
};// katla.config.js (CommonJS)
module.exports = {
siteId: 'your-site-id',
};| Option | Type | Default | Description |
|--------|------|---------|-------------|
| siteId | string | — | Your site's UUID |
| dir | string | '.katla' | Output directory for pulled files |
| baseUrl | string | 'https://dist.katla.app' | Override the CDN base URL |
| locale | string | — | Pull a single locale only (e.g., 'en-GB'). Omit to pull all. |
| format | string | 'full' | Policy format: 'full', 'cookie', or 'table' |
CLI flags always override config file values. With a config file, katla pull works without arguments.
Static cookie data (build-time)
CLI:
katla pull [site-id]
# Outputs: .katla/cookies.json, .katla/cookies.*.json, .katla/policy.*.json, .katla/guard.js, .katla/manifest.jsonThe site-id argument is optional when a config file is present.
Programmatic:
import { fetchStaticAll } from '@katla.app/sdk/static';
const { cookies, policies, guard, manifest } = await fetchStaticAll({
siteId: 'your-site-id',
});Use the generated cookies.json as initialCookies and guard.js as guardScript in KatlaProvider/KatlaNextProvider:
// Vite (raw import)
import cookies from './.katla/cookies.json';
import guardScript from './.katla/guard.js?raw';
<KatlaProvider siteId="your-site-id" initialCookies={cookies} guardScript={guardScript}>// Next.js (server helper)
import { getStaticGuardScript } from '@katla.app/sdk/next/server';
const guardScript = await getStaticGuardScript();
<KatlaNextProvider siteId="your-site-id" initialCookies={cookies} guardScript={guardScript}>Policies
Fetch auto-generated policy documents in any supported locale:
const client = createKatlaClient({ siteId: 'your-site-id' });
// Fetch combined cookie + privacy policy
const policy = await client.getPolicy({ locale: 'de-DE', format: 'full' });
console.log(policy.policy.markdown);
// Fetch cookie policy only
const cookiePolicy = await client.getPolicy({ format: 'cookie' });
// Fetch cookie tables only
const tables = await client.getPolicy({ format: 'table' });Formats: full (combined cookie + privacy policy), cookie (cookie policy only), table (cookie tables only).
Supported locales: en-GB, en-US, de-DE, fr-FR, es-ES, it-IT, nl-NL, pt-PT, sv-SE, nb-NO, da-DK, pl-PL, fi-FI.
Build-time fetch (all locales):
import { fetchStaticAll } from '@katla.app/sdk/static';
const { cookies, policies, manifest } = await fetchStaticAll({
siteId: 'your-site-id',
// locale: 'de-DE', // optional, omit to pull all locales
// format: 'full', // optional, default
});CLI (katla pull fetches cookies + policies for all locales by default):
katla pull [site-id]
# Outputs: .katla/cookies.json, .katla/cookies.*.json, .katla/policy.*.json, .katla/guard.js, .katla/manifest.json
katla pull [site-id] --locale de-DE --format full
# Outputs: .katla/cookies.json, .katla/cookies.de-de.json, .katla/policy.de-de.json, .katla/guard.js, .katla/manifest.jsonCCPA / GPC support
Check if the visitor's browser has Global Privacy Control enabled and handle CCPA opt-outs:
import { isGPCEnabled } from '@katla.app/sdk';
if (isGPCEnabled()) {
// Browser has GPC enabled — honor opt-out
window.KatlaConsent?.optOutOfSale();
}
// Check active regulation
window.KatlaConsent?.getRegulation(); // 'gdpr' or 'ccpa'Documentation
- Product onboarding: katla.app
- Developer docs: docs.katla.app
