Bootstrapping Bloomreach Content

Vue Storefront ships with a set of schemas for content types, folders, components, menus and layouts. They are aligned with our out-of-the-box frontend components. Here you will learn how to import them into your Bloomreach Content environment using our Bloomreach Content Manager tool.

The tool is still in beta

Bloomreach Content Manager is a recently developed tool with significant potential for further enhancements. If you encounter any challenges while using it, please feel free to report the issues to the Vue Storefront team. Your feedback and input are valuable in helping us improve the tool and provide a better experience for all users

Overview

Bloomreach Content comes equipped with powerful Management APIs (opens new window), which provide developers the flexibility to interact with the CMS using a fully programmatic approach. Instead of navigating through the UI, developers can construct schemas for their data models and efficiently upload them to their Bloomreach Content environment using tools like Postman (opens new window).

While this improvement alone is significant, certain tasks like creating projects, adding channels, manually sending individual requests, and then merging projects still demand attention, and the correct sequence of actions is crucial.

Vue Storefront takes this a step further by simplifying the entire process. Our Bloomreach Content Manager serves as an additional abstraction layer built on top of the Management APIs. It enables developers to concentrate solely on writing Typescript schemas for their artifacts without worrying about other tasks.

With a single command, developers can instruct the manager to synchronize the schemas on their behalf. This automation not only saves valuable time but also ensures a hassle-free experience, allowing developers to savor their moments while the tool takes care of the rest.

Prerequisites

To work with our Manager, you're going to need a dedicated auth token. Go to your Bloomreach Content dashboard and follow the instructions in this guide (opens new window) to create a new auth token with the following permissions:

API Access
Site management Read ✔ Write ✔︎
Content type management Read ✔ Write ✔︎
Content management Read ✔ Write ✔︎
Folder management Read ✔ Write ✔︎
Projects management Read ✔ Write ✔︎

Save the auth token for later. We will use it in the next sections of this tutorial.

Installation

Install Bloomreach Content Manager as a dev dependency of your project with the following command:

# npm
npm install @vsf-enterprise/bloomreach-content-manager@beta --save-dev

# yarn
yarn add @vsf-enterprise/bloomreach-content-manager@beta -D

Bootstrapping

Good to know

This guide assumes you had completed your frontend application setup by following either of the guides on bootstrapping Nuxt or Next.

If you have followed one of the guides for setting up your frontend application, you've likely already utilized our CLI tool for CMS integrations. As part of the bootstrapping process, the CLI tool copied the /schemas directory, along with other essential components, into your project:

└── schemas
    ├── component-groups
    │   └── ...
    ├── components
    │   └── ...
    ├── content-types
    │   ├── documents
    │   │   └── ...
    │   └── field-groups
    │       └── ...
    ├── folders
    │   └── ...
    ├── index.ts
    ├── layouts
    │   └── ...
    ├── menus
    │   └── ...
    └── synchronize.ts

The directory contains Typescript schemas and the synchronize.ts script, which facilitates the uploading of these schemas into any Bloomreach Content environment. Before running the script, please open it and replace <brx_host> with the ID of your specific Bloomreach Content environment, and <brx_auth_token> with the authentication token generated in the Prerequisites chapter:

const bloomreachManager = new BloomreachManager({
  apiUrl: 'https://<brx_host>.bloomreach.io/',
  authToken: '<brx_auth_token>'
});

The default schema provided to the synchronize.ts script is set up to create component groups, components, layouts and menus specifically for the en channel. If your Bloomreach environment has a channel with a different name, it is essential to make appropriate updates to the synchronize.ts script to reflect the correct channel name.

In case your environment features multiple channels (for example, to serve dynamic content in different languages), you can easily handle this by adding additional properties in the channelOperations object. Each property in this object corresponds to a different channel, enabling you to manage the synchronization process efficiently for multiple channels as needed.

bloomreachManager.run({
  // ...
  channelsOperations: {
    'en': {
      // ...
    },
    'de': {
      // ...
    }
  },
});

Once ready, run the script from the root of your project using ts-node:

ts-node ./schemas/synchronize.ts

To ensure optimal performance, it is recommended to use the Manager with a clean Bloomreach Content environment. If you already have existing artifacts in your instance, please verify that there are no naming collisions between those artifacts and Vue Storefront's schemas.

Good to know

If you plan to utilize the Manager regularly, we strongly advise creating a dedicated script in the package.json file as follows:

{
  "scripts": {
    // ...
    "br": "ts-node ./schemas/synchronize.ts"
  }
}

It will allow you to effortlessly execute the synchronize.ts script with a simple command:

