Skip to main content
The @katla.app/sdk/react entry point provides React components and hooks for managing cookies and consent. Use it with Vite, Create React App, or any client-side React setup.
For Next.js projects, use the Next.js guide instead — it provides a streamlined setup for the App Router.

Prerequisites

Setup

Wrap your app with KatlaProvider:
import { KatlaProvider } from '@katla.app/sdk/react';

function App() {
  return (
    <KatlaProvider siteId="your-site-id">
      {/* Your app */}
    </KatlaProvider>
  );
}
KatlaProvider includes KatlaGuard and ConsentBridge automatically. To enable Google Consent Mode, pass the googleConsentMode prop:
<KatlaProvider siteId="your-site-id" googleConsentMode>
  {/* Your app */}
</KatlaProvider>
ComponentPurpose
KatlaProviderCreates the SDK client and makes it available to hooks
KatlaGuardInjects the cookie guard script that blocks non-consented cookies
ConsentBridgeConnects window.KatlaConsent events to the React consent state
GoogleConsentModeSignals consent state to Google Analytics/Ads via Google Consent Mode v2

KatlaProvider props

PropTypeDefaultDescription
siteIdstringYour site’s UUID (required)
baseUrlstringhttps://dist.katla.appOverride the CDN base URL
localePolicyLocaleDefault locale for policy documents (e.g., en-GB, de-DE, sv-SE). When set, all policy fetches use this locale unless overridden.
debugbooleanfalseEnable console logging
initialCookiesCookieData | nullPre-fetched cookie data. When provided, useKatlaCookies() skips the runtime fetch.
guardScriptstringPre-fetched guard script content. When provided, the guard is inlined instead of fetched from the CDN.
guardbooleantrueInject the cookie guard script that blocks non-consented cookies
consentBridgebooleantrueConnect window.KatlaConsent events to the React consent state
googleConsentModebooleanfalseSignal consent state to Google Analytics/Ads via Google Consent Mode v2

Hooks

useKatlaCookies

Fetches your site’s cookie data on mount.
import { useKatlaCookies } from '@katla.app/sdk/react';

function CookieList() {
  const { cookies, loading, error } = useKatlaCookies();

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;
  if (!cookies) return null;

  return (
    <ul>
      {Object.entries(cookies.cookies).map(([category, list]) => (
        <li key={category}>
          {category}: {list.length} cookies
        </li>
      ))}
    </ul>
  );
}
Return fieldTypeDescription
cookiesCookieData | nullCookie data grouped by category
loadingbooleantrue while fetching
errorError | nullFetch error, if any

useKatlaConsent

Tracks the visitor’s current consent state in real time.
import { useKatlaConsent } from '@katla.app/sdk/react';

function ConsentStatus() {
  const { consent } = useKatlaConsent();

  if (!consent) return <p>No consent recorded yet.</p>;

  return (
    <ul>
      {Object.entries(consent).map(([category, allowed]) => (
        <li key={category}>
          {category}: {allowed ? 'Allowed' : 'Declined'}
        </li>
      ))}
    </ul>
  );
}
Return fieldTypeDescription
consentConsentState | nullCurrent consent per category, or null if none
onChange(callback) => () => voidSubscribe to consent changes; returns unsubscribe

useKatlaClient

Returns the underlying KatlaClient instance for direct API access.
import { useKatlaClient } from '@katla.app/sdk/react';

function ManifestLoader() {
  const client = useKatlaClient();

  async function loadManifest() {
    const manifest = await client.getManifest();
    console.log(manifest);
  }

  return <button onClick={loadManifest}>Load manifest</button>;
}

useConsentManager

Headless hook that combines cookie data, consent state, and window.KatlaConsent actions into a single API. Use it to build fully custom consent UIs without boilerplate.
import { useConsentManager } from '@katla.app/sdk/react';

function MyConsentUI() {
  const {
    ready,               // true once window.KatlaConsent is available
    hasDecision,         // true after the visitor 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() and closes the panel
    rejectAll,           // calls KatlaConsent.rejectAll() and closes the panel
    saveSelection,       // calls KatlaConsent.acceptCategories() and closes the 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>
          <button onClick={() => setOpen(true)}>Customize</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>
  );
}
Return fieldTypeDescription
readybooleantrue once window.KatlaConsent is available
hasDecisionbooleantrue after the visitor has made a consent choice
openbooleanWhether the preferences panel is visible
setOpen(open: boolean) => voidToggle the preferences panel
selectedManageableCategory[]Currently selected categories
availableCategoriesManageableCategory[]Categories that have cookies (excludes functional and unknown)
toggleCategory(cat: ManageableCategory) => voidToggle a category on/off
acceptAll() => voidAccept all categories and close the panel
rejectAll() => voidReject non-essential categories and close the panel
saveSelection() => voidSave selected categories and close the panel
cookies{ data, loading, error }Cookie data from useKatlaCookies()
The ManageableCategory type ('personalization' | 'analytics' | 'marketing' | 'security') is also exported for type-safe category handling.

Components

