contentstack
nuxt-contentstack

用于 Nuxt 的 Contentstack 集成

Nuxt Contentstack

Nuxt Contentstack

npm versionnpm downloadsLicenseNuxt

用于 Nuxt 的 Contentstack 集成。

注意:这是一个由 @timbenniks 维护的开源项目,而不是 Contentstack 团队官方维护的包。支持请求可以通过 Github issues 和直接渠道联系 @timbenniks。

功能

  • 完整的 Vue Composables 集(条目、资产、按 URL)
  • 高级筛选、分页和排序
  • 支持实时预览和可视化构建器
  • 支持服务器端中间件的个性化功能
  • 使用 useImageTransform Composables 进行图像转换
  • 与 @nuxt/image 集成,实现自动优化
  • 支持 TypeScript,提供完整的类型安全
  • 公开的 SDK:交付 SDK、实时预览工具 SDK、个性化 SDK

快速设置

npx nuxi module add nuxt-contentstack
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ["nuxt-contentstack"],

  "nuxt-contentstack": {
    // Required
    apiKey: "your_contentstack_api_key",
    deliveryToken: "your_delivery_token",
    environment: "your_environment",

    // Optional
    region: "eu", // 'us' | 'eu' | 'au' | 'azure-na' | 'azure-eu' | 'gcp-na' | 'gcp-eu'
    branch: "main",
    locale: "en-us",

    // Live Preview
    livePreview: {
      enable: true,
      previewToken: "your_preview_token",
      editableTags: true,
      editButton: true, // or object with enable, position, exclude, includeByQueryParameter
      mode: "builder", // 'builder' | 'preview'
      ssr: false,
    },

    // Personalization
    personalization: {
      enable: true,
      projectUid: "your_project_uid",
    },

    debug: true,
  },
});

配置

核心设置

选项类型必需默认描述
apiKeystring-Contentstack 栈 API 密钥(以“blt”开头)
deliveryTokenstring-交付令牌(以“cs”开头)
environmentstring-目标环境(“preview”|“production”)
regionstring'us'Contentstack 区域
branchstring'main'内容分支
localestring'en-us'默认区域设置
调试booleanfalse启用调试日志记录

实时预览

选项类型默认描述
enablebooleanfalse启用实时预览
previewTokenstring-预览令牌(如果启用则必需)
editableTagsbooleanfalse为可视化构建添加可编辑标签
editButtonboolean | objectfalse启用/编辑按钮配置
模式'builder' | 'preview''builder'实时预览模式
ssrbooleanfalse启用 SSR 模式(实验性)

编辑按钮对象

editButton: {
  enable: boolean
  position?: 'top' | 'bottom' | 'left' | 'right' | 'top-left' | 'top-right' | 'top-center' | 'bottom-left' | 'bottom-right' | 'bottom-center'
  exclude?: ('insideLivePreviewPortal' | 'outsideLivePreviewPortal')[]
  includeByQueryParameter?: boolean
}

个性化

选项类型必需描述
enableboolean启用个性化
projectUidstring个性化项目 UID

提供

通过 useNuxtApp().$contentstack 访问

const {
  stack, // Delivery SDK Stack instance
  ContentstackLivePreview, // Live Preview Utils SDK
  Personalize, // Personalize SDK
  livePreviewEnabled, // boolean
  editableTags, // boolean
  variantAlias, // Variant manifest for personalization
  VB_EmptyBlockParentClass, // Visual Builder empty block class
} = useNuxtApp().$contentstack;

个性化 SDK 使用

const { Personalize } = useNuxtApp().$contentstack;

// Set user attributes
await Personalize.set({ age: 20 });

// Trigger impression
await Personalize.triggerImpression(experienceShortId);

// Trigger conversion event
await Personalize.triggerEvent("eventKey");

可组合项

所有 Composable 都支持实时预览更新、个性化变体和 Nuxt 的缓存系统。

useGetEntryByUrl

