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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@duffcloudservices/cms

v0.3.16

Published

Vue 3 composables and Vite plugins for DCS CMS integration

Downloads

1,212

Readme

@duffcloudservices/cms

Vue 3 composables and Vite plugins for DCS (Duff Cloud Services) CMS integration.

Installation

# Using pnpm
pnpm add @duffcloudservices/cms

# Using npm
npm install @duffcloudservices/cms

# Using yarn
yarn add @duffcloudservices/cms

Peer Dependencies

This package requires:

  • vue ^3.4.0
  • @unhead/vue ^1.9.0

Quick Start

1. Configure Vite Plugins

// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { dcsContentPlugin, dcsSeoPlugin } from '@duffcloudservices/cms/plugins'

export default defineConfig({
  plugins: [
    vue(),
    dcsContentPlugin(),
    dcsSeoPlugin()
  ]
})

For VitePress:

// .vitepress/config.ts
import { defineConfig } from 'vitepress'
import { dcsContentPlugin, dcsSeoPlugin } from '@duffcloudservices/cms/plugins'

export default defineConfig({
  vite: {
    plugins: [
      dcsContentPlugin(),
      dcsSeoPlugin()
    ]
  }
})

2. Set Environment Variables

# .env
VITE_SITE_SLUG=your-site-slug

# Optional: for runtime overrides (premium tier)
VITE_API_BASE_URL=https://portal.duffcloudservices.com
VITE_TEXT_OVERRIDE_MODE=commit  # 'commit' (default) or 'runtime'

3. Use Composables

<script setup lang="ts">
import { useTextContent, useSEO } from '@duffcloudservices/cms'

// Text content with defaults
const { t } = useTextContent({
  pageSlug: 'home',
  defaults: {
    'hero.title': 'Welcome to Our Site',
    'hero.subtitle': 'Build amazing things with us',
    'cta.primary': 'Get Started'
  }
})

// SEO configuration
const { applyHead } = useSEO('home')
applyHead()
</script>

<template>
  <section class="hero">
    <h1>{{ t('hero.title') }}</h1>
    <p>{{ t('hero.subtitle') }}</p>
    <button>{{ t('cta.primary') }}</button>
  </section>
</template>

Composables

useTextContent

Provides text content management with build-time injection and optional runtime overrides.

import { useTextContent } from '@duffcloudservices/cms'

const {
  t,                    // (key: string, fallback?: string) => string
  texts,                // ComputedRef<Record<string, string>>
  overrides,            // Ref<Record<string, string>>
  isLoading,            // Ref<boolean>
  error,                // Ref<string | null>
  refresh,              // () => Promise<void>
  hasOverride,          // (key: string) => boolean
  hasBuildTimeContent,  // boolean
  mode                  // 'commit' | 'runtime'
} = useTextContent({
  pageSlug: 'home',
  defaults: {
    'hero.title': 'Default Title'
  },
  fetchOnMount: true,  // default: true (only matters in runtime mode)
  cacheTtl: 60000      // default: 60000ms
})

Content Resolution Order:

  1. Runtime API overrides (premium tier only)
  2. Build-time content from .dcs/content.yaml
  3. Hardcoded defaults passed to the composable

useSEO

Provides SEO configuration with meta tags, Open Graph, Twitter Cards, and JSON-LD.

import { useSEO } from '@duffcloudservices/cms'

const {
  config,         // ComputedRef<ResolvedPageSeo>
  applyHead,      // (overrides?: HeadOverrides) => void
  getSchema,      // () => object[]
  getCanonical,   // () => string
  hasBuildTimeSeo // boolean
} = useSEO('home', '/') // pageSlug, optional pagePath

// Apply all meta tags
applyHead()

// Or with overrides
applyHead({
  title: 'Custom Title',
  description: 'Custom description',
  schemas: [...getSchema(), customSchema]
})

useReleaseNotes

Fetches release notes from the DCS Portal API.

import { useReleaseNotes } from '@duffcloudservices/cms'

