Use Contentful with Visual Editor
Visual Editor has first-class support for two-way syncing content between Contentful and Visual Editor.
# Configure Contentful as a content source
Visual Editor has a tight integration to support Contentful as one or more of your content sources. This guide covers what you need to know about configuring Visual Editor to provide a two-way data sync between your Contentful spaces.
Here is an example configuration that uses Next.js as the site framework and uses a page
content type to represent pages:
// stackbit.config.ts
import { defineStackbitConfig } from "@stackbit/types";
import { ContentfulContentSource } from "@stackbit/cms-contentful";
export default defineStackbitConfig({
stackbitVersion: "~0.6.0",
ssgName: "nextjs",
nodeVersion: "16",
contentSources: [
new ContentfulContentSource({
spaceId: process.env.CONTENTFUL_SPACE_ID!,
environment: process.env.CONTENTFUL_ENVIRONMENT!,
previewToken: process.env.CONTENTFUL_PREVIEW_TOKEN!,
accessToken: process.env.CONTENTFUL_MANAGEMENT_TOKEN!,
useWebhookForContentUpdates: true
})
],
models: {
page: { type: "page", urlPath: "/{slug}" }
}
});
Notice the following:
ContentfulContentSource
is being loaded from the@stackbit/cms-contentful
which must be installed first. This package is not needed in your production site.- Contentful is being configured using local environment variables. Visual Editor will automatically load a
.env
file in the root of your project. - There is a content type with an ID of
page
that is being used to store page data in Contentful. That content type has a field with nameslug
that determines the URL path at which the page is made available.
# Prerequisites
To be able to work with Contentful, you must first have the following:
A Contentful space with content.
The proper API keys that can access your content. (See options below.)
Installed
@stackbit/cms-contentful
package as a development dependency. (We also recommend@stackbit/types
to help with configuration.)npm install -D @stackbit/types @stackbit/cms-contentful
# Usage
import { ContentfulContentSource } from "@stackbit/cms-contentful";
new ContentfulContentSource({
spaceId: "...",
environment: "...",
previewToken: "...",
accessToken: "...",
useWebhookForContentUpdates: true
});
# Options
The following are all required options, unless noted:
accessToken
: the personal access token for your authenticated user. This is sometimes called a management token. It is not the delivery API key for your space.environment
: name of the environment in which the content is stored in Contentful.previewToken
: a preview API key for the space and environment you're using.spaceId
: ID for the space, which can be found in the URL of the space.useWebhookForContentUpdates
: (optional, default:false
) whether or not to rely on a Contentful webhook for reacting to content changes.- When set to
false
(default), Visual Editor polls the Contentful Sync API every second for new and updated content, but still relies on webhooks for deleted entries. - When set to
true
, Visual Editor minimizes the number of API calls and relies on webhooks for all content changes.
- When set to
# Store sensitive values
Sensitive values can be stored in a .env
file, which will then be available when Visual Editor configuration file is loaded.
# .env
CONTENTFUL_SPACE_ID="..."
CONTENTFUL_ENVIRONMENT="..."
CONTENTFUL_PREVIEW_TOKEN="..."
CONTENTFUL_MANAGEMENT_TOKEN="..."
# Content type inference
The Contentful CSI module infers all Contentful content types to be Visual Editor data
models, unless otherwise specified.
Therefore, page
models must be defined using the modelExtensions
property.
# Use multiple spaces or environments
The contentSources
property is an array of content sources that are all pulled together with Visual Editor. You can add another content source by instantiating another class as another item in the array, while using separate environment variables for the options.
// stackbit.config.ts
import { ContentfulContentSource } from "@stackbit/cms-contentful";
export default {
contentSources: [
new ContentfulContentSource({
spaceId: process.env.CONTENTFUL_SPACE_ID_01,
environment: process.env.CONTENTFUL_ENVIRONMENT_01,
previewToken: process.env.CONTENTFUL_PREVIEW_TOKEN_01,
accessToken: process.env.CONTENTFUL_MANAGEMENT_TOKEN_01
}),
new ContentfulContentSource({
spaceId: process.env.CONTENTFUL_SPACE_ID_02,
environment: process.env.CONTENTFUL_ENVIRONMENT_02,
previewToken: process.env.CONTENTFUL_PREVIEW_TOKEN_02,
accessToken: process.env.CONTENTFUL_MANAGEMENT_TOKEN_02
})
]
// ...
};
# Conflicting model names
Note that if there are conflicting model names (for example, IDs), the model that was loaded last (later in the contentSources
array) will override those defined earlier.
# Handle Contentful presets
In Contentful, all relationships among objects are references — you can't embed entries inside another entry. By default, Visual Editor uses existing references when creating new content from a preset.
Consider a scenario in which a page
model has two fields — components
and author
— both of which hold references to other entries in the CMS.
If you then create a new page from a preset, Visual Editor will use the existing components
and author
entries. The only new content created will be the page
entry.
You can override this behavior using the presetReferenceBehavior
setting in your configuration file. See below for examples.
Note
Note that preset configuration changes only apply to newly-created presets. This is because preset configurations are stored as files and Visual Editor will not adjust existing files in your repository.
# Duplicate references
If you'd prefer for Visual Editor to duplicate references by default rather than using existing references, you can set that behavior in your configuration file.
// stackbit.config.js
export default {
presetReferenceBehavior: "duplicateContents"
// ...
};
# Add models as exceptions
There will likely be exceptions to that rule. Again, using the example above, you may want buttons to be duplicated, but author references to be copied.
# Specify exceptions to copyReference
In that case, we can leave the default presetReferenceBehavior
set to copyReference
and set the models that should duplicate the content instead (button).
// stackbit.config.js
export default {
duplicatableModels: ["button"]
// ...
};
# Specify exceptions to duplicateContents
The option changes if you've overridden the default behavior. In that case, you'd use nonDuplicatableModels
:
// stackbit.config.js
export default {
presetReferenceBehavior: "duplicateContents",
nonDuplicatableModels: ["author"]
// ...
};
# Provision Contentful
Note
This is only relevant when creating a Visual Editor project from a template.
You don't need Contentful provisioning if you have already set up a Contentful space for your project, or if you plan to manually create and configure a space.
Visual Editor will handle provisioning a new Contentful space, along with the initial payload of models and content when creating a new project from a template.
# Export content from Contentful
In most cases, projects that can be provisioned with Contentful as a content source have a Contentful space as the source of truth for duplicated projects.
The first step in preparing your project to be duplicated is to export the content schema and the initial site contents from your Contentful space.
Be sure to configure the exports to include content types, entries, and to download assets. This will place your exported data in a new directory located wherever you ran the export command. Place this directory and its contents in your project and commit the files to Git.
# Import configuration
Once you've exported the content (and committed the data files), all that is left to do is add configuration for importing the content during the provisioning process.
The following properties should be added to an import
property in your Visual Editor configuration file. All properties are required and are strings, unless otherwise noted.
assetsDirectory
: set this to the directory containing your exported content, not the path to exported assets. ThecontentFile
contains paths relative to this directory, which Visual Editor will use to upload assets into the new space. Note: This property can be ignored ifuploadAssets
is set tofalse
.contentFile
: path to theexport.json
file provided by the Contentful export.deliveryTokenEnvVar
: a string representing the name of the environment variable that contains the API delivery token that can be used to retrieve content from Contentful. This is not the token itself, but the name of the environment variable.previewTokenEnvVar
: a string representing the name of the environment variable that contains the API preview token that can be used to retrieve content from Contentful. This is not the token itself, but the name of the environment variable.spaceIdEnvVar
: a string representing the name of the environment variable that contains the Contentful space ID. This is not the space ID itself, but the name of the environment variable.type
: set tocontentful
.uploadAssets
: (boolean) whether exported assets should be uploaded. This is typicallytrue
when you're base space included asset entries.
// stackbit.config.js
export default {
contentSources: [
new ContentfulContentSource({
spaceId: process.env.CONTENTFUL_SPACE_ID,
environment: process.env.CONTENTFUL_ENVIRONMENT,
previewToken: process.env.CONTENTFUL_PREVIEW_TOKEN,
accessToken: process.env.CONTENTFUL_MANAGEMENT_TOKEN
})
],
models: {
// page definitions and model decorations ...
},
import: {
type: "contentful",
contentFile: "contentful/export.json",
uploadAssets: true,
assetsDirectory: "contentful",
spaceIdEnvVar: "CONTENTFUL_SPACE_ID",
deliveryTokenEnvVar: "CONTENTFUL_DELIVERY_TOKEN",
previewTokenEnvVar: "CONTENTFUL_PREVIEW_TOKEN"
}
// other properties ...
};
Did you find this doc useful?
Your feedback helps us improve our docs.