npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

nuxt-contentstack

v0.1.6

Published

Contentstack integration for Nuxt

Readme

Nuxt Contentstack

Nuxt Contentstack

npm version npm downloads License Nuxt

Contentstack integration for Nuxt.

Notice: This is an OSS project by @timbenniks and not an officially maintained package by the Contentstack team. Support requests can come through Github issues and via direct channels to @timbenniks.

Requirements

This module requires:

  • Nuxt 3.20.1 or higher (including Nuxt 4.x)
  • @nuxt/image ^2.0.0 (required for image provider functionality)

Make sure to install these dependencies in your project:

npm install nuxt@^3.20.1 @nuxt/image@^2.0.0
# or
pnpm add nuxt@^3.20.1 @nuxt/image@^2.0.0
# or
yarn add nuxt@^3.20.1 @nuxt/image@^2.0.0

Features

  • Complete set of Vue composables (entries, assets, by URL)
  • Advanced filtering, pagination, and sorting
  • Live Preview & Visual Builder support
  • Personalization support with server-side middleware
  • Image transformations with useImageTransform composable
  • @nuxt/image integration with automatic optimization
  • TypeScript support with full type safety
  • Exposed SDKs: Delivery SDK, Live Preview Utils SDK, Personalize SDK

Quick Setup

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,
  },
});

Configuration

Core Settings

| Option | Type | Required | Default | Description | | --------------- | --------- | -------- | --------- | ---------------------------------------------- | | apiKey | string | Yes | - | Contentstack stack API key (starts with "blt") | | deliveryToken | string | Yes | - | Delivery token (starts with "cs") | | environment | string | Yes | - | Target environment ('preview' | 'production') | | region | string | No | 'us' | Contentstack region | | branch | string | No | 'main' | Content branch | | locale | string | No | 'en-us' | Default locale | | debug | boolean | No | false | Enable debug logging |

Live Preview

| Option | Type | Default | Description | | -------------- | ------------------------ | ----------- | ------------------------------------- | | enable | boolean | false | Enable live preview | | previewToken | string | - | Preview token (required if enabled) | | editableTags | boolean | false | Add editable tags for visual building | | editButton | boolean \| object | false | Enable/edit button config | | mode | 'builder' \| 'preview' | 'builder' | Live preview mode | | ssr | boolean | false | Enable SSR mode (experimental) |

Edit button object:

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
}

Personalization

| Option | Type | Required | Description | | ------------ | --------- | -------- | --------------------------- | | enable | boolean | Yes | Enable personalization | | projectUid | string | Yes | Personalization project UID |

Provides

Access via 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;

Personalization SDK Usage

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");

Composables

All composables support live preview updates, personalization variants, and Nuxt's caching system.

useGetEntryByUrl

Fetch entry by URL field.

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

useGetEntry

Fetch single entry by UID.

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

useGetEntries

Fetch multiple entries with filtering, pagination, and sorting.

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

Fetch single asset by UID.

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

useGetAssets

Fetch multiple assets with filtering.

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
  },
});

Query Operators

Supported in where clause for entry composables:

  • Exact match: field: "value"
  • Array contains: tags: ["tech", "news"]
  • Comparison: field: { $gt: 100, $gte: 50, $lt: 200, $lte: 150, $ne: "value" }
  • Existence: field: { $exists: true }
  • Regex: field: { $regex: "pattern" }

useImageTransform

Transform Contentstack images programmatically.

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 });

Components

ContentstackModularBlocks

Renders Contentstack modular blocks as Vue components with optional auto-fetch capability. Auto-fetch is disabled by default. To enable auto-fetch, provide both contentTypeUid and url props. When using pre-fetched blocks, pass blocks via the blocks prop without providing contentTypeUid or url.

Pattern 1: Auto-fetch Entry

<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>

Pattern 2: Pre-fetched Blocks

<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>

Props

| Prop | Type | Default | Description | | ---------------------- | ----------------------------------- | -------------------------------------- | ---------------------------------------------------------- | | blocks | ContentstackBlock[] | [] | Array of modular blocks | | componentMap | ComponentMapping | {} | Block type → Vue component mapping | | fallbackComponent | Component | ContentstackFallbackBlock | Component for unmapped blocks | | contentTypeUid | string | undefined | Content type for auto-fetch (required if using auto-fetch) | | url | string | undefined | URL for auto-fetch (required if using auto-fetch) | | blocksFieldPath | string | 'components' | Field path to extract blocks | | referenceFieldPath | string[] | [] | Reference fields to include | | jsonRtePath | string[] | [] | JSON RTE field paths | | locale | string | 'en-us' | Locale | | replaceHtmlCslp | boolean | editableTags | Replace HTML CSLP tags | | seoMeta | SeoMetaInput | - | SEO metadata (passed to useSeoMeta) | | autoSeoMeta | boolean \| Record<string, string> | false | Auto-generate SEO from entry | | containerClass | string | 'contentstack-modular-blocks' | Container CSS class | | emptyBlockClass | string | 'visual-builder__empty-block-parent' | Empty block CSS class | | showEmptyState | boolean | true | Show empty state | | keyField | string | '_metadata.uid' | Key field for blocks | | autoExtractBlockName | boolean | true | Auto-extract block name |

SEO Metadata

Manual SEO:

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

Auto-generate 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',
  }"
/>

Default auto-SEO mapping:

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

Slots

  • loading - Custom loading state (auto-fetch mode)
  • error - Custom error state (auto-fetch mode)
  • empty - Custom empty state

ContentstackFallbackBlock

Built-in fallback component for unmapped block types. Displays block title, type badge, and props as formatted JSON.

@nuxt/image Integration

Note: This module requires @nuxt/image version 2.0.0 or higher. Make sure you have it installed before using the Contentstack image provider.

Setup

The @nuxt/image module should already be installed as a peer dependency. If not, install it:

npm install @nuxt/image@^2.0.0
// 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
  },
});

Usage

<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>

Supported Modifiers

  • 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 }

Development

# 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