CookieBanner

A ready-to-use consent banner with accept, reject, and per-category customization. The component is unstyled — it renders semantic HTML with stable katla-* class names you can target with your own CSS.
import { CookieBanner } from '@katla.app/sdk/react';

function App() {
  return (
    <KatlaProvider siteId="your-site-id">
      <CookieBanner />
    </KatlaProvider>
  );
}
Customize labels and copy:
<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"
/>
PropTypeDefaultDescription
titlestring"Cookie preferences"Banner heading
descriptionReactNodeBrief consent copyDescriptive text below the title
labelsobjectSee aboveButton and badge labels
classNamestringAdditional class on the root element
children(state: ConsentManagerState) => ReactNodeRender prop for full UI override
For a fully custom UI, use the children render prop. The default markup is replaced entirely:
<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:
ClassElement
katla-bannerRoot <aside>
katla-banner-copyTitle and description wrapper
katla-banner-controlsButton area in the preferences panel
katla-toggle-gridCategory toggle container
katla-toggle-cardIndividual category toggle
katla-pill”Always on” badge
katla-button-rowRow of action buttons
katla-button-acceptAccept button
katla-button-rejectReject button
katla-button-saveSave selection button
katla-button-customizeCustomize button
katla-privacy-triggerRe-open button (shown after consent)

CookieCatalog

Displays your site’s cookies grouped by category. Also unstyled with katla-* class names.
import { useKatlaCookies, CookieCatalog } from '@katla.app/sdk/react';

function CookieList() {
  const { cookies, loading, error } = useKatlaCookies();
  return <CookieCatalog data={cookies} loading={loading} error={error} />;
}
PropTypeDefaultDescription
dataCookieData | nullCookie data from useKatlaCookies()
loadingbooleanfalseShow loading state
errorError | string | nullShow error state
maxPerCategorynumber5Max cookies shown per category
classNamestringAdditional class on the root element
emptyMessagestring"No cookies found."Message when no cookies exist
renderCategory(category, cookies) => ReactNodeOverride a full category section
renderCookie(cookie, category) => ReactNodeOverride a single cookie row
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:
ClassElement
katla-catalog-gridRoot grid container
katla-catalog-cardCategory card
katla-catalog-card-headerCard header with category name and count
katla-empty-cardShown when no cookies exist
The fastest way to add a consent banner is with the <CookieBanner> component — it handles all the consent logic out of the box. For full control, use the useConsentManager hook or call window.KatlaConsent methods directly.
window.KatlaConsent is provided by the guard script. It becomes available after KatlaGuard mounts and the script loads. The ConsentBridge component handles polling for it and relaying events to React.

Static cookies (build-time)

Use the Katla CLI to fetch cookie data at build time, then pass it as static data — no runtime fetch needed. 1. Add to your build pipeline:
{
  "scripts": {
    "prebuild": "katla pull your-site-id",
    "build": "vite build"
  }
}
2. Import and pass to the provider:
import cookies from './.katla/cookies.json';
import { KatlaProvider } from '@katla.app/sdk/react';

function App() {
  return (
    <KatlaProvider siteId="your-site-id" initialCookies={cookies}>
      {/* useKatlaCookies() returns data immediately — no fetch */}
    </KatlaProvider>
  );
}
See the SDK overview for CLI reference and the programmatic API.

Server-side rendering (SSR)

If your framework supports server-side rendering (Remix, Astro, etc.), fetch cookies on the server and pass them to the provider to avoid a client-side network request:
// Server-side (e.g. Remix loader)
import { createKatlaClient } from '@katla.app/sdk';

const client = createKatlaClient({ siteId: 'your-site-id' });
const cookies = await client.getCookies();
// Client component
import { KatlaProvider } from '@katla.app/sdk/react';

function App({ cookies }) {
  return (
    <KatlaProvider siteId="your-site-id" initialCookies={cookies}>
      {/* useKatlaCookies() returns data immediately — no fetch */}
    </KatlaProvider>
  );
}
The guard script and consent bridge still run client-side. Only the cookie data fetch is moved to the server.

Debug mode

Pass debug to KatlaProvider to log SDK activity to the browser console:
<KatlaProvider siteId="your-site-id" debug>

Full example

A minimal Vite + React app with cookie catalog and consent banner:
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import {
  KatlaProvider,
  CookieBanner,
  CookieCatalog,
  useKatlaCookies,
} from '@katla.app/sdk/react';

function App() {
  const { cookies, loading, error } = useKatlaCookies();

  return (
    <div>
      <h1>Cookie consent</h1>
      <CookieCatalog data={cookies} loading={loading} error={error} />
      <CookieBanner />
    </div>
  );
}

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <KatlaProvider siteId="your-site-id" debug>
      <App />
    </KatlaProvider>
  </StrictMode>,
);

Examples

Dynamic fetching

Vite + React app that fetches cookies and policy at runtime.

Build-time static

Vite + React app using katla pull for build-time cookie data.

Custom consent UI

Vite + React app with a fully custom consent UI using useConsentManager.