# Integrating CMS

Want to build an integration?

If you want to integrate any CMS platform with Vue Storefront please contact the core team first. We are eager to help you with building it and ensuring its high quality! Building the integration together with core team is the best way to keep its quality high and make it officially recommended once its done.

Integrating a CMS platform with Vue Storefront is a piece of cake. You just have to provide few parameters to our factory functions and expose a way to configure the integration.

# What is needed

Here are the things that are expected from CMS integration:

# Configuration

This part is usually either using CMS JavaScript SDK under the hood or calls the API directly. Config should contain at least the API endpoint and credentials.

  • a configuration via setup method for non-Nuxt apps
// public API
setup(config)
  • a Nuxt module that runs the setup method for Nuxt apps
// public API
['@vue-storefront/{cms}/nuxt', config]

# Content fetching

Another (and the most important) thing that we need is a composable to fetch the content from our CMS.

// public API
const { search, content, loading, error } = useContent()

To create this composable you should use useContentFactory from Vue Storefront core.

// integration
import { useContentFactory } from '@vue-storefront/core'

// CONTENT and CONTENT_SEARCH_PARAMS are your CMS-specific types, we advise to have at least 'id' param for search
const useContent = useContentFactory<CONTENT, CONTENT_SEARCH_PARAMS>({
  // (params: CONTENT_SEARCH_PARAMS) => Promise<CONTENT>;
  search (params) { 
    // write your content fetching logic here
    return content
  }
}) 

The factory will output a composable fulfilling our interfaces. That's all you have to write in terms of content fetching.

# Content rendering (optional)

Many CMS systems allow to control the page layout by returning a list of components as a JSON file. These components are then rendered in the applicatio. The component that is mapping the content object into Vue components and renders them is called RenderContent.

<!-- public API -->
<RenderContent :content="content">

To build this component you just have to use our renderComponentFactory.

// integration
import { renderComponentFactory } from '@vue-storefront/core'

// CONTENT and CONTENT_SEARCH_PARAMS are your CMS-specific types, we advise to have at least 'id' param for search
const RenderComponent = renderComponentFactory({
  // (extractContent: CONTENT) => { componentName, props }[]
  extractContent (content) { 
    // extract an array of { componentName: string, props: { name, value } } pairs and the factory will generate a component that will render these components based on the ones that are currently registered within application
    return components[]
  }
}) 

Under the hood the RenderComponent is rendering components using Vue dynamic component feature:

<!-- core, inside renderComponentFactory -->
<component v-for="component in components" is="component.componentName" content="props" />

# Usage example in real app

<template>
  <div v-if="loading">Loading content...</div>
  <div v-if="error">Something is wrong!</div>
  <RenderContent v-if="content" :content="content" />
</template>

<script>
import { onSSR } from '@vue-storefront/core'
import { useContent, RenderContent } from '@vue-storefront/my-super-cms'
// These are the components that will be rendered by RenderContent.
// `extractContent` should return [{ componentName: 'CMSBanner', props: { ... }}, { componentName: 'CMSHero', props: { ... }}]
import { CMSBanner, CMSHero } from '~/components'

export default {
  components: {
    RenderContent,
    CMSBanner,
    CMSHero
  }
  setup( ) {
    const { search, content, loading, error } = useContent()

    onSSR(async () {
      await search({ id: 'CONTENT_ID' })
    })

    return {
      content,
      loading,
      error
    }
  }
}
</script>