Skip to main content

Nuxt

Components

Component reference

Every component reads the consent runtime the Nuxt module creates, and each imports its own styles. The module registers the components marked Global, so you use them in templates without an import. Import the others by path.

ComponentIn NuxtWhat it renders
ConsentRootGlobalThe banner, rendered on the server, and the preference dialog once opened. Switches to the IAB surfaces under an IAB policy when iab is set.
ConsentWidgetGlobalCategory switches and save actions inline, for a privacy page.
ConsentDialogLinkGlobalA button that opens preferences.
ConsentDialogTriggerGlobalA floating, draggable button that opens preferences.
ConsentGateGlobalIts default slot while a category is allowed, otherwise its placeholder slot.
ConsentBannerc15t/vue/runtime/components/consent-banner.vueThe first-layer banner on its own.
ConsentManagerc15t/vue/runtime/components/consent-manager.vueThe preference dialog on its own.
IABConsentBannerc15t/vue/runtime/components/iab-consent-banner.vueThe IAB TCF first layer.
IABConsentDialogc15t/vue/runtime/components/iab-consent-dialog.vueThe IAB TCF preference centre.
ConsentDevToolsc15t/vue/devtoolsA development panel for the consent runtime.

Import the path components inside a Nuxt component's <script setup>:

import ConsentBanner from 'c15t/vue/runtime/components/consent-banner.vue';

ConsentRoot or the parts

ConsentRoot renders ConsentBanner and ConsentManager, or the IAB components when iab is set, for the visitor's policy. Mount ConsentRoot, or mount the parts, never both, or the visitor sees two banners. Always use the global ConsentRoot in Nuxt, not the one c15t/vue/vue-plugin exports. The global one renders the banner on the server. The module writes theme tokens into the page head whether you mount ConsentRoot or the parts.

Use the components in Vue Vapor

Nuxt 4.6 and later can compile your components with Vue Vapor. Vapor needs Vue 3.6, which is a release candidate, so install vue 3.6 alongside Nuxt and turn on vue.vapor:

nuxt.config.ts
export default defineNuxtConfig({
	c15t: { backendURL: 'https://your-project.inth.app' },
	modules: ['c15t/vue'],
	// Vapor needs Vue 3.6. Opt components in with `<script setup vapor>`.
	vue: { vapor: true },
});

Mark a page or component with <script setup vapor> to compile it with Vapor. c15t's components stay on the virtual DOM, and Nuxt renders them inside Vapor components through its interop layer. Mount ConsentRoot in a Vapor app.vue, pass slots to ConsentGate or ConsentDialogLink, and call the composables in a Vapor <script setup>, as you would elsewhere:

app/components/VideoEmbed.vue
<!-- A Vapor component passing both slots to ConsentGate. -->
<script setup vapor lang="ts"></script>

<template>
	<ConsentGate category="measurement">
		<iframe
			src="https://www.youtube-nocookie.com/embed/czTksCF6X8Y"
			title="YouTube video"
			loading="lazy"
			allowfullscreen
		/>
		<template #placeholder>
			<p>Allow measurement to load this YouTube video.</p>
			<ConsentDialogLink>Choose video permissions</ConsentDialogLink>
		</template>
	</ConsentGate>
</template>

Vapor does not make the banner or the preference dialog faster, because they still render with the virtual DOM. The interop layer ships the Vapor runtime next to the virtual DOM one, so expect more JavaScript, not less: the /consent-example page of internals/fixtures/nuxt-vapor downloads about 18% more JavaScript than the same app without Vapor.

Building blocks

The stock surfaces are built from smaller components that the package also exports under c15t/vue/runtime/components/: consent-button.vue, consent-switch.vue, consent-actions.vue, consent-link.vue, consent-legal-links.vue, consent-description.vue, consent-tag.vue and consent-branding-icon.vue. For consent UI in your own markup, use the headless composables instead. They give you the policy's actions and the draft state without the stock markup.