---
title: Policy Packs
description: Configure regional consent policies in the headless JavaScript runtime — hosted mode, presets, and offline fallback.
---
Policy packs configure how c15t handles regional consent in the headless runtime. When connected to a backend, the runtime receives the resolved policy automatically via the `/init` response. For local development, testing, previews, or temporary outage fallback, you can pass policies directly and c15t resolves them locally.

## Hosted Runtime (Recommended)

Point the runtime at your backend — policy resolution happens server-side:

```ts
import { getOrCreateConsentRuntime } from 'c15t';

const { consentStore } = getOrCreateConsentRuntime({
  backendURL: 'https://your-instance.c15t.dev',
});

const state = consentStore.getState();
console.log(state.policy?.id);
console.log(state.policyDecision?.matchedBy);
```

Configure your presets on the backend side. The frontend receives the resolved policy with no client-side policy config required.

## Offline / Fallback

For local development, demos, automated tests, or as a resilience fallback during a temporary outage, pass presets directly:

```ts
import {
  getOrCreateConsentRuntime,
  policyPackPresets,
} from 'c15t';

const { consentStore } = getOrCreateConsentRuntime({
  mode: 'offline',
  offlinePolicy: {
    policyPacks: [
      policyPackPresets.europeOptIn(),
      policyPackPresets.californiaOptOut(),
      policyPackPresets.worldNoBanner(),
    ],
  },
  overrides: {
    country: 'US',
    region: 'CA',
  },
});

const state = consentStore.getState();
console.log(state.policy?.id);       // → 'policy_ca_opt_out'
console.log(state.policyDecision?.matchedBy); // → 'region'
```

## Custom Pack

```ts
const { consentStore } = getOrCreateConsentRuntime({
  mode: 'offline',
  offlinePolicy: {
    policyPacks: [
      {
        id: 'eu',
        match: { countries: ['DE', 'FR', 'IT'] },
        consent: { model: 'opt-in', categories: ['necessary', 'measurement', 'marketing'] },
        ui: { mode: 'banner' },
      },
      {
        id: 'default',
        match: { isDefault: true },
        consent: { model: 'none' },
        ui: { mode: 'none' },
      },
    ],
  },
  overrides: { country: 'DE' },
});
```

## Runtime Shape

Offline policy resolution is configured directly on `offlinePolicy`:

```ts
const runtime = getOrCreateConsentRuntime({
  mode: 'offline',
  offlinePolicy: {
    policyPacks: [...],
  },
});
```

## Fallback Rules

| Configuration                        | Result                                                                   |
| ------------------------------------ | ------------------------------------------------------------------------ |
| `offlinePolicy.policyPacks` omitted  | Synthetic opt-in fallback banner (also used for hosted network fallback) |
| `offlinePolicy: { policyPacks: [] }` | Explicit no-banner mode                                                  |
| Non-empty pack, no match, no default | Explicit no-banner mode                                                  |

The omitted-config fallback is intentionally conservative: if the backend is unreachable or a local preview forgets to pass `offlinePolicy`, c15t still shows an opt-in banner instead of silently dropping consent UI.

## When to Use Offline Mode

* Local demos and prototypes
* Storybook or playground environments
* Automated tests that need deterministic policy resolution
* Framework wrappers built on top of `c15t`
* Resilience fallback when the backend is temporarily unreachable

For production apps, keep the canonical pack on the backend and use offline policies only for development, testing, previews, or outage fallback.

> ℹ️ **Info:**
> For the full concept model (matchers, scope modes, re-prompting), see Policy Packs concepts. For backend setup, see the self-host guide.
