A CMS integration plugin allows you to automatically synchronize your Vendure product catalog with an external Content Management System.
This is done in a way that establishes Vendure as the source of truth for the ecommerce's data.
This guide demonstrates how to build a production-ready CMS integration plugin. The principles covered here are designed to be CMS-agnostic, however we do have working examples for various platforms.
Platforms covered in the guide:
This guide provides a high-level overview of building a CMS integration plugin. For complete implementations, refer to working examples repository
The code examples in this guide are simplified for educational purposes. The actual implementations contain additional features like error handling, retry logic, and performance optimizations.
This plugin leverages several key Vendure concepts:
The CMS integration follows a simple event-driven flow:
This ensures reliable, asynchronous synchronization with built-in retry capabilities.
First, let's use the Vendure CLI to scaffold the basic plugin structure:
This command will create the basic plugin structure. Next, we'll generate the required services:
Now we start by defining the main plugin class, its services, and the configuration types.
The CmsPlugin class registers the necessary services (CmsSyncService, CmsSpecificService) and sets up any Admin API extensions.
The plugin's configuration options are defined in a types.ts file.
Create this file in your plugin directory to define the interfaces. These options will be passed to the plugin from your vendure-config.ts.
This would be created for you automatically when you run the CLI command npx vendure add
The plugin uses Vendure's EventBus to capture changes in real-time.
In the onModuleInit lifecycle hook, we create job queues and subscribe to entity events.
You can also scaffold job queue handlers using the CLI:
This creates a productSyncQueue in the CmsSyncService. The service will be responsible for setting up the queues and processing the jobs. It will expose public methods to trigger new jobs.
Next, in the CmsPlugin, we subscribe to the EventBus and call the new service method to add a job to the queue whenever a relevant event occurs.
The sync logic is split into two services: a generic service to fetch data, and a specific service to communicate with the CMS.
CmsSyncService orchestrates the synchronization logic. It acts as the bridge between Vendure's internal systems and your CMS platform, handling data fetching, relationship resolution, and error management.
Separating orchestration logic from CMS-specific API calls allows for better testability and maintainability. The sync service handles Vendure-specific operations while CMS services focus on API communication.
The sync service handles several critical functions:
The service follows Vendure's dependency injection pattern and requires several core Vendure services:
Product sync demonstrates the complete workflow from job processing to CMS communication:
The service includes methods to resolve entity relationships. For example, finding collections that contain a specific variant:
The service can also includes syncVariantToCms() and syncCollectionToCms() methods that follow the same pattern as the product sync shown above.
These implementations are omitted from this guide for brevity, but they handle their respective entity types with similar data fetching, relationship resolution, and error handling patterns.
The complete implementations can be found in the working example repositories.
This sync service provides the foundation for handling all Vendure-specific complexity while delegating CMS API communication to specialized services.
The complete, production-ready Storyblok implementation can be found in the Storyblok integration example. Refer to it for a minimal working implementation.
Setting up Storyblok Space
Add these variables to your .env file:
The Storyblok Service
StoryblokService handles all Storyblok-specific operations including API communication, content type management, and data transformation. Key features include:
Basic Service Structure
The service follows Vendure's standard dependency injection pattern and implements OnApplicationBootstrap to ensure Storyblok is properly configured before handling sync operations.
Making API Requests
All Storyblok API communication is centralized through a single method that handles authentication, error handling, and response parsing. This approach ensures consistent behavior across all operations.
Data Transformation
Transformation methods convert Vendure entities into the format expected by Storyblok's API. The content object structure must match the component schema defined in Storyblok.
Relationship Handling
One of the most important aspects of CMS integration is maintaining relationships between entities. Products have variants, variants belong to collections, and these relationships need to be reflected in the CMS. Storyblok uses story UUIDs to create references between content pieces.
First, we need methods to query the Vendure database for related entities:
We can also use batch lookups to find multiple stories at once:
Finally, we combine database queries with CMS lookups to build relationships:
CRUD Operations
These methods handle the basic Create, Read, Update, and Delete operations for stories in Storyblok. They follow REST API conventions and leverage the centralized request method for consistent behavior.
Final Plugin Configuration
This setup provides a complete Storyblok CMS integration that automatically creates the necessary content types and syncs your Vendure catalog with structured content in Storyblok.
The complete implementations can be found in the working example repositories.
To allow for manual synchronization through graphQL mutations, we can extend the Admin API with new mutations. Let's use the CLI to generate the API extensions:
The resolver for these mutations re-uses the existing CmsSyncService to add a job to the queue.
Finally, add the plugin to your vendure-config.ts file with the appropriate configuration for your chosen CMS platform.
Refer to the platform-specific configuration examples in the tabs above for the exact environment variables and options needed for your chosen CMS.
For complete, production-ready implementations, see the working examples: