@duffcloudservices/cms
v0.1.1
Published
Vue 3 composables and Vite plugins for DCS CMS integration
Maintainers
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/cmsPeer 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:
- Runtime API overrides (premium tier only)
- Build-time content from
.dcs/content.yaml - 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 missionTypeScript 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.
License
MIT
