---
title: DevTools
description: Inspect consent, scripts, location and events in a Svelte app with
  ConsentDevTools from @c15t/svelte/devtools, loaded only in development.
group: frameworks
lastModified: "2026-10-10T16:01:45+01:00"
---
## Add the panel in development

Render `ConsentDevTools` inside `ConsentProvider`, and load it only in
development. Vite sets `import.meta.env.DEV` to `true` in `vite dev` and to
`false` in a production build, which then drops the import:

```svelte title="src/lib/ConsentDevTools.svelte"
<script lang="ts">
	const devTools = import.meta.env.DEV ? import('@c15t/svelte/devtools') : null;
</script>

{#if devTools}
	{#await devTools then { ConsentDevTools }}
		<ConsentDevTools />
	{/await}
{/if}
```

Render `<ConsentDevTools />` from that file anywhere inside the provider. The
export is also available as `DevTools` and `C15TDevTools`.

## What the panel shows

The panel is a floating inspector for the provider's consent runtime. Its
tabs:

|Tab|Shows|
|--|--|
|`consents`|Effective permissions and the recorded choice per category, with switches to stage and save a test choice.|
|`scripts`|Each registered script and its loading state.|
|`location`|The country, region and language the policy resolved for, with overrides to test another location.|
|`policy`|The resolved policy rule, its model, prompt, scope and rights.|
|`iab`|The TCF state, when IAB is on.|
|`events`|The consent runtime's events and script lifecycle events.|
|`actions`|Buttons to open the banner or dialog, reset the draft, clear stored records and resolve the policy again.|

Clearing records from the panel deletes the stored choice through the
provider's storage settings, so a custom `storageConfig` is respected.
Location overrides from the panel change the current page only.

## Props

|Prop|Type|Default|Behavior|
|--|--|--|--|
|`position`|`'bottom-right'`, `'bottom-left'`, `'top-right'` or `'top-left'`|`'bottom-right'`|Corner of the panel's toggle.|
|`defaultOpen`|`boolean`|`false`|Opens the panel on load.|
|`defaultTab`|one of the tabs above|`'consents'`|The tab it opens on.|
|`maxEvents`|`number`|`100`|How many events the `events` tab keeps.|
|`getConsentCategories`|`() => AllConsentNames[]`|the provider's categories|Categories the `consents` tab lists.|
|`getPresentation`|`() => ConsentPresentation`|the provider's `presentation`|Presentation used for the panel's diagnostics.|
|`clearRecords`|`() => void`|the provider's own|Replaces what the clear action does.|
|`shadow`|`boolean`|`true`|`false` mounts the panel without a shadow root.|

By default the panel renders inside a shadow root with its own stylesheet,
so your CSS does not restyle it and its CSS does not leak into the page.
`shadow={false}` mounts the panel in the light DOM instead and puts its
stylesheet in `<head>`.

## Open DevTools from the consent trigger

While `ConsentDialogTrigger` is visible, it becomes a two-button toolbar with
a DevTools button, and DevTools hides its own floating launcher, so one
control occupies the corner. The DevTools button sits at the end of the
toolbar farthest from its corner. The panel opens just past the toolbar,
aligned with its outer edge, and follows it when a visitor drags the toolbar
to another corner. `position` applies again once no trigger is visible. The
trigger that `ConsentDialog`'s `showTrigger` prop renders behaves the same
way.

DevTools brings its launcher back whenever no trigger is visible, for example
with `showWhen="never"` or while the dialog is open. A production build that
loads DevTools only in development shows no DevTools button in the trigger.

## Keep it out of production

The panel can clear consent and change the location the policy resolves for.
Render it in development only. Importing `@c15t/svelte/devtools` statically
puts the panel in every bundle that imports the file, so import it
dynamically behind a development check, as the example above does.
