This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
Distro CMS is an open source CMS used to edit Nuxt 3 Content pages, right from your site. Content updates in real-time with 2-way binding.
``bashnpm
npm install @distromade/distro-cms @distromade/distro-ui
$3
`
`$3
Add a button or link to open the CMS
`
`$3
Under
/composables, create useThemeContent.ts:`
import { computed } from 'vue';
import { v4 as uuid } from 'uuid';
import { useGlobalCMSState } from '@distromade/distro-cms';
import type {
MarkdownElement,
PlainTextElement,
PageContentType,
} from '@distromade/distro-cms/dist/types';export async function useThemeContent<
M = Record,
P = Record,
>(contentPath: string) {
const { pageContent } = useGlobalCMSState();
const contentStore = useContentStore();
const content = (await queryContent(contentPath).findOne()) as unknown as PageContentType;
contentStore.setContent(content);
const mdElements = computed(() => {
const { markdownElements } = content.cms;
const { markdownElements: cmsMdElements } = JSON.parse(
JSON.stringify(pageContent.value?.cms ?? {}),
);
if (cmsMdElements) return cmsMdElements as M;
return markdownElements as M;
});
const textElements = computed(() => {
const { plainTextElements } = content.cms;
const { plainTextElements: cmsTextElements } = JSON.parse(
JSON.stringify(pageContent.value?.cms ?? {}),
);
if (cmsTextElements) return cmsTextElements as P;
return plainTextElements as P;
});
const pageTitle = computed(() => {
if (pageContent.value) return pageContent.value.cms.pageTitle;
return content.cms.pageTitle;
});
/**
* This is a hack to force elements bound to mdElements via v-html to re-render
* when the pageContent changes.
*/
const key = computed(() => {
// does nothing; just triggers reactivity:
pageContent.value?.cms;
return uuid();
});
return {
key,
mdElements,
textElements,
pageTitle,
};
}
`$3
In your
/stores directory, create useContentStore.ts:`
import { defineStore } from 'pinia';
import type { PageContentType } from '@distromade/distro-cms/dist/types';export interface ContentState {
content: PageContentType | null;
}
export const useContentStore = defineStore('content', {
state(): ContentState {
return {
content: null as PageContentType | null,
};
},
actions: {
setContent(content: PageContentType | null) {
this.content = content;
},
},
});
`$3
In your
/pages directory, create a .vue page. In this example, we'll use about.vue for an about page.`
{{ text(textElements.title) }}
`You can render either as text in
{{ }} or in v-html.$3
In your
/content directory, create about.json.`json
{
"contentId": "about",
"cms": {
"pageTitle": "About us",
"pageDescription": "About our company...",
"plainTextElements": {
"title": {
"label": "About title",
"text": "About Killer Coffee Co."
}
},
"markdownElements": {
"about": {
"label": "About description",
"markdown": "This is our company bio, written in markdown."
}
}
}
}
`$3
`bash
npm run dev
`Now, you can edit your static content with the CMS, right from your project.
$3
---
Testing the CMS with Storyboook
To run the Storybook preview locally, while developing, run the following command:
#### Using NPM
`bash
npm install
npm run storybook
`#### Using Yarn
`bash
yarn install
yarn storybook
`#### Using PNPM
`bash
pnpm install
pnpm storybook
``