Component Previews
Component previews allow Vue components to be rendered in isolation in external contexts, such as the Drupal Canvas editor. This enables editors to see live previews of components directly in the page builder.
nuxt-component-preview implements this for Nuxt/Vue. It enables previewing components in external contexts and auto-generates a component index for Drupal Canvas integration.
If you are using the Nuxt Starter or nuxtjs-drupal-ce, the module is already pre-configured — no setup needed.
Component Index
The module auto-generates a component index at /nuxt-component-preview/component-index.json, listing all global components with their metadata and prop schemas. This is what Canvas External JS Components (a Canvas extension for integrating external JavaScript components) reads to populate the Canvas editor.
Only global components are included. Components in components/global/ are automatically global; others can be registered with global: true in nuxt.config.ts.
Grouping Components by Folder
A recommended pattern is to keep Canvas components in a dedicated components/Canvas/ folder and derive categories from subfolder names:
components: [
{ path: '~/components/Canvas', global: true, pathPrefix: false, prefix: '' },
{ path: '~/components/global', global: true },
'~/components',
],
componentPreview: {
componentIndex: {
// Derive Canvas component categories from folder names (Base/, Layout/, Card/, Hero/)
category: { directory: true, fallback: 'Misc' },
},
},
For working examples, see the Canvas components in the Lupus Decoupled Nuxt Starter.
JSDoc Metadata
Both components and their props are documented via TypeScript, with JSDoc annotations used to provide additional metadata that TypeScript alone cannot express. The pattern is consistent: a label (display name) and an optional description, plus additional tags.
Component Metadata
Define component-level metadata via a JSDoc comment at the top of <script setup>:
<script setup lang="ts">
/**
* Hero Billboard
* @description A full-width hero section with background image and overlay.
* @category Hero
* @status stable
*/
</script>
| Tag | Description |
|---|---|
| First line | Label / display name (falls back to auto-generated from PascalCase) |
@description | Component description shown in the editor |
@category | Category override (alternative to directory-based) |
@status | experimental, stable, deprecated, or obsolete |
All fields are optional. Config-level overrides take priority over JSDoc.
Prop Metadata
Props follow the same pattern — a label and description, plus additional tags for editor behavior:
<script setup lang="ts">
withDefaults(defineProps<{
/**
* Button label text
* @example Submit
*/
label?: string
/**
* Button variant
* @enumLabels {"large": "Extra Large (XL)"}
*/
variant?: 'primary' | 'secondary' | 'large'
}>(), {
label: 'Click me',
variant: 'primary'
})
</script>
The prop label is auto-generated from the first JSDoc line or prop name. Use @title to override.
| Tag | Description |
|---|---|
@title | Explicit label override |
@example | Adds example values (multiple allowed) |
@enumLabels | Custom labels for enum values, e.g. {"large": "Extra Large (XL)"} |
@contentMediaType text/html | Enables rich text editing in Canvas for string props |
@formattingContext block|inline | Controls formatting context (default: block) |
@schemaRef | Reference Canvas JSON schema definitions (e.g. canvas/stream-wrapper-uri) |
@format | JSON Schema format for semantic validation and UI widgets: date, date-time, time, duration, email, hostname, ipv4, ipv6, uuid, uri, uri-reference, etc. |
@pattern | JSON Schema regex pattern for string validation |
@allowed-schemes | Allowed URI schemes for Canvas field type detection (e.g. public or http, https) |
Drupal Canvas Types
For Drupal Canvas integration, special TypeScript types are available that generate JSON schemas enabling Canvas UI features like media library selection. These types are auto-imported by Nuxt.
| Type | Description |
|---|---|
CanvasImage | Image with media library integration (src, alt, width, height) |
CanvasVideo | Video with poster support |
Example usage:
<script setup lang="ts">
/**
* Hero Banner
*/
defineProps<{
/**
* Background image
* @example src=https://example.com/hero.jpg alt="Hero" width=1200 height=600
*/
image: CanvasImage
}>()
</script>
The @example for Canvas types supports two formats:
- Key-value:
src=https://... alt="text" width=800 height=600 - JS object:
{ src: 'https://...', alt: 'text', width: 800 }
Schema References
For advanced use cases, @schemaRef allows referencing Canvas JSON schema definitions directly, useful for types like stream-wrapper-uri and stream-wrapper-image-uri. Use the shorthand prefix/name notation:
/**
* @schemaRef canvas/stream-wrapper-uri
*/
imageUri?: string
This expands to json-schema-definitions://canvas.module/stream-wrapper-uri.
Manual Setup
If you are not using the Nuxt Starter or nuxtjs-drupal-ce, install and configure the module manually.
Install the module:
npm install nuxt-component-preview
Add it to nuxt.config.ts and add <ComponentPreviewArea /> to app.vue:
export default defineNuxtConfig({
modules: ['nuxt-component-preview'],
})
<template>
<ComponentPreviewArea v-if="useRuntimeConfig().public.componentPreview" />
<NuxtPage v-else />
</template>
When embedding previews from a different domain (e.g. a Drupal backend), disable the app manifest in development to avoid relative URL failures:
$development: {
experimental: {
appManifest: false
}
}
For CORS configuration, see the nuxt-component-preview CORS setup. When using nuxtjs-drupal-ce, CORS is configured automatically.