按 URL 字段获取条目。

const { data, status, refresh } = await useGetEntryByUrl<Page>({
  contentTypeUid: "page",
  url: "/about",
  referenceFieldPath: ["author", "category"],
  jsonRtePath: ["rich_text_field"],
  locale: "en-us",
  replaceHtmlCslp: true,
});

useGetEntry

按 UID 获取单个条目。

const { data } = await useGetEntry<Article>({
  contentTypeUid: "article",
  entryUid: "your_entry_uid",
  referenceFieldPath: ["author"],
  jsonRtePath: ["content"],
  locale: "en-us",
});

useGetEntries

通过筛选、分页和排序获取多个条目。

const { data } = await useGetEntries<Article>({
  contentTypeUid: "article",
  referenceFieldPath: ["author"],
  locale: "en-us",
  limit: 10,
  skip: 0,
  orderBy: "created_at",
  includeCount: true,
  where: {
    status: "published",
    view_count: { $gt: 1000 },
    created_at: { $gte: "2024-01-01", $lt: "2024-12-31" },
    featured_image: { $exists: true },
    title: { $regex: "nuxt.*contentstack" },
    tags: ["tech", "news"],
    author: { $ne: "guest" },
  },
});

// Access results
console.log(data.value?.entries); // Article[]
console.log(data.value?.count); // number (if includeCount: true)

useGetAsset

按 UID 获取单个资产。

const { data } = await useGetAsset<Asset>({
  assetUid: "your_asset_uid",
  locale: "en-us",
});

useGetAssets

通过筛选获取多个资产。

const { data } = await useGetAssets<Asset>({
  locale: "en-us",
  limit: 20,
  orderBy: "created_at",
  includeCount: true,
  where: {
    content_type: "image/jpeg",
    // Note: Most asset filters are applied client-side
  },
});

查询运算符

在条目 Composable 的 where 子句中受支持

  • 精确匹配: field: "value"
  • 数组包含: tags: ["tech", "news"]
  • 比较: field: { $gt: 100, $gte: 50, $lt: 200, $lte: 150, $ne: "value" }
  • 存在: field: { $exists: true }
  • 正则: field: { $regex: "pattern" }

useImageTransform

以编程方式转换 Contentstack 图像。

const { transformedUrl, updateTransform, resetTransform } = useImageTransform(
  imageUrl,
  {
    width: 800,
    height: 600,
    quality: 80,
    format: "webp",
    fit: "crop",
    blur: 5,
    saturation: 10,
    brightness: 5,
    overlay: {
      relativeURL: "/watermark.png",
      align: "bottom-right",
      width: "20p",
    },
    sharpen: {
      amount: 5,
      radius: 2,
      threshold: 0,
    },
  }
);

// Update reactively
updateTransform({ width: 1200, quality: 90 });

组件

ContentstackModularBlocks

将 Contentstack 模块化块渲染为具有自动获取功能的 Vue 组件。默认情况下,自动获取已启用,其中 contentTypeUid: 'page'url: '/'。在使用预获取块时,要禁用自动获取,请将这些 prop 设置为 undefined

模式 1:自动获取条目

<script setup>
const componentMapping = {
  hero: Hero,
  grid: Grid,
  text_block: TextBlock,
};
</script>

<template>
  <ContentstackModularBlocks
    content-type-uid="page"
    :url="$route.path"
    blocks-field-path="components"
    :reference-field-path="['author']"
    :json-rte-path="['rich_text']"
    :auto-seo-meta="true"
    :component-map="componentMapping"
  >
    <template #loading>Loading...</template>
    <template #error>Failed to load</template>
    <template #empty>No content</template>
  </ContentstackModularBlocks>
</template>

模式 2:预获取块

<script setup>
const { data: page } = await useGetEntryByUrl({
  contentTypeUid: "page",
  url: useRoute().path,
});

const componentMapping = {
  hero: Hero,
  grid: Grid,
};
</script>

<template>
  <ContentstackModularBlocks
    :blocks="page.components"
    :component-map="componentMapping"
  />
</template>

属性

属性类型默认描述
blocksContentstackBlock[][]模块化块数组
componentMapComponentMapping{}块类型 → Vue 组件映射
fallbackComponent组件ContentstackFallbackBlock用于未映射块的组件
contentTypeUidstring'page'用于自动获取的内容类型
urlstring'/'用于自动获取的 URL
blocksFieldPathstring'components'提取块的字段路径
referenceFieldPathstring[][]要包含的引用字段
jsonRtePathstring[][]JSON RTE 字段路径
localestring'en-us'Locale
replaceHtmlCslpbooleaneditableTags替换 HTML CSLP 标签
seoMetaSeoMetaInput-SEO 元数据(传递给 useSeoMeta
autoSeoMetaboolean | Record<string, string>false从条目自动生成 SEO
containerClassstring'contentstack-modular-blocks'容器 CSS 类
emptyBlockClassstring'visual-builder__empty-block-parent'空块 CSS 类
showEmptyStatebooleantrue显示空状态
keyFieldstring'_metadata.uid'块的关键字段
autoExtractBlockNamebooleantrue自动提取块名称

SEO 元数据

手动 SEO

<ContentstackModularBlocks
  :seo-meta="{
    title: 'Page Title',
    description: 'Page description',
    ogImage: 'https://example.com/image.jpg',
  }"
/>

自动生成 SEO

<!-- Default field mapping -->
<ContentstackModularBlocks :auto-seo-meta="true" />

<!-- Custom field mapping -->
<ContentstackModularBlocks
  :auto-seo-meta="{
    title: 'seo_title|title|name',
    description: 'meta_description|description',
    ogImage: 'featured_image.url',
  }"
/>

默认自动 SEO 映射

  • title: seo_titletitlename
  • description: seo_descriptiondescriptionsummary
  • ogImage: featured_image.urlog_image.urlimage.url

插槽

  • loading - 自定义加载状态(自动获取模式)
  • error - 自定义错误状态(自动获取模式)
  • empty - 自定义空状态

ContentstackFallbackBlock

内置的未映射块类型回退组件。显示块标题、类型徽章和格式化为 JSON 的属性。

@nuxt/image 集成

设置

npm install @nuxt/image
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ["nuxt-contentstack", "@nuxt/image"],

  image: {
    providers: {
      contentstack: {
        name: "contentstack",
        provider:
          "node_modules/nuxt-contentstack/dist/runtime/providers/contentstack",
      },
    },
    provider: "contentstack", // Optional: set as default
  },
});

使用

<template>
  <!-- Basic usage -->
  <NuxtImg
    :src="image.url"
    :alt="image.title"
    width="800"
    height="400"
    :modifiers="{ auto: 'webp,compress', quality: 90 }"
    provider="contentstack"
  />

  <!-- Responsive -->
  <NuxtImg
    :src="image.url"
    sizes="100vw sm:50vw lg:33vw"
    :modifiers="{ auto: 'webp,compress' }"
  />

  <!-- Art direction -->
  <NuxtPicture
    :src="image.url"
    sizes="100vw md:50vw"
    :modifiers="{ auto: 'webp,compress' }"
  />
</template>

支持的修饰符

  • auto: 'webp' | 'webp,compress'
  • quality: number
  • format: 'webp' | 'png' | 'jpg' | 'jpeg' | 'gif' | 'auto'
  • width, height, dpr: number
  • fit: 'bounds' | 'crop'
  • blur, brightness, contrast, saturation: number
  • sharpen: { amount, radius, threshold }
  • overlay: { relativeURL, align, repeat, width, height, pad }

开发

# Install dependencies
npm install

# Generate type stubs
npm run dev:prepare

# Develop with playground
npm run dev

# Build playground
npm run dev:build

# Lint
npm run lint

# Test
npm run test
npm run test:watch

# Release
npm run release