const {
  releaseNote,  // Ref<ReleaseNote | null>
  isLoading,    // Ref<boolean>
  error,        // Ref<string | null>
  refresh       // () => Promise<void>
} = useReleaseNotes('1.2.0')  // or 'latest'

useSiteVersion

Gets the current site version for footer badges.

import { useSiteVersion } from '@duffcloudservices/cms'

const {
  version,          // Ref<string | null>
  isLoading,        // Ref<boolean>
  releaseNotesUrl   // ComputedRef<string>
} = useSiteVersion()

Vite Plugins

dcsContentPlugin

Injects .dcs/content.yaml at build time.

import { dcsContentPlugin } from '@duffcloudservices/cms/plugins'

dcsContentPlugin({
  contentPath: '.dcs/content.yaml',  // default
  debug: false                        // default
})

dcsSeoPlugin

Injects .dcs/seo.yaml at build time.

import { dcsSeoPlugin } from '@duffcloudservices/cms/plugins'

dcsSeoPlugin({
  seoPath: '.dcs/seo.yaml',  // default
  debug: false                // default
})

Configuration Files

.dcs/content.yaml

version: 1
lastUpdated: "2025-01-01T00:00:00Z"
updatedBy: "portal"

global:
  nav.home: Home
  nav.about: About
  footer.copyright: © 2025 My Company

pages:
  home:
    hero.title: Welcome to Our Site
    hero.subtitle: Build amazing things
    cta.primary: Get Started
  about:
    hero.title: About Us
    hero.subtitle: Learn more about our mission

.dcs/seo.yaml

version: 1
lastUpdated: "2025-01-01T00:00:00Z"

global:
  siteName: My Site
  siteUrl: https://example.com
  locale: en_US
  defaultTitle: My Site
  defaultDescription: Build amazing things with us
  titleTemplate: "%s | My Site"
  
  social:
    twitter: mycompany
    linkedin: my-company
  
  images:
    logo: https://example.com/logo.png
    ogDefault: https://example.com/og-image.jpg

pages:
  home:
    title: Welcome
    description: Build amazing things with our platform
    noTitleTemplate: true
    openGraph:
      type: website
    twitter:
      card: summary_large_image
  
  about:
    title: About Us
    description: Learn more about our company and mission

TypeScript Support

All composables and plugins are fully typed. Import types as needed:

import type {
  TextContentConfig,
  TextContentReturn,
  SeoConfiguration,
  PageSeoConfig,
  ReleaseNote
} from '@duffcloudservices/cms'

Migration from Manual Setup

If you're migrating from manually copied composables:

// Before:
import { useTextContent } from '@/lib/use-text-content'

// After:
import { useTextContent } from '@duffcloudservices/cms'

The API is the same, so no other code changes are needed.

DCS Visual Editor Bridge

For DCS-managed sites, src/editor/editorBridge.ts is the shared discovery/runtime layer that turns site DOM markers into portal editing entry points.

Managed background images

For customer-site hero, CTA, footer, and card backgrounds that need editor image replacement, prefer a real <picture>/<img> layer over CSS-only background-image. Put the URL in .dcs/content.yaml, include the key in .dcs/pages.yaml, render the layer with data-dcs-image-key="<content.key>", and keep the current URL available through data-dcs-image-url or a hidden data-dcs-text marker. This lets the visual editor open image management for the asset and lets snapshot capture wait on an actual image before full-page.png.

Current first-party surfaces:

  • Managed forms — discovers [data-form-key], reports hasManagedForms/managedFormIds, and emits dcs:managed-form-click
  • Reviews — discovers [data-dcs-reviews], reports hasReviews/reviewKeys, emits dcs:reviews-click, and accepts structured dcs:update-reviews data for live preview refresh

The bridge owns discovery and affordances; the portal owns the actual editing workflow. Keep every entry point converged on one sheet per component family instead of creating parallel editors.

See ../FIRST-PARTY-COMPONENTS.md for the shared contract across runtime markers, bridge events, portal workflows, publishing, rollout, and validation.

License

MIT