Install Smart CMS Content Assistant
Edit on GitHubSmart CMS Content Assistant is an AI-powered panel embedded in the Back Office CMS Page and CMS Block glossary editors. It lets Back Office users generate and refine placeholder content per locale through a conversational AI interface. This document describes how to install Smart CMS Content Assistant.
Install the feature core
Follow the steps in the following sections to install the Smart CMS Content Assistant feature core.
Prerequisites
Install the required features:
| NAME | VERSION | INSTALLATION GUIDE |
|---|---|---|
| AI Commerce | 202604.0 | Install AI Commerce |
| CMS | 202604.0 |
1) Generate transfers and run database migration
console transfer:generate
console propel:install
2) Add configuration constants
Add the project-level constants interface to map the AI configuration keys used by the Back Office Configuration UI:
src/Pyz/Shared/AiCommerce/AiCommerceConstants.php
<?php
declare(strict_types = 1);
namespace Pyz\Shared\AiCommerce;
use SprykerFeature\Shared\AiCommerce\AiCommerceConstants as SprykerFeatureAiCommerceConstants;
interface AiCommerceConstants extends SprykerFeatureAiCommerceConstants
{
public const string AI_CONFIGURATION_SMART_CMS_OPENAI = 'AI_COMMERCE:AI_CONFIGURATION_SMART_CMS_OPENAI';
public const string AI_CONFIGURATION_SMART_CMS_AWS = 'AI_COMMERCE:AI_CONFIGURATION_SMART_CMS_AWS';
public const string AI_CONFIGURATION_SMART_CMS_ANTHROPIC = 'AI_COMMERCE:AI_CONFIGURATION_SMART_CMS_ANTHROPIC';
}
3) Configure AI models for Smart CMS Content Assistant
Add the Smart CMS Content Assistant named AI configuration entries to config/Shared/config_ai.php. The feature supports OpenAI, AWS Bedrock, and Anthropic. Only the configuration matching the vendor selected in the Back Office Configuration UI is used at runtime.
config/Shared/config_ai.php
<?php
use Pyz\Shared\AiCommerce\AiCommerceConstants;
use Spryker\Shared\AiFoundation\AiFoundationConstants;
$config[AiFoundationConstants::AI_CONFIGURATIONS][AiCommerceConstants::AI_CONFIGURATION_SMART_CMS_OPENAI] = [
'provider_name' => AiFoundationConstants::PROVIDER_OPENAI,
'provider_config' => [
'key' => AiFoundationConstants::CONFIGURATION_REFERENCE_PREFIX . \SprykerFeature\Shared\AiCommerce\AiCommerceConstants::CONFIGURATION_KEY_OPENAI_API_TOKEN,
'model' => AiFoundationConstants::CONFIGURATION_REFERENCE_PREFIX . \SprykerFeature\Shared\AiCommerce\AiCommerceConstants::CONFIGURATION_KEY_SMART_CMS_OPENAI_MODEL,
],
'system_prompt' => AiFoundationConstants::CONFIGURATION_REFERENCE_PREFIX . \SprykerFeature\Shared\AiCommerce\AiCommerceConstants::CONFIGURATION_KEY_SMART_CMS_SYSTEM_PROMPT,
];
$config[AiFoundationConstants::AI_CONFIGURATIONS][AiCommerceConstants::AI_CONFIGURATION_SMART_CMS_AWS] = [
'provider_name' => AiFoundationConstants::PROVIDER_BEDROCK,
'provider_config' => [
'model' => AiFoundationConstants::CONFIGURATION_REFERENCE_PREFIX . \SprykerFeature\Shared\AiCommerce\AiCommerceConstants::CONFIGURATION_KEY_SMART_CMS_AWS_MODEL,
'bedrockRuntimeClient' => [
'region' => AiFoundationConstants::CONFIGURATION_REFERENCE_PREFIX . \SprykerFeature\Shared\AiCommerce\AiCommerceConstants::CONFIGURATION_KEY_AWS_REGION,
'token' => AiFoundationConstants::CONFIGURATION_REFERENCE_PREFIX . \SprykerFeature\Shared\AiCommerce\AiCommerceConstants::CONFIGURATION_KEY_AWS_API_TOKEN,
],
],
'system_prompt' => AiFoundationConstants::CONFIGURATION_REFERENCE_PREFIX . \SprykerFeature\Shared\AiCommerce\AiCommerceConstants::CONFIGURATION_KEY_SMART_CMS_SYSTEM_PROMPT,
];
$config[AiFoundationConstants::AI_CONFIGURATIONS][AiCommerceConstants::AI_CONFIGURATION_SMART_CMS_ANTHROPIC] = [
'provider_name' => AiFoundationConstants::PROVIDER_ANTHROPIC,
'provider_config' => [
'key' => AiFoundationConstants::CONFIGURATION_REFERENCE_PREFIX . \SprykerFeature\Shared\AiCommerce\AiCommerceConstants::CONFIGURATION_KEY_ANTHROPIC_API_TOKEN,
'model' => AiFoundationConstants::CONFIGURATION_REFERENCE_PREFIX . \SprykerFeature\Shared\AiCommerce\AiCommerceConstants::CONFIGURATION_KEY_SMART_CMS_ANTHROPIC_MODEL,
],
'system_prompt' => AiFoundationConstants::CONFIGURATION_REFERENCE_PREFIX . \SprykerFeature\Shared\AiCommerce\AiCommerceConstants::CONFIGURATION_KEY_SMART_CMS_SYSTEM_PROMPT,
];
The model configured for Smart CMS Content Assistant must support both image input and structured output.
Default model values:
- OpenAI:
gpt-4.1 - AWS Bedrock:
eu.anthropic.claude-sonnet-4-5-20250929-v1:0 - Anthropic:
claude-sonnet-4-5
4) Configure the Smart CMS configuration name
Override AiCommerceConfig in the Zed layer to route Smart CMS Content Assistant to the correct named configuration based on the Back Office setting:
src/Pyz/Zed/AiCommerce/AiCommerceConfig.php
<?php
declare(strict_types = 1);
namespace Pyz\Zed\AiCommerce;
use Pyz\Shared\AiCommerce\AiCommerceConstants;
use SprykerFeature\Zed\AiCommerce\AiCommerceConfig as SprykerAiCommerceConfig;
use SprykerFeature\Shared\AiCommerce\AiCommerceConstants as SprykerFeatureAiCommerceConstants;
class AiCommerceConfig extends SprykerAiCommerceConfig
{
public function getSmartCmsAiConfigurationName(): string
{
return (string)$this->getModuleConfig(
SprykerFeatureAiCommerceConstants::CONFIGURATION_KEY_SMART_CMS_AI_CONFIGURATION,
AiCommerceConstants::AI_CONFIGURATION_SMART_CMS_OPENAI,
);
}
}
5) Set up behavior
Register the following plugins to wire Smart CMS Content Assistant into AiFoundationDependencyProvider:
| PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
|---|---|---|---|
SmartCmsContentToolSetPlugin |
Registers the Smart CMS content toolset, including the get_content_items tool for fetching existing content items. |
SprykerFeature\Zed\AiCommerce\Communication\Plugin\AiFoundation |
src/Pyz/Zed/AiFoundation/AiFoundationDependencyProvider.php
<?php
namespace Pyz\Zed\AiFoundation;
use Spryker\Zed\AiFoundation\AiFoundationDependencyProvider as SprykerAiFoundationDependencyProvider;
use SprykerFeature\Zed\AiCommerce\Communication\Plugin\AiFoundation\SmartCmsContentToolSetPlugin;
// ... other existing imports
class AiFoundationDependencyProvider extends SprykerAiFoundationDependencyProvider
{
/**
* @return array<\Spryker\Zed\AiFoundation\Dependency\Tools\ToolSetPluginInterface>
*/
protected function getAiToolSetPlugins(): array
{
return [
// ... other existing plugins
new SmartCmsContentToolSetPlugin(),
];
}
}
Register the content widget editor plugins in AiCommerceDependencyProvider. These plugins make the available CMS content widgets accessible to the AI when generating content:
| PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
|---|---|---|---|
ContentBannerContentGuiEditorPlugin |
Registers Banner content items as available CMS widgets. | Spryker\Zed\ContentBannerGui\Communication\Plugin\ContentGui |
|
ContentProductContentGuiEditorPlugin |
Registers Abstract Product List content items as available CMS widgets. | Spryker\Zed\ContentProductGui\Communication\Plugin\ContentGui |
|
ContentProductSetGuiEditorPlugin |
Registers Product Set content items as available CMS widgets. | Spryker\Zed\ContentProductSetGui\Communication\Plugin\ContentGui |
|
ContentFileListContentGuiEditorPlugin |
Registers File List content items as available CMS widgets. | Spryker\Zed\ContentFileGui\Communication\Plugin\ContentGui |
|
ContentNavigationContentGuiEditorPlugin |
Registers Navigation content items as available CMS widgets. | Spryker\Zed\ContentNavigationGui\Communication\Plugin\ContentGui |
src/Pyz/Zed/AiCommerce/AiCommerceDependencyProvider.php
<?php
namespace Pyz\Zed\AiCommerce;
use Spryker\Zed\ContentBannerGui\Communication\Plugin\ContentGui\ContentBannerContentGuiEditorPlugin;
use Spryker\Zed\ContentFileGui\Communication\Plugin\ContentGui\ContentFileListContentGuiEditorPlugin;
use Spryker\Zed\ContentNavigationGui\Communication\Plugin\ContentGui\ContentNavigationContentGuiEditorPlugin;
use Spryker\Zed\ContentProductGui\Communication\Plugin\ContentGui\ContentProductContentGuiEditorPlugin;
use Spryker\Zed\ContentProductSetGui\Communication\Plugin\ContentGui\ContentProductSetGuiEditorPlugin;
use SprykerFeature\Zed\AiCommerce\AiCommerceDependencyProvider as SprykerFeatureAiCommerceDependencyProvider;
// ... other existing imports
class AiCommerceDependencyProvider extends SprykerFeatureAiCommerceDependencyProvider
{
/**
* @return array<\Spryker\Zed\ContentGuiExtension\Dependency\Plugin\ContentGuiEditorPluginInterface>
*/
protected function getContentGuiEditorPlugins(): array
{
return [
new ContentBannerContentGuiEditorPlugin(),
new ContentProductContentGuiEditorPlugin(),
new ContentProductSetGuiEditorPlugin(),
new ContentFileListContentGuiEditorPlugin(),
new ContentNavigationContentGuiEditorPlugin(),
];
}
}
Make sure AiCommerceTwigPlugin is registered in TwigDependencyProvider to provide the isSmartCmsEnabled() Twig function used in the glossary editor overrides:
| PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
|---|---|---|---|
AiCommerceTwigPlugin |
Registers Twig functions and variables required by the Smart CMS panel in glossary editors. | SprykerFeature\Zed\AiCommerce\Communication\Plugin\Twig |
src/Pyz/Zed/Twig/TwigDependencyProvider.php
<?php
namespace Pyz\Zed\Twig;
use Spryker\Zed\Twig\TwigDependencyProvider as SprykerTwigDependencyProvider;
use SprykerFeature\Zed\AiCommerce\Communication\Plugin\Twig\AiCommerceTwigPlugin;
class TwigDependencyProvider extends SprykerTwigDependencyProvider
{
/**
* @return array<\Spryker\Shared\TwigExtension\Dependency\Plugin\TwigPluginInterface>
*/
protected function getTwigPlugins(): array
{
return [
// ... other plugins
new AiCommerceTwigPlugin(),
];
}
}
6) Override glossary editor templates
Override the CMS Page and CMS Block glossary editor templates to inject the AI panel. Both templates extend their core counterparts and conditionally include the AI panel partial when the feature is enabled.
src/Pyz/Zed/CmsGui/Presentation/CreateGlossary/index.twig
{% extends '@Spryker:CmsGui/CreateGlossary/index.twig' %}
{% block content %}
{% if isSmartCmsEnabled() %}
{% set smartCmsPageMeta = [] %}
{% for pageAttribute in cmsPage.pageAttributes %}
{% set smartCmsLocaleMetaAttribute = null %}
{% for metaAttribute in cmsPage.metaAttributes %}
{% if metaAttribute.localeName == pageAttribute.localeName %}
{% set smartCmsLocaleMetaAttribute = metaAttribute %}
{% endif %}
{% endfor %}
{% set smartCmsPageMeta = smartCmsPageMeta|merge([{
'localeName': pageAttribute.localeName,
'name': pageAttribute.name,
'url': pageAttribute.url,
'metaTitle': smartCmsLocaleMetaAttribute ? smartCmsLocaleMetaAttribute.metaTitle : null,
'metaKeywords': smartCmsLocaleMetaAttribute ? smartCmsLocaleMetaAttribute.metaKeywords : null,
'metaDescription': smartCmsLocaleMetaAttribute ? smartCmsLocaleMetaAttribute.metaDescription : null,
}]) %}
{% endfor %}
{% set smartCmsStores = [] %}
{% if cmsPage.storeRelation is not null %}
{% for store in cmsPage.storeRelation.stores %}
{% set smartCmsStores = smartCmsStores|merge([store.name]) %}
{% endfor %}
{% endif %}
{% set smartCmsEntityContext = {
'name': cmsPage.pageAttributes is not empty ? cmsPage.pageAttributes|first.name : null,
'templateName': cmsPage.templateName,
'urlSlug': cmsPage.pageAttributes is not empty ? cmsPage.pageAttributes|first.url : null,
'key': null,
'attributes': {
'isActive': cmsPage.isActive,
'isSearchable': cmsPage.isSearchable,
'validFrom': cmsPage.validFrom,
'validTo': cmsPage.validTo,
'stores': smartCmsStores,
'localizedAttributes': smartCmsPageMeta,
}|json_encode,
} %}
{% include '@AiCommerce/Partials/smart-cms-glossary-panel.twig' ignore missing with {
'smartCmsEntityType': 'cms_page',
'smartCmsIdEntity': idCmsPage,
'smartCmsEntityContext': smartCmsEntityContext,
} %}
{% endif %}
{{ parent() }}
{% endblock %}
src/Pyz/Zed/CmsBlockGui/Presentation/EditGlossary/index.twig
{% extends '@Spryker:CmsBlockGui/EditGlossary/index.twig' %}
{% block content %}
{% if isSmartCmsEnabled() %}
{% set smartCmsStores = [] %}
{% if cmsBlock.storeRelation is not null %}
{% for store in cmsBlock.storeRelation.stores %}
{% set smartCmsStores = smartCmsStores|merge([store.name]) %}
{% endfor %}
{% endif %}
{% set smartCmsEntityContext = {
'name': cmsBlock.name,
'templateName': cmsBlock.templateName,
'urlSlug': null,
'key': cmsBlock.key,
'attributes': {
'isActive': cmsBlock.isActive,
'validFrom': cmsBlock.validFrom,
'validTo': cmsBlock.validTo,
'stores': smartCmsStores,
}|json_encode,
} %}
{% include '@AiCommerce/Partials/smart-cms-glossary-panel.twig' ignore missing with {
'smartCmsEntityType': 'cms_block',
'smartCmsIdEntity': idCmsBlock,
'smartCmsEntityContext': smartCmsEntityContext,
} %}
{% endif %}
{{ parent() }}
{% endblock %}
In the Back Office, open a CMS Page or CMS Block glossary editor. Make sure the Smart CMS panel is visible next to the editor when the feature is enabled.
7) Sync configuration and build frontend assets
console configuration:sync
console frontend:project:install-dependencies
console frontend:zed:build
console twig:cache:warmer
8) Enable the feature
Enable Smart CMS Content Assistant in the Back Office:
- In the Back Office, go to AI Commerce > Smart CMS > AI Vendor.
- Select the desired AI Configuration (OpenAI, AWS Bedrock, or Anthropic).
- Set the model for the selected provider.
- Click Save.
In the Back Office, open a CMS Page or CMS Block glossary editor. Type a prompt in the Smart CMS panel and make sure the AI generates content for the placeholder.
Thank you!
For submitting the form