yarn br

After a successful bootstrapping process, a series of green check marks in the terminal will indicate the completion. At this point, your journey with the Manager can conclude and you can proceed to create your first components and pages.

If your sole objective was to perform the initial environment bootstrap, you may choose to delete the /schemas directory from your project entirely and no longer utilize the tool. However, you can also choose to delve deeper into its capabilities.

General usage

The primary objective of the Manager is to grant you complete independence during the initial phase of working with Bloomreach Content and Vue Storefront. It allows you to populate your environment with default schemas, after which you can choose to discontinue its usage. Alternatively, you have the option to leverage its capabilities throughout your development journey with Vue Storefront, enabling you to create new schemas, update existing ones, and remove any that are no longer required.

Creating artifacts

Suppose you wish to create a new Example component in your frontend and establish a corresponding structure in Bloomreach Content. While you have the option to follow the manual approach using the UI, you can also opt to write schemas and let the manager handle the uploading process for you.

First, create a schema for your content type in the /schemas/content-types/documents directory:

Click to expand
import { ContentType } from "@vsf-enterprise/bloomreach-content-manager";

export const exampleContentType: ContentType = {
  name: 'vuestorefront:example',
  type: 'Document',
  presentation: {
    layout: 'one-column',
    displayName: 'Example'
  },
  fields: [
    {
      name: 'component',
      type: 'String',
      defaultValue: ['Example'],
      presentation: {
        displayType: 'Simple',
        caption: 'Component',
      }
    },
    {
      name: 'title',
      type: 'String',
      presentation: {
        displayType: 'Simple',
        caption: 'Title',
      },
      required: true
    },
    {
      name: 'subtitle',
      type: 'String',
      presentation: {
        displayType: 'Simple',
        caption: 'Subtitle',
      },
      required: true
    },
    {
      name: 'button',
      type: 'FieldGroup',
      fieldGroupType: 'vuestorefront:button',
      presentation: {
        caption: 'Button',
      }
    },
    {
      name: 'styles',
      type: 'FieldGroup',
      multiple: true,
      fieldGroupType: 'vuestorefront:styles',
      presentation: {
        caption: 'Style',
        hint: 'Adding properties such as margin and padding for various screen resolutions'
      }
    }
  ]
}

Second, create a schema for a new folder that will serve as the storage location for your new content type documents. Place it in the /schemas/folders directory:

Click to expand
import { Folder } from "@vsf-enterprise/bloomreach-content-manager";

export const exampleFolder: Folder = {
  path: '/content/documents/en/example',
  type: 'folder',
  allowedDocumentTypes: ['vuestorefront:example']
};

Finally, create a schema for a new Bloomreach component in the /schemas/components directory:

Click to expand
import { ComponentDefinition } from "@vsf-enterprise/bloomreach-content-manager";

export const exampleComponent: ComponentDefinition = {
  id: 'vuestorefront/example',
  extends: 'base/component',
  label: 'Vuestorefront Example',
  icon: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTc2IiBoZWlnaHQ9IjE3NiIgdmlld0JveD0iMCAwIDE3NiAxNzYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik03OS4yMTY1IDUuOTI0MDFDNzcuNjQ2MiA2LjkwMDUzIDc2LjEwNTIgOC40NDE0NyA3My4wMjM0IDExLjUyMzRDNjkuOTQxOCAxNC42MDQ4IDY4LjQwMDQgMTYuMTQ2MyA2Ny40MjQgMTcuNzE2NUM2NC4xOTIgMjIuOTE0IDY0LjE5MiAyOS40OTYgNjcuNDI0IDM0LjY5MzVDNjguNDAwMyAzNi4yNjM1IDY5Ljk0MDkgMzcuODA0MSA3My4wMjE1IDQwLjg4NDhMNzMuMDIzIDQwLjg4NjRDNzYuMTA0OSA0My45NjgyIDc3LjY0NjIgNDUuNTA5NSA3OS4yMTY1IDQ2LjQ4NkM4NC40MTQgNDkuNzE4IDkwLjk5NiA0OS43MTggOTYuMTkzNSA0Ni40ODZDOTcuNzYzOCA0NS41MDk1IDk5LjMwNDggNDMuOTY4NSAxMDIuMzg3IDQwLjg4NjdDMTA1LjQ2OSAzNy44MDQ4IDEwNy4wMDkgMzYuMjYzOCAxMDcuOTg2IDM0LjY5MzVDMTExLjIxOCAyOS40OTYgMTExLjIxOCAyMi45MTQgMTA3Ljk4NiAxNy43MTY1QzEwNy4wMDkgMTYuMTQ2MiAxMDUuNDY5IDE0LjYwNTMgMTAyLjM4NyAxMS41MjM0Qzk5LjMwNDggOC40NDE1NCA5Ny43NjM4IDYuOTAwNTMgOTYuMTkzNSA1LjkyNDAxQzkwLjk5NiAyLjY5MjAyIDg0LjQxNCAyLjY5MTk4IDc5LjIxNjUgNS45MjQwMVoiIGZpbGw9IiMwMkM2NTIiLz4KPHBhdGggZD0iTTk5LjQ5MjggMTAyLjM0MUwxMzUuMzUzIDY2LjQ4MDRDMTM2LjgzOSA2NC45OTQ2IDEzOC42MDMgNjMuODE2MSAxNDAuNTQ0IDYzLjAxMkMxNDIuNDg1IDYyLjIwNzkgMTQ0LjU2NiA2MS43OTQxIDE0Ni42NjcgNjEuNzk0MUMxNDguNzY4IDYxLjc5NDEgMTUwLjg0OCA2Mi4yMDc5IDE1Mi43OSA2My4wMTJDMTU0LjczMSA2My44MTYxIDE1Ni40OTUgNjQuOTk0NiAxNTcuOTggNjYuNDgwM0wxNzYgODQuNDk5OEMxNzUuODkxIDg0LjYwOCA4OCAxNzIuNSA4OCAxNzIuNUwwIDg0LjQ5OTlDMC4yMzg3NDUgODQuMjYxOCA5Ljk4MTYgNzQuNTE4OCAxOC4yMDkyIDY2LjI5MUMxOS42OTQxIDY0LjgwNTkgMjEuNDU3MSA2My42Mjc5IDIzLjM5NzMgNjIuODI0MkMyNS4zMzc2IDYyLjAyMDUgMjcuNDE3MiA2MS42MDcgMjkuNTE3MyA2MS42MDcxQzMxLjYxNzQgNjEuNjA3MyAzMy42OTY5IDYyLjAyMTIgMzUuNjM3MSA2Mi44MjUyQzM3LjU3NzIgNjMuNjI5MiAzOS4zMzk5IDY0LjgwNzUgNDAuODI0NiA2Ni4yOTI4TDc2Ljg3NDMgMTAyLjM0MkM3OC4zNTk1IDEwMy44MjcgODAuMTIyNyAxMDUuMDA1IDgyLjA2MzIgMTA1LjgwOUM4NC4wMDM3IDEwNi42MTMgODYuMDgzNSAxMDcuMDI2IDg4LjE4MzggMTA3LjAyNkM5MC4yODQyIDEwNy4wMjYgOTIuMzYzOSAxMDYuNjEyIDk0LjMwNDMgMTA1LjgwOEM5Ni4yNDQ3IDEwNS4wMDQgOTguMDA3NyAxMDMuODI2IDk5LjQ5MjggMTAyLjM0MVoiIGZpbGw9IiMwMkM2NTIiLz4KPC9zdmc+Cg==',
  ctype: 'Example',
  parameters: [
    {
      name: 'document',
      displayName: 'Document',
      valueType: "string",
      required: true,
      config: {
        pickerConfiguration: 'cms-pickers/documents-only',
        type: 'contentpath',
        pickerInitialPath: "example",
        pickerSelectableNodeTypes: [
          'vuestorefront:example'
        ]
      }
    },
    {
      name: 'document-template-query',
      displayName: 'Document template query',
      valueType: "string",
      defaultValue: "new-vuestorefront-example-document",
      hidden: true
    } as any,
    {
      name: 'root',
      displayName: 'Root document folder',
      valueType: "string",
      defaultValue: 'example',
      hidden: true
    },
    {
      name: 'parameter',
      displayName: 'Document parameter',
      valueType: "string",
      defaultValue: "document",
      hidden: true
    }
  ]
};

As you can see, the schema files import various types from the @vsf-enterprise/bloomreach-content-manager library. They will assist you in constructing your schema object by offering useful Typescript property suggestions and real-time input validation. With experience, creating such schemas becomes more straightforward. Additionally, you have the option to use existing schemas from your repository as a starting point while creating new ones, updating only the relevant fields.

Ensure that you re-export your newly created schemas from the index.ts files located in the /schemas/content-types, /schemas/folders, and /schemas/components directories. After completing this step, execute the synchronize.ts script, and the Manager will take care of the rest of the process.

