@lars-plate/nuxt-delta-client
v0.0.8
Published
Nuxt module for Delta Client
Readme
@platecms/nuxt-delta-client
Nuxt module that wires Plate CMS Delta into your Nuxt app: runtime configuration, Vue plugin setup, building-block auto-registration, and optional editor, preview, and component-dev routes.
Built on @platecms/delta-client and @platecms/delta-client-vue.
Features
- Registers the Delta Vue plugin with TanStack Vue Query
- Exposes
environment,token, andversionvia NuxtruntimeConfig.public.delta - Auto-imports Delta composables and registers Delta Vue components globally
- Glob-registers Vue building blocks from
app/blocks - Loads building-block JSON schemas from
delta/building-blocks/at runtime - Optional routes for live content, in-CMS editor iframe, preview iframe, and local component showcase
Requirements
- Nuxt 4+
- Node 18+
- A Plate CMS project with Delta CLI output (
delta/,app/blocks/,delta-types.d.ts)
Installation
Install the module and its peer dependencies:
pnpm add @platecms/nuxt-delta-client @platecms/delta-client @platecms/delta-client-vuenpm install @platecms/nuxt-delta-client @platecms/delta-client @platecms/delta-client-vueyarn add @platecms/nuxt-delta-client @platecms/delta-client @platecms/delta-client-vueOr with the Nuxt module helper:
npx nuxt module add @platecms/nuxt-delta-clientThen add the module to nuxt.config.ts:
export default defineNuxtConfig({
modules: ['@platecms/nuxt-delta-client'],
delta: {
environment: process.env.DELTA_ENVIRONMENT ?? 'dev',
token: process.env.DELTA_TOKEN,
version: process.env.DELTA_VERSION ?? 'v0',
},
})Configuration
The module is configured under the delta key in nuxt.config.ts (configKey: 'delta').
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| environment | string | 'dev' | Delta API environment (e.g. dev, staging, prod) |
| token | string | undefined | API token for content fetches (prefer env vars) |
| version | string | 'v0' | Content version label passed to the client |
| editor | boolean | false | Enable /editor/* route for CMS editor iframe |
| preview | boolean | false | Enable /preview/* route for CMS preview iframe |
| components | boolean | false | Enable /components dev routes for isolated block preview |
Full example
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@platecms/nuxt-delta-client'],
delta: {
environment: process.env.DELTA_ENVIRONMENT,
token: process.env.DELTA_TOKEN,
version: process.env.DELTA_VERSION ?? 'v0',
// Development helpers (disable in production unless needed)
editor: true,
preview: true,
components: true,
},
})Environment variables
# .env
DELTA_ENVIRONMENT=dev
DELTA_TOKEN=your-api-token
DELTA_VERSION=v0Values are merged into useRuntimeConfig().public.delta and injected into the Delta Vue plugin.
Project layout
After running the Delta CLI in your Nuxt app, you typically have:
my-nuxt-app/
├── app/
│ └── blocks/ # Vue building-block components
│ ├── RootBuildingBlock.vue
│ ├── HeroBuildingBlock.vue
│ └── index.ts # Generated slug → component map
├── delta/
│ ├── building-blocks/ # JSON schemas (synced from CMS)
│ │ └── root.json
│ └── content-types/ # Content type definitions
│ └── page.json
├── delta.config.ts # Delta CLI config (theme, paths, token)
├── delta-types.d.ts # Generated TypeScript for Content.* types
└── nuxt.config.tsdelta.config.ts
Used by the Delta CLI (not read directly by this Nuxt module). Example:
export type DeltaConfig = {
directories: {
components: string
content: string
}
theme: {
name: string
prn: string
}
token?: string
}
const config: DeltaConfig = {
directories: {
components: 'app/blocks',
content: 'delta',
},
theme: {
name: 'My Theme',
prn: 'prn:plate-dev:…:cms:theme:…',
},
token: process.env.DELTA_TOKEN,
}
export default configBuilding-block registry (app/blocks/index.ts)
Generated by the Delta CLI. Maps CMS slugs to Vue component names:
// Autogenerated by the Delta CLI. DO NOT MODIFY OR REMOVE.
export const components = {
root: 'RootBuildingBlock',
'smart-text': 'SmartTextBuildingBlock',
hero: 'HeroBuildingBlock',
}The module registers all *.vue files under app/blocks as global components and uses this map with useDeltaComponents().
Building blocks
Each building block is a Vue SFC. Use generated types from delta-types.d.ts for typed data props.
<!-- app/blocks/RootBuildingBlock.vue -->
<template>
<section data-building-block-slug="root">
<h1>{{ data.title }}</h1>
</section>
</template>
<script setup lang="ts">
import type { BuildingBlock } from '@platecms/delta-client/schema'
import type { Content } from '@platecms/delta-client'
defineProps<{
buildingBlock: BuildingBlock
data: Content.RootBuildingBlock
}>()
</script>data-building-block-slugshould match the block slug in the CMS.buildingBlockis the block metadata from the API.datais the resolved field content, typed per block inContent.*.
JSON definitions live in delta/building-blocks/<slug>.json and are loaded by the module’s blockLoader when the Delta Vue plugin needs schema metadata.
Routes
The module extends Nuxt pages automatically:
| Route | Enabled when | Purpose |
|-------|----------------|---------|
| /:pathMatch(.*)* | Always | Fetches and renders a content experience for the current URL path |
| /editor/:pathMatch(.*)* | delta.editor: true | Iframe target for the CMS editor (window connector) |
| /preview/:pathMatch(.*)* | delta.preview: true | Iframe target for preview mode |
| /components | delta.components: true | Lists all building blocks with placeholders |
| /components/:slug | delta.components: true | Renders a single building block in isolation |
The catch-all content route is registered last so more specific app routes (e.g. /about) can take precedence if you define them in your own pages/ directory.
Content experience (production)
ContentExperienceView uses the current route path to load CMS content:
<!-- Provided by the module at runtime -->
<script setup lang="ts">
const { data, error } = useDeltaFetchContentExperienceByPath(useRoute().path)
</script>
<template>
<DeltaContentExperienceComponent
v-if="data"
:content-experience="data"
:root-experience-component="data.experienceComponent"
/>
<p v-if="error">Error: {{ error.message }}</p>
</template>Visit /, /blog/my-post, or any path that exists in your CMS; the module resolves the matching content experience.
Editor & preview (CMS iframe)
When editor or preview is enabled, the app listens for messages from the parent CMS window via useDeltaClientConnector() and renders incoming ContentExperience / ExperienceComponent payloads.
Point your Plate CMS theme settings at:
- Editor URL:
https://your-app.example/editor - Preview URL:
https://your-app.example/preview
Component showcase (local dev)
With components: true:
- Open
/componentsto see every registered block with placeholder data. - Open
/components/root(or any slug) to work on one block without CMS content.
Auto-imports
The module registers these composables (from @platecms/delta-client-vue):
| Composable | Description |
|------------|-------------|
| useDeltaClientConnector | Window messaging between Nuxt app and CMS parent frame |
| useDeltaComponents | Resolves slug → Vue component map from app/blocks/index.ts |
| useDeltaFetchContentExperienceByPath | Fetches content experience by URL path (Vue Query) |
And these components (also from @platecms/delta-client-vue):
| Component | Description |
|-----------|-------------|
| DeltaContentExperienceComponent | Renders a full content experience tree |
| ExperienceComponentComponent | Renders a single experience component node |
| DeltaBuildingBlockComponent | Renders one building block (used in /components) |
| DeltaGridPlacementComponent | Renders grid placement / layout regions |
Use them in any page or component without manual imports.
Custom pages
You can build your own routes and still use Delta primitives:
<!-- pages/custom.vue -->
<script setup lang="ts">
import { components as blocks } from '~/blocks'
const { components } = useDeltaComponents(blocks)
provide('components', components)
const { data } = useDeltaFetchContentExperienceByPath('/my-custom-path')
</script>
<template>
<DeltaContentExperienceComponent
v-if="data"
:content-experience="data"
:root-experience-component="data.experienceComponent"
/>
</template>provide('components', components) is required so nested Delta components can resolve building-block Vue components.
Runtime config
Access Delta settings anywhere in the app:
const { environment, token, version } = useRuntimeConfig().public.deltaThe Nuxt plugin also provides delta-config on the Vue app for packages that read it via inject.
TypeScript
Commit the generated delta-types.d.ts from the Delta CLI. It augments @platecms/delta-client with project-specific Content.* interfaces:
// delta-types.d.ts (excerpt — generated, do not edit by hand)
declare module '@platecms/delta-client' {
namespace Content {
export interface RootBuildingBlock {
title: string
}
}
}Run pnpm run test:types (in this repo) or vue-tsc --noEmit in your app to verify block props against generated types.
Development workflow
- Configure
delta.config.tsand authenticate the Delta CLI. - Pull or sync schemas: building blocks and content types under
delta/. - Generate or update
app/blocks/*.vue,app/blocks/index.ts, anddelta-types.d.ts. - Run
nuxt devwithDELTA_TOKENset. - Use
/components(if enabled) to iterate on blocks; use/editorand/previewwhen testing inside the CMS.
Module development
This repository includes a playground/ Nuxt app that consumes the module from ../src/module.
# Install dependencies
pnpm install
# Build stubs and prepare playground
pnpm run dev:prepare
# Start playground
pnpm run dev
# Lint & test
pnpm run lint
pnpm run testRelated packages
| Package | Role |
|---------|------|
| @platecms/delta-client | Core client, GraphQL types, window connector |
| @platecms/delta-client-vue | Vue components and composables |
| @platecms/nuxt-delta-client | This module — Nuxt integration layer |
