Was this page helpful?

CLI tools and Compose

Compose is being deprecated. It is in maintenance mode and won’t be updated with any new features. Current installations will work until December 2025.
This document describes Compose that is driven by a legacy content model. If you set up Compose after April 21st 2022, please refer to the updated Compose documentation.

To get a general understanding of our CLI you can either read about it here or go through some guides like the one for scripting migrations.

Set up the CLI for use with Compose

In order to not lose settings in your content model that Compose relies on, you need to install and use the experimental version of our CLI. To do that install it inside your project or globally if you prefer:

npm install contentful-cli@experimental --save

In all subsequent steps you now have to provide an additional --header 'x-contentful-enable-alpha-feature: assembly-types' parameter to the CLI. Not doing that will remove all the "Composition relationship" settings in your content model, which will change the behaviour of Compose (see Composition relationship for linked entries).

Let's briefly take a closer look to get a better understanding of it. Running an export on a Compose space via

contentful space export --space-id ... --header 'x-contentful-enable-alpha-feature: assembly-types'

will yield the following data for the content field of the "Compose: Page" content type (see Compose Content Model for a detailed explanation):

{
  "contentTypes": [
    {
      "fields": [
        {
          "name": "Content",
          "validations": [
            { "linkContentType": ["page_landing", "page_help_center_article"] },
            { "relationshipType": ["Composition"] }
          ],
          ...
        },
        ...
      ]
    },
    ...
  ]
}

The crucial part here is the relationshipType validation that is heavily used by Compose.

If you run the command without the header parameter on the same space, the output will look like this:

{
  "contentTypes": [
    {
      "fields": [
        {
          "name": "Content",
          "validations": [
            { "linkContentType": ["page_landing", "page_help_center_article"] }
          ],
          ...
        },
        ...
      ]
    },
    ...
  ]
}

If you then reuse that export further to import it into another space or do other operations with the provided data, the Composition relationship for the content in that space will be deactivated.

Create an initial migration for the content model of Compose

Imagine you want to start rolling out Compose in more spaces without the need to go through the UI setup flow again and again. In that case you can generate yourself a migration file by running:

contentful space generate migration --space-id ... --header 'x-contentful-enable-alpha-feature: assembly-types'

This will create a JavaScript file for you in your current folder, which you might want to check if it contains the aforementioned relationshipType: ["Composition"].

With this migration file as a starting point you can programmatically set up spaces or environments for Compose easily. See Scripting migrations with the Contentful CLI for more examples, but keep in mind that you will still need to use our experimental version of the CLI and append the header parameter.

Add a new reference field to the Landing Page

Let's consider an example of how to expand a standard Landing page in Compose with a dedicated section for the bottom of the web page.

First, we create a file called add-bottom-section.js with this content:

module.exports = function (migration) {
  const landing = migration.editContentType('page_landing');
  landing
    .createField('section_bottom')
    .name('Bottom section')
    .type('Link')
    .required(true)
    .validations([
      { linkContentType: ['component_text'] },
      { relationshipType: ['Composition'] },
    ])
    .linkType('Entry');
};

Then, we use that file and migrate a Compose space with:

contentful space migration --space-id ... --header 'x-contentful-enable-alpha-feature: assembly-types' add-bottom-section.js

We used relationshipType: ["Composition"] in the validations to make Compose expand these entries by default in the page editor. Our guiding principle in this case is that it inherently belongs to one particular page and won't be reused in other pages (see When to activate the Composition relationship for more information).

Add a new page type to Compose

As another example of tailoring Compose towards your specific needs, let's add an "About" page type with the CLI. The page type creation flow will be the same as described in Page types, but the CLI allows to do it programmatically rather than manually.

Again, we create our migration first. Let's call it add-about-page.js and add this content:

module.exports = function (migration) {
  // create the content type
  const about = migration
    .createContentType('page_about')
    .name('About page')
    .description('About pages')
    .displayField('name');

  // add mandatory 'name' field
  about.createField('name').name('Internal name').type('Symbol').required(true);

  // re-use the text content type
  about
    .createField('text')
    .name('Text')
    .type('Link')
    .required(true)
    .validations([
      { linkContentType: ['component_text'] },
      // giving it a composition relationship will expand the entry
      // by default in Compose
      { relationshipType: ['Composition'] },
    ])
    .linkType('Entry');

  const page = migration.editContentType('page');
  page.editField('content').validations([
    // enable the new page type, so it's picked up by Compose
    {
      linkContentType: [
        'page_landing',
        'page_help_center_article',
        'page_about',
      ],
    },
    { relationshipType: ['Composition'] },
  ]);
};

Let's highlight the usage of the relationshipType validation again before applying it.

The first time we use it is for the text field on our new about page. This will make it auto-expand in Compose when you view a page. We do it for the same reasons as in the previous example: It belongs to individual "About" pages and won't be reused in other places. The second time we use it is when we adjust our core "Compose: Page". This time it is a must-have as Compose relies on that setting to pick up page types, so don't forget to use it.

As a last step, apply the migration on a space that was already set up for Compose by running:

contentful space migration --space-id ... --header 'x-contentful-enable-alpha-feature: assembly-types' migrations/add-about-page.js

Go to Compose and you will see an "About page" as an option when creating a new page.