Regrettably, the Manager cannot currently recognize updated schemas. As a result, it synchronizes all schemas provided to the run() method. To expedite the synchronization process, you can pass only the relevant schemas into the run() method.

import { bannerContentType, bannerFolder, bannerComponent } from "./schemas";

// ...

bloomreachManager.run({
  contentType: {
    createOrUpdate: [bannerContentType],
  },
  folder: {
    createOrUpdate: [bannerFolder],
  },
  channelsOperations: {
    'en': {
      component: {
        createOrUpdate: [bannerComponent],
      },
    }
  },
});

Deleting artifacts

First and foremost, the Manager provides functionality to create and update your Bloomreach Content artifacts. However, it also offers the ability to delete them. The object passed to the run() method includes separate fields for accepting schemas to facilitate artifact deletion.

For instance, suppose you intend to delete the vuestorefront:example component. You can achieve this by calling the run() method with the following object:

bloomreachManager.run({
  channelsOperations: {
    'en': {
      component: {
        remove: [
          { groupName: 'vuestorefront', componentName: 'example' },
        ]
      },
    }
  },
});

Similarly, you can remove the example folder:

bloomreachManager.run({
  folder: {
    remove: [
      { folderPath: 'content/documents/en/example' },
    ],
  },
});

and the vuestorefront:example content type:

bloomreachManager.run({
  contentType: {
    remove: [
      { contentTypeName: 'vuestorefront:example' },
    ],
  },
});

The removal operations must be executed in a specific order, aligned with the interdependencies between these artifacts. After successfully deleting the artifacts, it is essential to manually delete their corresponding create/update schemas located in the /schemas directory. This manual cleanup ensures that the schemas remain in sync with the current state of the system after the removal process.

Renaming artifacts

In addition to creating, updating, and removing artifacts, certain artifacts also support a rename operation. For instance, you can rename a content type or update the path of a folder using Manager's support for such actions. To rename the vuestorefront:example content type, you would run the Manager with the following object:

bloomreachManager.run({
  contentType: {
    rename: [
      {
        contentTypeName: 'vuestorefront:example',
        newName: 'vuestorefront:newexample',
        displayName: 'New Example'
      }
    ]
  },
});

To rename the corresponding folder:

bloomreachManager.run({
  folder: {
    moveOrRename: [
      {
        srcPath: 'content/documents/en/example',
        dstPath: 'content/documents/en/newexample'
      }
    ]
  },
});

Rename/move requests operate independently from the create/update schemas discussed in the Creating artifacts section. As a result, after sending a rename/move request, it is essential to manually update the create/update schema in the /schemas directory for the corresponding artifact. This ensures that the schema aligns with the changes made through the rename/move request.

Managing synchronize script

Using the Manager offers the advantage of version-controlling your Bloomreach Content schemas alongside your Vue or React components. However, you will also have the synchronize.ts script in the repository, which is likely to undergo frequent updates while working with the Manager. Most of these changes may not be suitable for committing to the remote repository. Therefore, it is advisable to exclude the synchronize.ts script from being version-controlled.

One viable solution to address this situation is to commit only the initial "empty shell" version of the synchronize.ts script to your remote repository:

Click to expand
import { BloomreachManager } from "../manager-lib";

const bloomreachManager = new BloomreachManager({
  apiUrl: 'https://<brx_host>.bloomreach.io/',
  authToken: '<brx_auth_token>'
});

bloomreachManager.run({
  resourceBundle: {
    createOrUpdate: [],
    remove: []
  },
  contentType: {
    createOrUpdate: [],
    remove: []
  },
  folder: {
    createOrUpdate: [],
    remove: [],
    moveOrRename: []
  },
  componentGroup: {
    ['en']: {
      createOrUpdate: [],
      remove: []
    }
  },
  component: {
    ['en']: {
      createOrUpdate: [],
      remove: []
    }
  },
  layout: {
    ['en']: {
      createOrUpdate: [],
      remove: []
    }
  },
  menu: {
    ['en']: {
      createOrUpdate: [],
      remove: []
    }
  }
});

Subsequently, to exclude it from being version-controlled, you can utilize the git update-index (opens new window) command.

git update-index --assume-unchanged ./schemas/synchronize.ts

By using the --assume-unchanged option, you ensure that any future changes to the script remain local and do not impact the repository's version history. This approach streamlines your version control process, maintaining a cleaner and more efficient workflow for your project. It also grants you the freedom to utilize the synchronize.ts script fully for creating, updating, and removing artifacts with your schemas.

If you ever need to version-control the file again, you can easily revert the exclusion by running the command:

git update-index --no-assume-unchanged ./schemas/synchronize.ts'.