@sensinum/strapi-plugin-xecp
v5.0.0
Published
Strapi XECP (Cross Environment Content Promotion) plugin by Sensinum
Downloads
280
Readme
This plugin brings Cross Environment Content Promotion (XECP) to Strapi: move selected content from a source environment to a target with schema checks and snapshot-based comparison.
✅ GET THE LICENSE: To obtain the license we encourage you to visit the plugin commercial website, select the appropriate plan, and reach out to your preferred reseller or directly contact the plugin authors via this form.
⚠️ This plugin is licensed by Sensinum Sp. z o.o. under the End User License Agreement (EULA). Unauthorized use, including usage without a valid license key or modification of the code in a way that breaches the integrity of the software, is strictly prohibited and will be treated as a violation of the EULA, with all associated legal consequences.
Table of Contents
- ✨ Features
- 🎨 Admin Panel Features
- ⚙️ How it works
- ⚠️ Important Considerations
- 🔧 Configuration
- 🔐 Permissions
- 🧪 Testing
- 📝 License
✨ Features
- Schema Comparison: Catch content-type mismatches before promotion.
- Environment Snapshots: Store target content hashes locally so comparison can detect changes without re-fetching the remote every time.
- Selective Content Promotion: Choose exactly what moves to the target.
- Sync Job Control: Start, monitor, cancel, and resume snapshot syncs (extra requests queue while one is running).
- Configurable Scope: Include or exclude content types from the promotion graph.
- Media-Aware Promotion: Transfer media only when opted in (uploads, replaces, removes, reorders, alt changes).
🎨 Admin Panel Features
- Comparison Workspace: Review local vs snapshot differences and choose what to promote.
- Snapshot Controls: Request a new snapshot and track sync progress (start, cancel, resume).
- Target Setup: Configure the remote environment, API token, and which content types are in scope.
⚙️ How it works
XECP links a Strapi application (the source) to another Strapi instance (the target) configured with a URL and API token. The plugin also uses a configured set of content types as the promotion scope.
Before content can be promoted, XECP compares the schemas of those configured content types (and the components they use) between source and target. If they do not match, promotion and snapshot actions stay blocked until the environments are aligned. Unconfigured content types are ignored by this check.
Entity comparison requires a local snapshot of the target. XECP syncs target entities into that snapshot so comparison does not fetch from the remote on every review. The snapshot must be refreshed manually after changes on the target; it is not updated automatically.
Snapshot syncs use a shared queue: only one sync job runs at a time on the instance. If a snapshot is requested while another sync is already running, the new job is queued (FIFO) and starts automatically when the active job finishes. A content type cannot have more than one running or queued sync at once.
On the home page, operators pick a content type, review differences between local entries and the snapshot, select what to promote (including related content when applicable), and optionally opt in to media updates. XECP then pushes the selected content to the target.
⚠️ Important Considerations
Schema compatibility
Promotion and meaningful entity comparison require compatible schemas between source and target. If schemas do not match, the home page shows a schema-mismatch alert and blocks promote / get-snapshot actions until the environments are aligned.
Schema comparison is not run for every content type in the app. It covers only content types configured under Settings → Content Promotion → Configuration, excluding UIDs listed in excludedContentTypes and nonPromotableContentTypes (and a small set of plugin-owned types). Components are compared only when they are used by that scoped set. If no content types are configured, the comparison scope is empty and is treated as a match.
Entity comparison depth
Under Settings → Content Promotion → Configuration, Entity comparison depth controls how many levels of nested relations and components are inspected during entity comparison (and related sync/promote traversal). The default is 3.
If the graph is deeper than this limit, the home page can warn that max depth was exceeded: promotion can still proceed, but some nested relations may be omitted from comparison. Values above 6 may slow snapshot sync and comparison because of deep relation traversal.
Target API compatibility
XECP uses Strapi's default Content API endpoints to retrieve, create, and update content on the target environment. All default endpoints used by XECP must remain available, and their standard response structures must not be modified. Replacing these endpoints or changing their responses may prevent snapshot synchronization, comparison, or content promotion from working correctly.
Target environment credentials
The target API token is stored encrypted using the plugin encryptionKey. Use a dedicated Custom API token with at least:
| Scope | Actions | Why |
| --------------------------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------- |
| Each promotable and related collection type | find, findOne, create, update | Snapshot sync (list), lookups, create, and update / locale writes |
| Each promotable and related single type | find, update | Read and update |
| Content-Type Builder | getContentTypes, getComponents | Schema comparison |
| Upload | find, upload | Media match (GET /api/upload/files) and upload / replace (POST /api/upload) |
Grant these for every content type in Configuration that can be promoted or appears as related content. Do not grant delete unless required for other reasons — XECP does not delete remote entries.
Media uploads
When promoting media, the plugin uses Strapi’s Upload API. Uploaded files are stored in the API Uploads folder. This destination is fixed by Strapi’s upload pipeline and cannot be changed by the plugin.
Media fields are updated only when the “Update media” checkbox is selected for the promoted entries. That includes not only uploading or replacing files, but also:
- removing media from entity fields
- reordering media
- changing media metadata
Without “Update media” selected, those field changes are not applied on the target.
Replacing images that already exist on the target environment causes them to lose folder info and appear in the root Media Library folder, while the folder file count is not updated. This is a Strapi bug, not XECP behaviour.
🔧 Configuration
To configure the plugin, create a plugins.js (or plugins.ts) file in the Strapi project's config directory.
File: config/plugins.js
module.exports = {
'content-promotion': {
enabled: true,
config: {
/**
* Required. Exactly 32 characters.
* Used to encrypt the target environment API key at rest.
*/
encryptionKey: '12345678901234567890123456789012',
/**
* Optional. Max time (ms) a sync job may run before being treated as stale.
* Default value: 6 * 60 * 1000 (6 minutes)
*/
staleSyncLockMs: 6 * 60 * 1000,
/**
* Optional. Content types excluded from the promotion graph and remote push,
* but still configurable as related types in settings.
*/
nonPromotableContentTypes: [],
/**
* Optional. Content types fully ignored by XECP
* (not in settings, comparison, or promotion).
*/
excludedContentTypes: [],
},
},
};Then configure the target environment and promotable content types under Settings → Content Promotion → Configuration.
Configuration options
encryptionKey(string, required): Exactly 32 characters. Encrypts the target environment API key.staleSyncLockMs(number, optional): Maximum duration for a running sync job before it is considered stale.nonPromotableContentTypes(string[], optional): UIDs excluded from promotion / remote push / content hashes, but allowed as related types in settings.excludedContentTypes(string[], optional): UIDs fully ignored by XECP.
Environment variables
| Variable | Description |
| --------------------- | ------------------ |
| XECP_LICENSE_KEY | Licence key |
| XECP_LICENSE_SERVER | Licence server URL |
🔐 Permissions
Four admin actions:
| Action | Typical use |
| ------------------- | ------------------------------------------------ |
| settings.read | View Configuration / About; settings links |
| settings.update | Save configuration; test target connection |
| promotion.read | Plugin menu, home page, comparison / sync status |
| promotion.execute | Promote content; start / cancel / resume sync |
🧪 Testing
From the plugin directory:
yarn test:unit
# or
npm run test:unitTypecheck:
yarn test:ts:front
yarn test:ts:backWatch mode: yarn test:unit:watch / npm run test:unit:watch.
📝 License
All rights reserved. Copyright (c) Sensinum Sp. z o.o.
