<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Spryker Documentation</title>
        <description>Spryker documentation center.</description>
        <link>https://docs.spryker.com/</link>
        <atom:link href="https://docs.spryker.com/feed.xml" rel="self" type="application/rss+xml"/>
        <lastBuildDate>Fri, 17 Apr 2026 10:26:16 +0000</lastBuildDate>
        <generator>Jekyll v4.2.2</generator>
        
        
        <item>
            <title>Release notes 202604.0</title>
            <description>Spryker Cloud Commerce OS is an end-to-end solution for digital commerce. This document contains a business-level description of new features and improvements.

For information about installing Spryker, see [Getting started guide](/docs/dg/dev/development-getting-started-guide). 

## Connected, and AI-Enabled Platform

### Algolia configuration in the Back Office {% include badge.html type=&quot;improvement&quot; %}

We updated the Algolia integration configuration to use the Back Office Configuration Framework instead of the legacy ACP-based setup. This gives users a clearer and more consistent way to manage Algolia credentials directly in the Back Office.

**Key capabilities:**
- Added a dedicated configuration page under **Back Office &gt; Configuration &gt; Integrations &gt; Algolia**
- Added fields for **Application ID**, **Search-only API key**, and **Admin API key**
- Added credential validation through the Algolia API
- Aligned Algolia configuration with the current integration approach in Spryker

**Business benefits:**
- Simplifies Algolia setup for project teams
- Reduces implementation effort and configuration errors
- Replaces legacy integration-specific configuration with a standardized Back Office experience

**Documentation:**

### Mollie PSP integration {% include badge.html type=&quot;feature&quot; %}

We introduced a new Mollie payment service provider integration for European B2B and B2C commerce scenarios. The integration helps customers implement a region-relevant PSP faster and with less custom project effort.

**Key capabilities:**
- Added support for Mollie as a payment service provider
- Enables a PSP option that is well aligned with European market requirements
- Delivered in collaboration with Spryker Solution Partner **KPS**

**Business benefits:**
- Speeds up go-live for European payment setups
- Reduces bespoke implementation and maintenance effort
- Improves checkout fit for local payment expectations across European markets

**Documentation:**

### IAM readiness and standardized OAuth SSO integration {% include badge.html type=&quot;feature&quot; %}

We introduced a reusable and standardized approach for OAuth 2.0 and OpenID Connect single sign-on across Spryker applications. This release makes identity integrations more predictable and easier to implement for the Back Office, Storefront, and Platform API.

**Key capabilities:**
- Standardized OAuth SSO approach for the **Back Office**, **Storefront**, and **Platform API**
- Added provider-agnostic integration patterns for external identity providers such as Keycloak, Azure AD, and Okta
- Added token exchange support for headless scenarios in the Platform API
- Added persistent identity linking between external identities and Spryker users or customers
- Enabled configuration of OAuth providers through YAML without code changes
- Preserved backward compatibility with existing form-based login

**Business benefits:**
- Reduces custom development for enterprise identity integrations
- Makes SSO implementations faster, more repeatable, and more predictable
- Improves consistency across applications and user roles

**Documentation:**

### Back Office Configuration Framework reaches General Availability

The Back Office Configuration Framework is now generally available. This release closes key operational and usability gaps to make configuration management more transparent, searchable, and reliable for production use.

**Key capabilities:**
- Added stronger governance and transparency for configuration changes
- Improved discoverability and search for configuration options
- Enhanced usability of configuration workflows in the Back Office
- Added support for streamlined configuration import workflows
- Improved visibility of conflicts between code-based and Back Office configuration

**Business benefits:**
- Increases operator confidence through better transparency and governance
- Reduces time spent finding and managing configuration settings
- Makes the framework ready for broader enterprise adoption

**Documentation:**

### Smart PIM in the public demo shop {% include badge.html type=&quot;early-access&quot; %}

We added Smart PIM to the public demo shop to showcase AI-assisted product enrichment in the Back Office. The feature helps users create richer and more consistent product data with less manual effort.

**Key capabilities:**
- Supports AI-powered translation of product names and descriptions into any locale
- Improves product names and descriptions with AI assistance
- Generates alt text for product images
- Suggests best-fitting product categories
- Provides user-friendly error handling when the AI integration is not configured

**Business benefits:**
- Reduces manual effort when enriching product data
- Helps merchants scale catalog creation and localization faster
- Improves product content quality and consistency across markets

**Documentation:**

### AI visual search in the demo shop {% include badge.html type=&quot;early-access&quot; %}

We added AI-powered visual search to the public demo shop. Customers can search for products using an uploaded photo, making product discovery faster and more intuitive in image-driven use cases.

**Key capabilities:**
- Enables product search through image upload
- Supports mobile-friendly visual search experiences
- Uses Spryker AI Foundation for AI connectivity
- Helps identify products based on visual input instead of manual search terms

**Business benefits:**
- Reduces friction in product discovery for technical and spare-part scenarios
- Helps customers find the right product faster and with fewer errors
- Improves conversion through a more intuitive search experience

**Documentation:**

### Back Office AI Assistant {% include badge.html type=&quot;early-access&quot; %}

We introduced an AI-powered assistant in the Back Office that helps operators complete selected tasks through natural language chat. The feature is available as Early Access and is designed to improve efficiency in common operational workflows.

**Key capabilities:**
- Added a chat interface directly in the Back Office
- Supports order status questions and Back Office navigation guidance
- Supports discount creation through chat for selected cart rule scenarios
- Supports basic product creation through chat
- Supports order creation from invoice PDFs with SKU and quantity information
- Added AI Foundation enhancements to better support chat-based agent workflows

**Business benefits:**
- Reduces time spent on repetitive Back Office tasks
- Lowers UI navigation effort for operators
- Demonstrates AI-assisted operational workflows for pilot and demo scenarios

**Documentation:**

### AI workflow visualization in the Back Office {% include badge.html type=&quot;early-access&quot; %}

We added Back Office visibility for AI workflow execution. Users can now inspect workflow runs, review state history, and manually trigger available actions when needed.

**Key capabilities:**
- Added an AI workflow list page in the Back Office
- Added a workflow details page with state history
- Added visualized workflow state progression similar to OMS process views
- Added support for triggering manual events when available

**Business benefits:**
- Improves transparency into AI-driven workflow execution
- Makes workflow troubleshooting and monitoring easier
- Supports operational control for AI-assisted processes

**Documentation:**

### AI Foundation audit log {% include badge.html type=&quot;improvement&quot; %}

We introduced persistent audit logging for AI interactions and added a dedicated Back Office UI for inspection and monitoring. This provides a structured record of prompts, responses, model details, token usage, and execution timing.

**Key capabilities:**
- Persisted AI interaction data in the database for auditability
- Added a dedicated **Intelligence &gt; Audit Logs** page in the Back Office
- Added sorting, filtering, and pagination for AI interaction logs
- Added aggregation statistics such as total requests, total tokens, success rate, and average inference time
- Added inline inspection for prompts, responses, and metadata

**Business benefits:**
- Improves traceability and governance for AI-powered features
- Simplifies troubleshooting and performance analysis
- Helps teams monitor AI usage, optimize prompts, and manage costs

**Documentation:**

### Punchout gateway with native cXML and OCI support {% include badge.html type=&quot;feature&quot; %}

We introduced native Punchout gateway capabilities for cXML and OCI to support procurement-driven B2B commerce scenarios. This makes Punchout integrations more reusable and reduces project-specific implementation effort.

**Key capabilities:**
- Added native support for **cXML** and **OCI** Punchout flows
- Supports key requisition flow steps such as session start, cart editing, and cart return
- Added standard OCI parameter handling and OCI cart return support
- Added reusable building blocks and implementation guidance for Punchout projects

**Business benefits:**
- Reduces bespoke development for Punchout integrations
- Speeds up delivery of procurement-based sales channels
- Improves support for SAP-centric procurement environments

**Documentation:**

### New Stripe integration {% include badge.html type=&quot;improvement&quot; %}

We replaced the legacy ACP-based Stripe approach with a new Stripe integration designed for extensibility and direct integration into the Spryker payment stack. We also added a Back Office configuration page for Stripe settings.

**Key capabilities:**
- Added a new Stripe Eco module that works without ACP at runtime
- Integrated Stripe into the standard Spryker payment stack
- Added support for payment initialization, authorization, capture, refund, and cancel flows
- Added a dedicated configuration page under **Back Office &gt; Configuration &gt; Integrations &gt; Stripe**
- Added validation for configuration values, including webhook-related checks

**Business benefits:**
- Gives customers and partners more flexibility to extend Stripe payment flows
- Reduces dependency on legacy implementation constraints
- Improves maintainability and long-term cost efficiency

**Documentation:**

### New Vertex integration {% include badge.html type=&quot;improvement&quot; %}

We introduced a new Vertex integration to replace the legacy ACP-based approach. The new integration is designed to provide more flexibility and reduce dependency on legacy architecture constraints.

**Key capabilities:**
- Added a new Vertex integration approach outside of the legacy ACP app model
- Improves extensibility for tax-related integration scenarios
- Reduces architectural constraints for future tax logic adaptations

**Business benefits:**
- Supports more flexible implementation of tax calculation scenarios
- Reduces integration friction for changing tax and business requirements
- Improves maintainability and lowers long-term ownership cost

**Documentation:**

### API Platform reaches General Availability

API Platform is now generally available as the new foundation for API development in Spryker. Existing APIs were migrated internally to API Platform while keeping external contracts backward compatible.

**Key capabilities:**
- Migrated internal API infrastructure to **API Platform**
- Preserved existing external API interfaces for current consumers
- Improved extensibility and standardization of API development
- Supports more declarative API resource definition and generation
- Provides a stronger foundation for future API capabilities

**Business benefits:**
- Reduces development effort for new and existing APIs
- Speeds up API delivery and change cycles
- Lowers long-term maintenance effort with a more standardized framework

**Documentation:**
## Other

### Back Office Configuration Framework {% include badge.html type=&quot;feature&quot; %}

Introduced the Back Office Configuration Framework as generally available to provide a structured way to manage and extend Back Office configuration. This helps standardize configuration handling across Back Office capabilities.

**Key capabilities:**
- Provides a dedicated framework for Back Office configuration management
- Supports more consistent and scalable Back Office extensibility

**Business benefits:**
- Simplifies configuration of Back Office capabilities
- Reduces implementation complexity for configuration-related customizations

**Documentation:**

### AI Foundation: Audit logs {% include badge.html type=&quot;feature&quot; %}

Added audit log capabilities for AI Foundation to improve traceability of AI-related actions and events. This helps teams monitor usage and maintain better operational oversight.

**Key capabilities:**
- Captures audit logs for AI Foundation activities
- Improves visibility into AI-related actions

**Business benefits:**
- Supports governance and compliance requirements
- Makes troubleshooting and operational monitoring easier

**Documentation:**

### AI Foundation: Audit Log UI in the Back Office {% include badge.html type=&quot;feature&quot; %}

Added a Back Office user interface for AI Foundation audit logs so users can review audit information directly in the Back Office. This makes audit data more accessible for daily operations and investigations.

**Key capabilities:**
- Provides a Back Office interface for viewing AI Foundation audit logs
- Makes audit information easier to access and review

**Business benefits:**
- Speeds up investigations and operational checks
- Improves usability for business and support teams

**Documentation:**

### OCI API compatibility and documentation enablement {% include badge.html type=&quot;feature&quot; %}

Added foundational OCI compatibility support and documentation enablement for SAP-centric procurement integrations. This reduces project-specific implementation effort and strengthens procurement integration support in enterprise B2B environments.

**Key capabilities:**
- Supports standard OCI parameters such as `HOOK_URL`, `OCI_VERSION`, and `USERNAME`
- Handles OCI cart return flows with line items posted back to the procurement system
- Includes documentation and integration guidance for SAP and Ariba use cases
- Provides a reference implementation example

**Business benefits:**
- Reduces effort required to implement OCI-based procurement integrations
- Increases confidence for SAP-heavy enterprise B2B projects
- Improves Spryker fit for standardized procurement scenarios

**Documentation:**
## B2B Business-Ready Commerce Experiences

### Login UX improvements {% include badge.html type=&quot;improvement&quot; %}

We improved the login experience across the Back Office, Storefront, and Marketplace to help users resume work faster and reduce friction in daily operations. Users now land on a more meaningful starting point after login, and session timeout handling preserves navigation context so they can return to the page they were using.

**Key capabilities:**
- Redirects Back Office users to the dashboard after login instead of a blank technical page
- Adds quick actions to the Back Office dashboard for common tasks such as viewing orders, adding products, opening the catalog, and checking returns
- Restores the last visited page after session timeout across the Back Office, Storefront, and Marketplace
- Reopens create and edit pages after re-login, while requiring users to re-enter unsaved data

**Business benefits:**
- Reduces onboarding friction for new users
- Improves efficiency for operational teams working across daily workflows
- Creates a more intuitive and consistent user experience
- Improves product demoability and perceived product maturity

**Documentation:**

### Product attribute display types {% include badge.html type=&quot;feature&quot; %}

You can now control where product attributes are displayed without project-specific customization. This helps keep buyer-facing product information focused while preserving internal attributes for operational and automation use cases.

**Key capabilities:**
- Introduces native visibility types for product attributes
- Supports controlling attribute visibility for internal use, PDP, and PLP and cart contexts
- Enables business and technical teams to use operational attributes without exposing them to buyers

**Business benefits:**
- Reduces repeated custom implementations across projects
- Improves time-to-market for B2B implementations
- Keeps product pages cleaner and easier for buyers to use
- Supports internal pricing, fulfillment, compliance, and AI-driven processes

**Documentation:**

### Search Statistics &amp; Google Analytics {% include badge.html type=&quot;feature&quot; %}

Spryker now provides native search statistics in the Back Office for ElasticSearch-based projects. Business users can analyze search behavior and identify zero-result searches to optimize discoverability and relevance.

**Key capabilities:**
- Adds Back Office views for top frequent searches and top zero-result searches
- Supports time-based filtering for analytics review
- Enables sorting, filtering, and CSV export for further analysis
- Tracks search-related events through Google Analytics integration

**Business benefits:**
- Eliminates repeated custom search analytics implementations
- Enables data-driven catalog and synonym optimization
- Helps identify gaps that lead to zero-result searches
- Supports better search relevance and conversion outcomes

**Documentation:**

### Budget &amp; Cost Centers EA {% include badge.html type=&quot;early-access&quot; %} {% include badge.html type=&quot;feature&quot; %}

Budget and cost center management is now available in Early Access for procurement-driven B2B scenarios. The release introduces core controls for assigning spend to cost centers, validating budgets during checkout, and integrating budget rules with approval workflows.

**Key capabilities:**
- Manages cost centers and assigns buyers to them
- Creates budgets with configurable enforcement rules such as block, warn, and require approval
- Supports cost center selection during checkout
- Validates available budget before order placement
- Integrates budget-triggered flows with the existing Approval Process
- Tracks budget consumption and restoration

**Business benefits:**
- Improves financial control and policy compliance
- Reduces overspending risk in organizational purchasing
- Increases transparency for departmental or project-based spend
- Streamlines procurement workflows in one system

**Documentation:**

### Basic shop theming {% include badge.html type=&quot;feature&quot; %}

Business users can now configure core branding elements directly in the Back Office without developer support. This makes it easier to prepare demos, launch storefronts faster, and align Storefront, Back Office, and Merchant Portal branding with company identity.

**Key capabilities:**
- Configures themes through the Back Office configuration experience
- Supports global and store-specific theme management
- Uploads and manages logos for Storefront, Back Office, and Merchant Portal
- Configures core branding colors using standardized design system values
- Applies changes without code changes or deployment

**Business benefits:**
- Reduces dependency on developers for basic branding updates
- Accelerates demo preparation, POCs, and customer onboarding
- Improves time-to-first-transaction
- Increases perceived product maturity and self-service value

**Documentation:**

### Back Office support for merchant product ownership

Marketplace operators can now manage merchant-product ownership directly in the Back Office. This closes an important operational gap for marketplace models where merchant products are not maintained primarily through the Merchant Portal.

**Key capabilities:**
- Supports assigning and changing merchant ownership for products in the Back Office
- Makes merchant assignment visible within product management workflows
- Aligns Back Office product management more closely with marketplace needs

**Business benefits:**
- Improves operational efficiency for marketplace operators
- Increases transparency and auditability of merchant assignments
- Supports centralized and hybrid marketplace operating models
- Reduces the need for custom implementations

**Documentation:**

### Product import and export in the Back Office

We introduced the first phase of product import and export capabilities in the Back Office to reduce dependency on developer-oriented CLI tools. Business users can now work with product catalog data through a more accessible workflow designed for operational and demo use cases.

**Key capabilities:**
- Enables Back Office-based product import and export for product-related data
- Supports reusable jobs and executable runs for import and export workflows
- Processes data asynchronously in batches for large files
- Provides a business-user-friendly file handling approach for creating and updating products

**Business benefits:**
- Reduces developer bottlenecks for catalog onboarding and updates
- Speeds up demo preparation and merchant onboarding
- Supports staging-to-production catalog workflows
- Improves self-service handling of product data operations

**Documentation:**

### Add to cart from image

We packaged and integrated the add-to-cart-from-image capability into the public demo setup. Buyers can use an image containing product identifiers and quantities to speed up quick order creation.

**Key capabilities:**
- Extracts product names or SKUs and quantities from uploaded images
- Auto-fills the quick add-to-cart form based on extracted information
- Uses Spryker AI Foundation for AI integration

**Business benefits:**
- Speeds up bulk and repeat ordering workflows
- Reduces manual entry effort and ordering errors
- Better reflects real-life B2B procurement behaviors in demos
- Improves convenience for busy buyers working from unstructured inputs

**Documentation:**

### Self-Service Portal demo data improvements {% include badge.html type=&quot;improvement&quot; %}

We updated the B2B Marketplace demo shop with more realistic Self-Service Portal sample data. The new data better reflects industry-focused scenarios and helps showcase portal capabilities in a more meaningful way.

**Key capabilities:**
- Adds industry-aligned assets to the demo data set
- Includes related services and spare parts for assets
- Expands inquiry scenarios for general and asset-related use cases
- Populates services, files, models, and CMS-related content to avoid empty states

**Business benefits:**
- Makes demos more relevant to target industries and ICPs
- Improves understanding of Self-Service Portal workflows
- Reduces demo friction for sales, partners, and internal teams
- Strengthens perceived value and product adoption potential

**Documentation:**

### New Spryker Design System for Storefront

We established the next phase of the Storefront design system to create a more consistent and scalable UI foundation. This includes both the token-based design foundation and a reusable composite component layer for common storefront patterns.

**Key capabilities:**
- Defines and structures design tokens for colors, spacing, typography, and related foundations
- Aligns design and frontend engineering on a shared naming and implementation approach
- Introduces reusable composite components such as cards, lists, tabs, menus, breadcrumbs, dialogs, tables, search bars, and filter panels
- Standardizes common UI patterns across browsing, checkout, and account areas

**Business benefits:**
- Improves consistency and usability across the Storefront
- Reduces duplicated UI implementations across teams
- Speeds up frontend delivery and future UI evolution
- Improves demo quality and overall product perception

**Documentation:**

### Back Office design theme update

We delivered the first phase of the Back Office theme modernization to improve consistency, responsiveness, and usability. This update creates a stronger visual foundation for future Back Office improvements while reducing UX debt from legacy styling.

**Key capabilities:**
- Improves visual hierarchy, spacing, and clarity across the Back Office
- Introduces a more consistent component structure and page presentation
- Improves responsiveness and usability of core layouts
- Reduces reliance on fragmented default styling patterns

**Business benefits:**
- Improves trust and confidence in Back Office demos
- Reduces friction in daily operational use
- Creates a more scalable base for future Back Office enhancements
- Lowers customization effort for common visual improvements

**Documentation:**
## Efficient and Flexible Cloud Foundation

### 2026 March-April Cloud Security Improvements {% include badge.html type=&quot;feature&quot; %}

We delivered a set of security enhancements across Spryker Cloud infrastructure to strengthen access control, reduce credential exposure, improve auditability, and modernize the security posture of runtime services. These updates also prepare the platform for more standardized and scalable identity management.

**Key capabilities:**
- Improved scheduled maintenance for Jenkins with gradual patch rollouts and controlled maintenance windows
- Hardened database security through tighter RDS access control, IAM-based authentication for human users, and improved auditability of RDS operations
- Introduced a revamped PaaS role model with composable roles to support standardized access management and future SSO readiness
- Restricted container access to EC2 instance metadata and prevented workloads from inheriting excessive EC2-level permissions
- Documented and aligned a secure process for temporary root access to AWS member accounts with defined roles and responsibilities
- Collected SSH/SFTP and deployment-version usage insights to support security analysis and patch-level visibility
- Added compatibility handling for MariaDB 11.8 secure transport defaults
- Started migration preparation and rollout patterns for Amazon Linux 2023 to address upcoming end-of-life timelines

**Business benefits:**
- Reduces the risk of privilege escalation and unauthorized access from running containers
- Improves traceability and control for sensitive infrastructure and database operations
- Establishes a more secure and scalable foundation for customer access management
- Supports safer maintenance rollouts with less operational risk
- Helps keep cloud environments aligned with supported and secure platform versions

**Documentation:**

### TLS/Auth/SSO for Cloud services (prev. Single-Sign-On for Cloud Services) {% include badge.html type=&quot;feature&quot; %}

We advanced centralized authentication and access management for Spryker Cloud services, including rollout and production-readiness improvements for SSO-enabled access. This work also included IAM policy cleanup, IAM artifact audits, bastion hardening, and stronger guardrails for privileged access in customer PaaS accounts.

**Key capabilities:**
- Rolled out SSO-based access management for cloud services such as Jenkins and RabbitMQ
- Added production-readiness and post-production rollout enhancements for SSO
- Audited IAM roles and policies to identify cleanup and standardization opportunities
- Prevented creation of unrestricted `*:*` IAM policies in customer PaaS accounts through stricter control boundaries
- Hardened bastion hosts with modernized OS support, workload isolation, and enforced SSO/MFA for human access
- Preserved SFTP integration access while deprecating direct SSH-based human access where applicable

**Business benefits:**
- Enables more secure and centralized user lifecycle management
- Reduces manual effort and waiting times for onboarding and offboarding access requests
- Lowers the risk of over-permissioned IAM configurations
- Improves compliance through MFA-backed human access and clearer access boundaries

**Documentation:**

### 2026Q1 Maintenance and service updates {% include badge.html type=&quot;feature&quot; %}

This release delivers maintenance and service updates across core cloud services and application tooling to keep Spryker Cloud environments secure, supported, and maintainable. It includes runtime service upgrades, application dependency updates, and groundwork for lower-downtime RabbitMQ upgrades.

**Key capabilities:**
- Updated critical cloud services, including Jenkins LTS and Nginx
- Replaced Ubuntu-based service components with Amazon Linux where in scope
- Upgraded application tooling with PHPUnit 12 and PHPStan 2.0 support
- Prepared support for RabbitMQ 4.2 and rolled out RabbitMQ 4.1 updates
- Implemented and validated a blue/green approach for RabbitMQ upgrades to reduce downtime and avoid message loss

**Business benefits:**
- Keeps cloud services on supported versions with better security and stability
- Reduces technical debt and maintenance overhead
- Improves developer efficiency through faster tooling and modern test support
- Minimizes disruption during future RabbitMQ service upgrades

**Documentation:**

### Cloud Observability // SMI: Logs forwarding to Dynatrace and others (Bring your own Monitoring) {% include badge.html type=&quot;feature&quot; %}

We added support for forwarding logs through SMI using OpenTelemetry-based integration so customers can correlate logs with traces in their monitoring platform of choice. This includes application logs, Jenkins job logs, RDS slow query logs, and application audit logs, along with metering and monitoring for log transfer.

**Key capabilities:**
- Export logs through SMI for use with Dynatrace and other compatible monitoring tools
- Correlate log entries with traces using standard telemetry fields such as trace and span IDs
- Forward application container logs, Jenkins job logs, RDS slow query logs, and application audit logs
- Support configurable log verbosity to control emitted log volume
- Added SMI metering and monitoring for log shipment usage and operational visibility

**Business benefits:**
- Helps engineering teams investigate issues faster by linking logs to traces
- Enables log-based alerting in external APM and observability platforms
- Improves flexibility for customers using their own monitoring stack
- Supports transparent usage tracking for billing and service monitoring

**Documentation:**
## Other

### Data import and queue processing performance {% include badge.html type=&quot;improvement&quot; %}

We improved long-running data processing flows to make imports and queue workers more transparent, stable, and resource-efficient. This release adds better progress visibility for data imports, reduces memory consumption in large import scenarios, improves queue worker throughput under load, and extends resource-aware queue processing support for Symfony Messenger.

**Key capabilities:**
- Added a progress bar for data import console commands to provide execution visibility.
- Reduced memory consumption in large-volume data imports, including merchant price imports at scale.
- Improved queue worker performance with dynamic waiting time adjustments under load.
- Added support for limiting the number of parallel jobs to improve worker stability and reduce out-of-memory risks.
- Enabled `ResourceAwareQueueWorker` compatibility with the Symfony Messenger adapter.

**Business benefits:**
- Improves observability for long-running import operations.
- Supports larger import volumes with lower memory pressure.
- Increases queue processing throughput and operational stability.
- Gives teams more control over workload tuning in high-volume environments.

**Documentation:**

### Back Office performance improvements {% include badge.html type=&quot;improvement&quot; %}

We improved several Back Office performance hotspots to reduce response times and lower resource consumption in data-heavy and permission-heavy environments. The updates cover ACL navigation checks, order page rendering, product-related lists, and widget rendering behavior.

**Key capabilities:**
- Optimized ACL-related access checks that impacted Back Office navigation rendering on every request.
- Reduced unnecessary permission evaluation overhead, including on requests where navigation is not needed.
- Improved performance of the order detail page for orders with many items.
- Improved responsiveness of product-related Back Office lists in large catalogs.
- Optimized widget rendering to reduce overall page overhead.

**Business benefits:**
- Speeds up the Back Office for users with restricted permissions.
- Improves usability in large-scale merchant and enterprise environments.
- Reduces page load times and infrastructure pressure for high-volume catalogs and order management.

**Documentation:**

### AI configuration management for runtime updates {% include badge.html type=&quot;feature&quot; %}

AI provider configuration values can now be resolved from Configuration Management at runtime. This lets Back Office administrators update selected AI settings, such as model, API key, or system prompt, without requiring code changes or deployments.

**Key capabilities:**
- Added support for resolving AI configuration values using the `configuration::` prefix.
- Enabled recursive runtime resolution for nested AI provider configuration values.
- Added validation and clear exception handling for unresolved configuration references.
- Supports managing AI-related configuration keys through Configuration Management.

**Business benefits:**
- Reduces dependency on deployments for AI configuration changes.
- Gives Back Office administrators more flexibility to tune AI behavior.
- Speeds up experimentation and operational adjustments for AI-powered features.

**Documentation:**

### AI agent instruction file generator {% include badge.html type=&quot;feature&quot; %}

We introduced a new developer command to generate example agent context files for AI-assisted development workflows. The command helps standardize setup for teams using coding agents in their projects.

**Key capabilities:**
- Added the `ai-dev:generate-agents-file` command.
- Generates example `AGENTS.md` or `CLAUDE.md` files for AI agent context.

**Business benefits:**
- Improves developer experience for teams working with AI coding agents.
- Helps standardize project context setup for AI-assisted development.

**Documentation:**

### Platform and security updates {% include badge.html type=&quot;improvement&quot; %}

We updated selected platform dependencies to improve long-term support, security, and maintainability. This includes upgrading frontend tooling to Node.js 24 LTS and updating `symfony/http-foundation` in affected application templates to address known vulnerabilities.

**Key capabilities:**
- Upgraded frontend tooling baseline to Node.js 24 LTS.
- Updated `symfony/http-foundation` to a secure supported version in affected application repositories.

**Business benefits:**
- Improves platform security and dependency health.
- Keeps development tooling on a supported long-term support version.
- Helps reduce maintenance and compliance risks.

**Documentation:**

### Logging improvements {% include badge.html type=&quot;improvement&quot; %}

We added support for non-buffered log streaming. This improves log handling in scenarios where immediate log output is preferred.

**Key capabilities:**
- Added support for streaming logs without buffering.

**Business benefits:**
- Improves log visibility for real-time monitoring and troubleshooting.
- Helps teams react faster during diagnostics and operational review.

**Documentation:**

### Demo analytics enablement {% include badge.html type=&quot;improvement&quot; %}

We enabled Amazon QuickSight support in the master-demo setup to improve demo readiness for analytics scenarios. This ensures demo environments can display analytics content for Back Office users.

**Key capabilities:**
- Enabled Amazon QuickSight integration in the master-demo branch.
- Added analytics asset bundle setup for demo Back Office usage.

**Business benefits:**
- Improves demo quality for analytics-related use cases.
- Makes it easier to showcase business intelligence capabilities in demo environments.

**Documentation:**</description>
            <pubDate>Fri, 17 Apr 2026 10:26:01 +0000</pubDate>
            <link>https://docs.spryker.com/docs/about/all/releases/release-notes-202604.0.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/about/all/releases/release-notes-202604.0.html</guid>
            
            
        </item>
        
        <item>
            <title>Install Search by Image</title>
            <description>Search by Image lets storefront customers upload a photo to find products. AI analyzes the image, identifies a search term, and redirects the customer to the search results page or the first matching product detail page. This document describes how to install the Search by Image feature.

## Install the feature core

Follow the steps in the following sections to install the Search by Image feature core.

### Prerequisites

Install the required features:

| NAME | VERSION | INSTALLATION GUIDE |
|------|---------|-------------------|
| AI Commerce | {{page.release_tag}} | [Install AI Commerce](/docs/dg/dev/ai/ai-commerce/install-ai-commerce.html) |
| Configuration Management | {{page.release_tag}} | [Install the Configuration Management feature](/docs/dg/dev/integrate-and-configure/integrate-confguration-feature.html) |
| Catalog | {{page.release_tag}} | |

### 1) Add translations

Append the glossary according to your configuration:
`data/import/common/common/glossary.csv`

```csv
ai_commerce.search_by_image.form.image.label,Search by image,en_US
ai_commerce.search_by_image.form.image.label,Bildersuche,de_DE
ai_commerce.search_by_image.form.image.error.mime_type,&quot;This image type is not supported. Please upload a JPEG, PNG, WebP, or GIF.&quot;,en_US
ai_commerce.search_by_image.form.image.error.mime_type,&quot;Dieses Bildformat wird nicht unterstützt. Bitte laden Sie ein JPEG, PNG, WebP oder GIF hoch.&quot;,de_DE
ai_commerce.search_by_image.error.no_image_provided,Please select an image to search.,en_US
ai_commerce.search_by_image.error.no_image_provided,Bitte wählen Sie ein Bild für die Suche aus.,de_DE
ai_commerce.search_by_image.error.search_failed,Search by Image failed. Please try again.,en_US
ai_commerce.search_by_image.error.search_failed,Bildsuche fehlgeschlagen. Bitte versuchen Sie es erneut.,de_DE
ai_commerce.search_by_image.error.unavailable,Search by Image is currently unavailable. Please try again later.,en_US
ai_commerce.search_by_image.error.unavailable,Bildsuche ist derzeit nicht verfügbar. Bitte versuchen Sie es später erneut.,de_DE
ai_commerce.search_by_image.error.disabled,Search by Image is currently disabled.,en_US
ai_commerce.search_by_image.error.disabled,Bildsuche ist derzeit deaktiviert.,de_DE
ai_commerce.search_by_image.search,Search,en_US
ai_commerce.search_by_image.search,Suchen,de_DE
ai_commerce.search_by_image.upload_image,Upload image,en_US
ai_commerce.search_by_image.upload_image,Bild hochladen,de_DE
ai_commerce.search_by_image.upload_image_to_find_products,Upload an image to find similar products.,en_US
ai_commerce.search_by_image.upload_image_to_find_products,&quot;Laden Sie ein Bild hoch, um ähnliche Produkte zu finden.&quot;,de_DE
ai_commerce.error.file.size.invalid,&quot;File size is too big.&quot;,en_US
ai_commerce.error.file.size.invalid,&quot;Ungültige Gesamtdateigröße.&quot;,de_DE
ai_commerce.search_by_image.image.description,&quot;Max up to %size% MB. Allowed file formats %format%&quot;,en_US
ai_commerce.search_by_image.image.description,&quot;Maximal bis zu %size%. Erlaubte Dateiformate: %format%&quot;,de_DE
```

Import the data:

```bash
console data:import glossary
```

{% info_block warningBox &quot;Verification&quot; %}

Make sure that the configured data has been added to the `spy_glossary_key` and `spy_glossary_translation` tables.

{% endinfo_block %}

### 2) Set up transfer objects

Generate transfer changes:

```bash
console transfer:generate
```

{% info_block warningBox &quot;Verification&quot; %}

Make sure the following transfers have been created:

| TRANSFER | TYPE | EVENT | PATH |
|----------|------|-------|------|
| SearchByImageRequest | class | created | src/Generated/Shared/Transfer/SearchByImageRequestTransfer.php |
| SearchByImageResponse | class | created | src/Generated/Shared/Transfer/SearchByImageResponseTransfer.php |
| SearchByImagePromptResponse | class | created | src/Generated/Shared/Transfer/SearchByImagePromptResponseTransfer.php |

{% endinfo_block %}

### 3) Register plugins

Register the following plugins:

| PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
|--------|---------------|---------------|-----------|
| SearchByImageRouteProviderPlugin | Registers the routes required for the Search by Image request handling. | | SprykerFeature\Yves\AiCommerce\SearchByImage\Plugin\Router |
| ImageSearchAiWidget | Renders the camera icon and image upload dialog next to the search input. | | SprykerFeature\Yves\AiCommerce\SearchByImage\Widget |

**src/Pyz/Yves/Router/RouterDependencyProvider.php**

```php
&lt;?php

namespace Pyz\Yves\Router;

use SprykerFeature\Yves\AiCommerce\SearchByImage\Plugin\Router\SearchByImageRouteProviderPlugin;
use SprykerShop\Yves\ShopApplication\Plugin\Provider\ShopControllerEventHandlerPlugin;

class RouterDependencyProvider extends SprykerRouterDependencyProvider
{
    /**
     * @return array&lt;\Spryker\Yves\RouterExtension\Dependency\Plugin\RouteProviderPluginInterface&gt;
     */
    protected function getRouteProvider(): array
    {
        return [
            // ...
            new SearchByImageRouteProviderPlugin(),
        ];
    }
}
```

**src/Pyz/Yves/ShopApplication/ShopApplicationDependencyProvider.php**

```php
&lt;?php

namespace Pyz\Yves\ShopApplication;

use SprykerFeature\Yves\AiCommerce\SearchByImage\Widget\ImageSearchAiWidget;
use SprykerShop\Yves\ShopApplication\ShopApplicationDependencyProvider as SprykerShopApplicationDependencyProvider;

class ShopApplicationDependencyProvider extends SprykerShopApplicationDependencyProvider
{
    /**
     * @return array&lt;string&gt;
     */
    protected function getGlobalWidgets(): array
    {
        return [
            // ...
            ImageSearchAiWidget::class,
        ];
    }
}
```

{% info_block warningBox &quot;Verification&quot; %}

Make sure that the `ImageSearchAiWidget` is registered and the camera icon is rendered next to the search bar when the feature is enabled.

{% endinfo_block %}

### 4) Configure AiFoundation for Search by Image

For a base AiFoundation setup, see [Configure AiFoundation](/docs/dg/dev/ai/ai-commerce/install-ai-commerce.html#2-configure-aifoundation).

Using a dedicated AI configuration for Search by Image is recommended because each named configuration is tracked separately in the AiFoundation audit log. This lets you isolate and review all AI calls made by the image search flow independently from other AI features in your project.

To use a dedicated AI model configuration for Search by Image instead of the default one, follow these steps:

1. In `config/Shared/config_ai.php`, add a named configuration entry using `AiCommerceConstants::SEARCH_BY_IMAGE_CONFIGURATION_NAME` as the key:

```php
$config[\Spryker\Shared\AiFoundation\AiFoundationConstants::AI_CONFIGURATIONS][\SprykerFeature\Shared\AiCommerce\AiCommerceConstants::SEARCH_BY_IMAGE_CONFIGURATION_NAME] = $openAiConfiguration;
```

2. Return the configuration name from `AiCommerceConfig`:

**src/Pyz/Yves/AiCommerce/AiCommerceConfig.php**

```php
&lt;?php

namespace Pyz\Yves\AiCommerce;

use SprykerFeature\Shared\AiCommerce\AiCommerceConstants;
use SprykerFeature\Yves\AiCommerce\AiCommerceConfig as SprykerAiCommerceConfig;

class AiCommerceConfig extends SprykerAiCommerceConfig
{
    public function getSearchByImageAiConfigurationName(): ?string
    {
        return AiCommerceConstants::SEARCH_BY_IMAGE_CONFIGURATION_NAME;
    }
}
```

### 5) Sync configuration

Sync the Search by Image configuration to the database:

```bash
console configuration:sync
```

### 6) Enable the feature

Enable the feature in the Back Office:

1. In the Back Office, go to **AI Commerce&amp;nbsp;&lt;span aria-label=&quot;and then&quot;&gt;&gt;&lt;/span&gt;&amp;nbsp;Search by Image&amp;nbsp;&lt;span aria-label=&quot;and then&quot;&gt;&gt;&lt;/span&gt;&amp;nbsp;Search by Image**.
2. Turn on **Enable Search by Image**.
3. Set **Redirect type** to the desired behavior:
   - **Search results** — redirects the customer to the catalog search results page for the identified search term.
   - **First result product detail page** — redirects the customer directly to the product detail page of the first matching result.
4. Click **Save**.

![Search by Image configuration](https://spryker.s3.eu-central-1.amazonaws.com/docs/dg/dev/ai-commerce/search-by-image-config.png)

{% info_block warningBox &quot;Verification&quot; %}

On the Storefront, make sure the camera icon is visible next to the search bar.

{% endinfo_block %}

## Integrate the feature frontend

{% info_block infoBox &quot;Note&quot; %}

The Twig template changes in this section reflect the current implementation. These templates may be updated in future releases. Review the latest demo shop templates before applying them at the project level.

{% endinfo_block %}

### 1) Add icon sprites

{% info_block infoBox &quot;Info&quot; %}

Do this step only if you have overridden `icon-sprite.twig` in the `ShopUi` module at the project level. If you have not overridden this template, skip to [2) Update the search form template](#2-update-the-search-form-template).

{% endinfo_block %}

In `src/Pyz/Yves/ShopUi/Theme/default/components/atoms/icon-sprite/icon-sprite.twig`, add the following SVG symbol definitions inside the `{% raw %}{% block sprite %}{% endraw %}` block:

```twig
{% raw %}
&lt;symbol id=&quot;:upload-image&quot; viewBox=&quot;0 -960 960 960&quot; fill=&quot;currentColor&quot;&gt;
    &lt;title id=&quot;:upload-image&quot;&gt;Upload Image&lt;/title&gt;
    &lt;path d=&quot;M480-480ZM224.62-160q-27.62 0-46.12-18.5Q160-197 160-224.62v-510.76q0-27.62 18.5-46.12Q197-800 224.62-800h280v40h-280q-10.77 0-17.7 6.92-6.92 6.93-6.92 17.7v510.76q0 10.77 6.92 17.7 6.93 6.92 17.7 6.92h510.76q10.77 0 17.7-6.92 6.92-6.93 6.92-17.7v-280h40v280q0 27.62-18.5 46.12Q763-160 735.38-160H224.62Zm46.15-144.62h418.46L560-476.92 440-325.38l-80-96.16-89.23 116.92ZM680-600v-80h-80v-40h80v-80h40v80h80v40h-80v80h-40Z&quot;/&gt;
&lt;/symbol&gt;
&lt;symbol id=&quot;:visual-search&quot; viewBox=&quot;0 -960 960 960&quot; fill=&quot;currentColor&quot;&gt;
    &lt;title id=&quot;:visual-search&quot;&gt;Visual Search&lt;/title&gt;
    &lt;path d=&quot;M367-367q-47-47-47-113t47-113q47-47 113-47t113 47q47 47 47 113t-47 113q-47 47-113 47t-113-47Zm169.5-56.5Q560-447 560-480t-23.5-56.5Q513-560 480-560t-56.5 23.5Q400-513 400-480t23.5 56.5Q447-400 480-400t56.5-23.5ZM480-480ZM200-120q-33 0-56.5-23.5T120-200v-160h80v160h160v80H200Zm400 0v-80h160v-160h80v160q0 33-23.5 56.5T760-120H600ZM120-600v-160q0-33 23.5-56.5T200-840h160v80H200v160h-80Zm640 0v-160H600v-80h160q33 0 56.5 23.5T840-760v160h-80Z&quot;/&gt;
&lt;/symbol&gt;
{% endraw %}
```

### 2) Update the search form template

{% info_block infoBox &quot;Info&quot; %}

Do this step only if you have overridden `search-form.twig` in the `ShopUi` module at the project level. If you have not overridden this template, skip to [3) Update the header template](#3-update-the-header-template).

{% endinfo_block %}

In `src/Pyz/Yves/ShopUi/Theme/default/components/molecules/search-form/search-form.twig`, add the `ImageSearchAiWidget` inside the search input area. Place it after the `&lt;input&gt;` element and before the submit button:

```twig
{% raw %}
{% if data.byImage and widgetGlobalExists(&apos;ImageSearchAiWidget&apos;) %}
    {% widget &apos;ImageSearchAiWidget&apos; with {
        data: {
            dataSearchId: attributes[&apos;data-search-id&apos;],
        },
    } only %}{% endwidget %}
{% endif %}
{% endraw %}
```

### 3) Update the header template

{% info_block infoBox &quot;Info&quot; %}

Do this step only if you have overridden `header.twig` in the `ShopUi` module at the project level. If you have not overridden this template, skip to [6) Apply the frontend changes](#6-apply-the-frontend-changes).

{% endinfo_block %}

In `src/Pyz/Yves/ShopUi/Theme/default/components/organisms/header/header.twig`, pass `byImage: true` in the `data` block when including the search form molecule:

```twig
{% raw %}
{% include molecule(&apos;search-form&apos;, &apos;SearchPage&apos;) with {
    ...
    data: {
        byImage: true,
    },
} only %}
{% endraw %}
```

### 4) Add the project-level component files

Create the following project-level files to register and style the `search-by-image` component.

**src/Pyz/Yves/AiCommerce/Theme/default/components/molecules/search-by-image/index.ts**

```ts
import &apos;./search-by-image&apos;;
import register from &apos;ShopUi/app/registry&apos;;

export default register(
    &apos;search-by-image&apos;,
    () =&gt;
        import(
            /* webpackMode: &quot;lazy&quot; */
            /* webpackChunkName: &quot;search-by-image&quot; */
            &apos;AiCommerce/components/molecules/search-by-image/search-by-image&apos;
        ),
);
```

**src/Pyz/Yves/AiCommerce/Theme/default/components/molecules/search-by-image/search-by-image.scss**

```scss
@include ai-commerce-search-by-image {
    position: absolute;
    right: rem(40);
    top: 50%;
    translate: 0 -50%;
    z-index: $setting-zi-search-suggestions + 2;

    @include helper-breakpoint(lg) {
        right: rem(10);
    }

    &amp;__popup-trigger {
        @include helper-effect-transition(rotate);
        border: none;
        width: rem(32);
        height: rem(32);
        background: none;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;

        &amp;:hover {
            rotate: 90deg;
        }
    }
}
```

**src/Pyz/Yves/AiCommerce/Theme/default/components/molecules/search-by-image/search-by-image.twig**

```twig
{% raw %}
{% extends molecule(&apos;search-by-image&apos;, &apos;@SprykerFeature:AiCommerce&apos;) %}

{% block triggerFileButton %}
    {% set triggerButtonClassname = &quot;search-by-image__popup-trigger search-by-image__popup-trigger--#{data.dataSearchId}&quot; %}
    {{ parent() }}
{% endblock %}

{% block triggerPhotoButton %}
    {% set triggerButtonClassname = &quot;search-by-image__popup-trigger search-by-image__popup-trigger--#{data.dataSearchId}&quot; %}
    {{ parent() }}
{% endblock %}
{% endraw %}
```

### 5) Update TypeScript configuration

In `tsconfig.yves.json`, add the `AiCommerce/*` path alias to the `compilerOptions.paths` section:

```json
&quot;AiCommerce/*&quot;: [&quot;./vendor/spryker-feature/ai-commerce/src/SprykerFeature/Yves/AiCommerce/Theme/default/*&quot;]
```

{% info_block warningBox &quot;Verification&quot; %}

Make sure the `AiCommerce/*` entry is added alongside the other module path aliases in the `paths` object.

{% endinfo_block %}

### 6) Apply the frontend changes

Apply the frontend changes:

```bash
docker/sdk cli npm install
docker/sdk cli console frontend:project:install-dependencies
docker/sdk cli console frontend:yves:build
```

{% info_block warningBox &quot;Verification&quot; %}

On the Storefront, make sure the camera icon is displayed next to the search bar. Click the icon, upload an image, and verify that you are redirected to either the search results page or the matching product detail page, depending on the configured redirect type.

{% endinfo_block %}
</description>
            <pubDate>Fri, 10 Apr 2026 12:25:48 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/ai/ai-commerce/search-by-image/install-search-by-image.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/ai/ai-commerce/search-by-image/install-search-by-image.html</guid>
            
            
        </item>
        
        <item>
            <title>Search by Image</title>
            <description>Search by Image lets customers find products by uploading a photo. A camera icon next to the search input opens an image upload dialog. After the image is uploaded, AI analyzes it, identifies a relevant search term, and redirects the customer — either to the catalog search results page or directly to the first matching product detail page (PDP).

**Use case:** A customer sees a product they want to buy but does not know what it is called. They photograph the product and upload the image using the Search by Image button. The system identifies the product and takes the customer directly to the matching product or a list of similar results.

Accepted file formats: JPEG, PNG, WebP, and GIF.

## Use Search by Image on the Storefront

1. On any page with the search bar, click the camera icon next to the search input.

   ![Search by Image button](https://spryker.s3.eu-central-1.amazonaws.com/docs/dg/dev/ai-commerce/search-by-image-button.png)

2. In the dialog that opens, click **Upload image** and select a photo from your device or take a new one using your smartphone camera.

   ![Search by Image upload dialog](https://spryker.s3.eu-central-1.amazonaws.com/docs/dg/dev/ai-commerce/search-by-image-upload.png)

3. The system analyzes the image and redirects you to the search results or the matching product page.

   ![Search by Image results](https://spryker.s3.eu-central-1.amazonaws.com/docs/dg/dev/ai-commerce/search-by-image-results.png)

## Enable Search by Image

To enable the feature, in the Back Office, go to **AI Commerce&amp;nbsp;&lt;span aria-label=&quot;and then&quot;&gt;&gt;&lt;/span&gt;&amp;nbsp;Search by Image&amp;nbsp;&lt;span aria-label=&quot;and then&quot;&gt;&gt;&lt;/span&gt;&amp;nbsp;Search by Image** and turn on **Enable Search by Image**.

![Search by Image configuration](https://spryker.s3.eu-central-1.amazonaws.com/docs/dg/dev/ai-commerce/search-by-image-config.png)

## Configure the redirect behavior

After enabling Search by Image, you can control where customers land after a successful image search. In the same settings group, set **Redirect type** to one of the following options:

| OPTION | DESCRIPTION |
|--------|-------------|
| Search results | Redirects the customer to the catalog search results page for the identified search term. This is the default. |
| First result product detail page | Redirects the customer directly to the PDP of the first matching product. |

## Developer resources

| RESOURCE | DESCRIPTION |
|----------|-------------|
| [Search by Image](/docs/dg/dev/ai/ai-commerce/search-by-image/search-by-image.html) | Technical overview: architecture, configuration options, and AiFoundation integration. |
| [Install Search by Image](/docs/dg/dev/ai/ai-commerce/search-by-image/install-search-by-image.html) | Step-by-step installation guide. |
</description>
            <pubDate>Fri, 10 Apr 2026 12:20:13 +0000</pubDate>
            <link>https://docs.spryker.com/docs/pbc/all/ai-commerce/latest/search-by-image.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/pbc/all/ai-commerce/latest/search-by-image.html</guid>
            
            
        </item>
        
        <item>
            <title>Search by Image</title>
            <description>Search by Image lets storefront customers find products by uploading a photo. AI analyzes the image, identifies a search term, and redirects the customer to either a catalog search results page or the first matching product detail page (PDP).

For the business overview and storefront usage, see [Search by Image](/docs/pbc/all/ai-commerce/latest/search-by-image.html).

## Architecture

The feature is built on the `AiFoundation` abstraction layer, which decouples the image analysis logic from any specific AI provider. The AI model and provider are configured per named configuration entry, so you can swap or reconfigure them without changing application code.

The Yves-side widget `ImageSearchAiWidget` renders the camera icon and the image upload dialog next to the search input. Routing is handled by `SearchByImageRouteProviderPlugin`. After the AI returns a search term, the redirect target is determined by the Back Office configuration — either the catalog search results page or the PDP of the first matching result.

## How it works

1. The customer clicks the camera icon next to the search bar.
2. The customer uploads an image.
3. The system validates the file format and size.
4. The image is encoded and sent to the AI model via the `AiFoundation` abstraction layer.
5. The AI returns a search term derived from the image content.
6. Depending on the configured redirect type, the customer is sent to:
   - The catalog search results page for the identified search term, or
   - The PDP of the first matching product.

## Configuration

The following options can be configured at the project level in `AiCommerceConfig`:

| CONFIGURATION | DEFAULT | DESCRIPTION |
|---------------|---------|-------------|
| `isSearchByImageEnabled()` | `false` | Enables or disables the feature. Controlled via the Back Office. |
| `getSearchByImageSupportedMimeTypes()` | `image/jpeg`, `image/png`, `image/webp`, `image/gif` | Allowed upload MIME types. |
| `getSearchByImageMaxFileSizeInBytes()` | Defined in `AiCommerceConfig` | Maximum upload file size in bytes. |
| `getSearchByImageAiConfigurationName()` | `null` | Named AI model configuration identifier used to look up the provider config from `AiFoundation`. When `null`, the default configuration is used. |
| `getSearchByImageRedirectType()` | `search_results` | Controls the redirect target after a successful image search. Controlled via the Back Office. |

## Install

[Install Search by Image](/docs/dg/dev/ai/ai-commerce/search-by-image/install-search-by-image.html)
</description>
            <pubDate>Fri, 10 Apr 2026 12:20:13 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/ai/ai-commerce/search-by-image/search-by-image.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/ai/ai-commerce/search-by-image/search-by-image.html</guid>
            
            
        </item>
        
        <item>
            <title>AI Commerce</title>
            <description>&lt;p&gt;AI Commerce brings AI-powered capabilities to your Spryker storefront, reducing manual effort for buyers and accelerating commerce workflows. Features are built on the &lt;code&gt;AiFoundation&lt;/code&gt; abstraction layer, so the underlying AI model can be swapped or configured per feature without changing application code.&lt;/p&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;FEATURE&lt;/th&gt;
&lt;th&gt;DESCRIPTION&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;/docs/pbc/all/ai-commerce/latest/visual-add-to-cart.html&quot;&gt;Visual Add to Cart&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Lets buyers upload a product image on the Quick Order page. AI recognizes the products in the image and pre-fills the order form with matching SKUs and quantities — enabling rapid bulk ordering without manual entry.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;/docs/pbc/all/ai-commerce/latest/backoffice-assistant.html&quot;&gt;Back Office Assistant&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;An AI-powered chat widget embedded in the Back Office. Admin users can ask natural language questions to navigate the Back Office, diagnose order issues, and create or update discounts.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;/docs/pbc/all/ai-commerce/latest/search-by-image.html&quot;&gt;Search by Image&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Lets customers upload a photo to search for products. AI analyzes the image, identifies a search term, and redirects to search results or the first matching product page.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;who-benefits&quot;&gt;Who benefits&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ROLE&lt;/th&gt;
&lt;th&gt;BENEFIT&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;B2B buyers&lt;/td&gt;
&lt;td&gt;Faster reordering from photos of shelves, product lists, or packaging. Find products by uploading a photo instead of searching by name.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Store operators&lt;/td&gt;
&lt;td&gt;Reduced support requests caused by manual order entry errors. Faster Back Office workflows through conversational AI assistance.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Developers&lt;/td&gt;
&lt;td&gt;AI provider-agnostic integration — swap or configure models per feature via configuration.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</description>
            <pubDate>Fri, 10 Apr 2026 12:20:13 +0000</pubDate>
            <link>https://docs.spryker.com/docs/pbc/all/ai-commerce/latest/ai-commerce.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/pbc/all/ai-commerce/latest/ai-commerce.html</guid>
            
            
        </item>
        
        <item>
            <title>Set up DNS</title>
            <description>To make your application accessible through your own domain, configure DNS records that point your domain to the Spryker-managed endpoint.

In most cases, this means adding a `CNAME` record in your DNS management for the domain you want to use. Spryker provides the target values as part of the setup process.

## Before you start

Before requesting DNS setup:

- Make sure the endpoint you want to use is final.
- Make sure the endpoint has been tested and approved internally.
- Make sure the `deploy.yml` file you provide to Spryker is the same file that will later be used for the Normal or Destructive deployment pipeline.
- Be aware that DNS setup is not immediate and can take up to a week to complete.

{% info_block infoBox &quot;Info&quot; %}

This process can take up to a full week because it includes both DNS propagation time and Spryker infrastructure work. To avoid rework, submit only final endpoint selections.

{% endinfo_block %}

## DNS setup process

The DNS setup usually follows these steps:

1. Add the endpoint you want to use to the appropriate `deploy.yml` file. For example, add a new endpoint under the desired application in your `deploy.yml`:

    ```yaml
    groups:
        EU:
            region: EU
            applications:
                yves:
                    application: yves
                    endpoints:
                        www.example.com:
                            store: DE
    ```

2. Create a support case and provide the `deploy.yml` file that contains the endpoint configuration. For example: &quot;We have added the endpoint `www.example.com` to our `deploy.yml` and would like to set up DNS for it.&quot;
3. Ensure that this is the same `deploy.yml` file that will later be used for the Normal or Destructive deployment pipeline.
4. Spryker prepares the endpoint configuration and sends you the DNS records required for TLS verification. For example, you may receive a `CNAME` record like `_acme-challenge.www.example.com` pointing to a validation target.
5. Add the provided TLS verification records in your DNS management.
6. After the records are in place and have propagated, notify Spryker Support.
7. Spryker completes the infrastructure configuration.
8. Spryker sends you the final DNS target values, usually `CNAME` records, that must be added in your DNS management. For example: `www.example.com CNAME xxx.elb.amazonaws.com`. Root domains are treated differently — see [Root domain configuration](#root-domain-configuration).
9. After the DNS records are added and propagated, your application becomes accessible through the new domain.
10. Trigger the Normal or Destructive deployment pipeline using the same `deploy.yml` file that was provided to Spryker.

## Important: Configuration changes are staged

DNS-related endpoint changes are prepared first, but they do not become active immediately.

After Spryker prepares the new endpoint configuration, the change remains staged until a deployment pipeline is triggered.

This is especially important for infrastructure components that support only one active endpoint at a time.

## Critical constraint for Scheduler and Queue endpoints

The following services support only **one active endpoint configuration at a time**:

- Scheduler (`Jenkins`)
- Queue (`RabbitMQ`)

When a new domain endpoint is configured for either of these services, the previous endpoint is replaced. It is not kept in parallel.

Dual-domain operation is **not supported** for these components.

{% info_block warningBox &quot;Warning&quot; %}

If a deployment is triggered before the required DNS records are fully added and propagated, `Jenkins` and `RabbitMQ` can become unreachable because their previous endpoints will already have been replaced.

{% endinfo_block %}

## Safe activation sequence

Do **not** trigger deployment immediately after receiving the DNS records from Spryker.

Before triggering a Normal or Destructive deployment pipeline:

1. Confirm that the pipeline will use the same `deploy.yml` file that was provided to Spryker for DNS setup.
2. Add all required TLS verification records.
3. Add all required final DNS records at your registrar or DNS provider.
4. Verify that DNS propagation is complete.
5. Notify Spryker Support that DNS setup is complete.
6. Wait for confirmation from Spryker that the infrastructure-side setup is finished.
7. Only then trigger the deployment pipeline.

## Recommended pre-deployment checklist

Before triggering deployment for a new domain or domain migration, confirm all of the following:

- The `deploy.yml` file used for deployment is the same one that was provided to Spryker for DNS setup.
- TLS verification records were added.
- Final DNS records were added at the registrar or DNS provider.
- DNS propagation was verified, for example with `dig` or another DNS checker.
- Spryker Support was notified that DNS setup is complete.
- Spryker confirmed that the infrastructure configuration is complete.

Only after all items are completed should deployment be triggered.

## Root domain configuration

If you want to use a root domain such as `example.com`, use an `A` record instead of a `CNAME` record.

In this case, contact Spryker so the team can provide the correct IP address to use.

Do **not** use the load balancer IP addresses directly as your `A` record target, because those IP addresses are subject to rotation.

## NS record delegation

Spryker does not normally support full DNS delegation.

Do **not** change your domain&apos;s `NS` records to delegate the full DNS zone to Spryker unless explicitly instructed by Spryker.

## Troubleshooting and practical notes

### Adding the endpoint to deploy.yml does not make it active

Adding the endpoint in code only starts the setup flow. The endpoint becomes active only after the DNS setup is complete and deployment is triggered.

### The deploy.yml file must match the one shared for DNS setup

The `deploy.yml` file used in the Normal or Destructive deployment pipeline must match the one provided to Spryker during the DNS setup process. Otherwise, the deployed configuration may not match the DNS configuration prepared by Spryker.

### Old and new domains cannot be active at the same time for Jenkins or RabbitMQ

These services support only one active endpoint configuration at a time.

### Biggest risk: premature deployment or mismatched deploy.yml

The main risk is triggering deployment too early or using a different `deploy.yml` file than the one shared with Spryker. If DNS records are not fully in place and propagated, or if the deployed configuration does not match the prepared DNS setup, `Jenkins` and `RabbitMQ` can become unavailable.

### Verifying DNS propagation

You can verify propagation with tools such as `dig` or another public DNS checker. Check that the records returned publicly match the values provided by Spryker.
</description>
            <pubDate>Thu, 09 Apr 2026 12:35:13 +0000</pubDate>
            <link>https://docs.spryker.com/docs/ca/dev/set-up-dns.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/ca/dev/set-up-dns.html</guid>
            
            
        </item>
        
        <item>
            <title>Install the Basic Shop Theme feature</title>
            <description>This document describes how to install the Basic Shop Theme feature.

The feature lets Business Admins configure logos, theme colors, and custom CSS for the Storefront, Back Office, and Merchant Portal directly from the Back Office.

## Prerequisites

Before installing this feature, install and configure the following:

| NAME | VERSION | INTEGRATION GUIDE |
|------|---------|-------------------|
| Configuration Management feature | ^0.1.0 | [Install the Configuration Management feature](/docs/dg/dev/integrate-and-configure/integrate-confguration-feature.html) |
| Spryker Core | ^3.82 | — |

## Install feature core

### 1) Install the required modules

Install the required modules using Composer:

```bash
composer require spryker/gui:&quot;^3.0.0&quot; spryker/zed-ui:&quot;^2.0.0&quot; spryker-shop/shop-ui:&quot;^1.0.0&quot; symfony/html-sanitizer:&quot;^7.4&quot; --update-with-dependencies
```

{% info_block warningBox &quot;Verification&quot; %}

Make sure the following modules have been installed:

| MODULE | EXPECTED DIRECTORY |
|--------|-------------------|
| Gui | vendor/spryker/gui |
| ZedUi | vendor/spryker/zed-ui |
| ShopUi | vendor/spryker-shop/shop-ui |
| symfony/html-sanitizer | vendor/symfony/html-sanitizer |

{% endinfo_block %}

### 2) Sync the theme configuration schema

Run the configuration sync command to register the theme settings in the Back Office:

```bash
console configuration:sync
```

{% info_block warningBox &quot;Verification&quot; %}

1. Log in to the Back Office.
2. Navigate to **Configuration**.
3. Verify that the **Theme** feature appears in the sidebar with four tabs: **Storefront**, **Back Office**, **Merchant Portal**, and **Logos**.

{% endinfo_block %}

### 3) Set up behavior

The `configurationValue()` and `configurationValues()` Twig functions are made available by existing plugins that are already registered in a standard Spryker installation:

- **Storefront (Yves)**: `ShopUiTwigExtension`
- **Back Office and Merchant Portal (Zed)**: `\Spryker\Zed\Twig\Communication\Plugin\Application\TwigApplicationPlugin`

No additional Twig plugin registration is required.

#### 3.1) Register ACL plugins for Merchant Portal

Register the ACL entity configuration and rule expander plugins so that Merchant Portal users can read theme configuration values through the ACL layer:

| PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
|--------|---------------|---------------|-----------|
| ConfigurationValueAclEntityConfigurationExpanderPlugin | Expands the ACL entity configuration with `ConfigurationValue` entity rules for Merchant Portal access. | None | Spryker\Zed\Configuration\Communication\Plugin\AclMerchantPortal |
| ConfigurationValueMerchantAclEntityRuleExpanderPlugin | Expands the Merchant ACL entity rule set to allow Merchant Portal users to read published configuration values. | None | Spryker\Zed\Configuration\Communication\Plugin\AclMerchantPortal |

**src/Pyz/Zed/AclMerchantPortal/AclMerchantPortalDependencyProvider.php**

Add the import statements:

```php
use Spryker\Zed\Configuration\Communication\Plugin\AclMerchantPortal\ConfigurationValueAclEntityConfigurationExpanderPlugin;
use Spryker\Zed\Configuration\Communication\Plugin\AclMerchantPortal\ConfigurationValueMerchantAclEntityRuleExpanderPlugin;
```

Register the plugins in the respective methods:

```php
protected function getAclEntityConfigurationExpanderPlugins(): array
{
    return [
        // ...
        new ConfigurationValueAclEntityConfigurationExpanderPlugin(),
    ];
}

protected function getMerchantAclEntityRuleExpanderPlugins(): array
{
    return [
        // ...
        new ConfigurationValueMerchantAclEntityRuleExpanderPlugin(),
    ];
}
```

{% info_block warningBox &quot;Verification&quot; %}

Log in to the Merchant Portal and navigate to any page. Verify there are no ACL-related errors in the application log.

{% endinfo_block %}

### 4) Configure media filesystems

The logo upload feature requires three Flysystem filesystem services: one per application context. Configure them in your shared config and provide local overrides for development and CI environments.

#### 4.1) Add filesystem services to the shared config

Add the three media filesystem services to `config/Shared/config_default.php`. In production, they read from S3 using the `SPRYKER_S3_PUBLIC_ASSETS_*` environment variables.

**config/Shared/config_default.php**

Add the three media filesystem entries inside the existing `$config[FileSystemConstants::FILESYSTEM_SERVICE]` array:

```php
$config[FileSystemConstants::FILESYSTEM_SERVICE] = [
    // ... existing entries ...
    &apos;backoffice-media&apos; =&gt; [
        &apos;sprykerAdapterClass&apos; =&gt; Aws3v3FilesystemBuilderPlugin::class,
        &apos;key&apos; =&gt; getenv(&apos;SPRYKER_S3_PUBLIC_ASSETS_KEY&apos;) ?: &apos;&apos;,
        &apos;bucket&apos; =&gt; getenv(&apos;SPRYKER_S3_PUBLIC_ASSETS_BUCKET&apos;) ?: &apos;&apos;,
        &apos;secret&apos; =&gt; getenv(&apos;SPRYKER_S3_PUBLIC_ASSETS_SECRET&apos;) ?: &apos;&apos;,
        &apos;root&apos; =&gt; &apos;/backoffice-media&apos;,
        &apos;path&apos; =&gt; &apos;/&apos;,
        &apos;version&apos; =&gt; &apos;latest&apos;,
        &apos;region&apos; =&gt; getenv(&apos;AWS_REGION&apos;),
    ],
    &apos;storefront-media&apos; =&gt; [
        &apos;sprykerAdapterClass&apos; =&gt; Aws3v3FilesystemBuilderPlugin::class,
        &apos;key&apos; =&gt; getenv(&apos;SPRYKER_S3_PUBLIC_ASSETS_KEY&apos;) ?: &apos;&apos;,
        &apos;bucket&apos; =&gt; getenv(&apos;SPRYKER_S3_PUBLIC_ASSETS_BUCKET&apos;) ?: &apos;&apos;,
        &apos;secret&apos; =&gt; getenv(&apos;SPRYKER_S3_PUBLIC_ASSETS_SECRET&apos;) ?: &apos;&apos;,
        &apos;root&apos; =&gt; &apos;/storefront-media&apos;,
        &apos;path&apos; =&gt; &apos;&apos;,
        &apos;version&apos; =&gt; &apos;latest&apos;,
        &apos;region&apos; =&gt; getenv(&apos;AWS_REGION&apos;),
    ],
    &apos;merchant-portal-media&apos; =&gt; [
        &apos;sprykerAdapterClass&apos; =&gt; Aws3v3FilesystemBuilderPlugin::class,
        &apos;key&apos; =&gt; getenv(&apos;SPRYKER_S3_PUBLIC_ASSETS_KEY&apos;) ?: &apos;&apos;,
        &apos;bucket&apos; =&gt; getenv(&apos;SPRYKER_S3_PUBLIC_ASSETS_BUCKET&apos;) ?: &apos;&apos;,
        &apos;secret&apos; =&gt; getenv(&apos;SPRYKER_S3_PUBLIC_ASSETS_SECRET&apos;) ?: &apos;&apos;,
        &apos;root&apos; =&gt; &apos;/merchant-portal-media&apos;,
        &apos;path&apos; =&gt; &apos;&apos;,
        &apos;version&apos; =&gt; &apos;latest&apos;,
        &apos;region&apos; =&gt; getenv(&apos;AWS_REGION&apos;),
    ],
];
```

#### 4.2) Add local filesystem fallback for development

In the development environment, override the three filesystem services with a local adapter when the S3 bucket is not configured. This stores uploaded files under `public/Yves/assets/static/images` and serves them via the Yves assets path.

**config/Shared/config_default-docker.dev.php**

Add the import statement:

```php
use Spryker\Shared\Flysystem\FlysystemConstants;
```

Add the following block in the filesystem section:

```php
if (!getenv(&apos;SPRYKER_S3_PUBLIC_ASSETS_BUCKET&apos;)) {
    $publicUrl = sprintf(
        &apos;%s%s&apos;,
        $config[ApplicationConstants::BASE_URL_YVES],
        &apos;/assets/static/images&apos;,
    );

    $localMediaFilesystemConfig = [
        &apos;sprykerAdapterClass&apos; =&gt; LocalFilesystemBuilderPlugin::class,
        &apos;root&apos; =&gt; APPLICATION_ROOT_DIR . &apos;/public/Yves/assets/static/images&apos;,
        &apos;path&apos; =&gt; &apos;&apos;,
    ];

    $config[FileSystemConstants::FILESYSTEM_SERVICE][&apos;backoffice-media&apos;] = $localMediaFilesystemConfig;
    $config[FileSystemConstants::FILESYSTEM_SERVICE][&apos;storefront-media&apos;] = $localMediaFilesystemConfig;
    $config[FileSystemConstants::FILESYSTEM_SERVICE][&apos;merchant-portal-media&apos;] = $localMediaFilesystemConfig;
    $config[FlysystemConstants::FLYSYSTEM_OPTIONS] = [
        &apos;public_url&apos; =&gt; $publicUrl,
    ];
}
```

#### 4.3) Add local filesystem fallback for CI

**config/Shared/config_default-docker.ci.php**

Add the import statements:

```php
use Spryker\Shared\Application\ApplicationConstants;
use Spryker\Shared\Flysystem\FlysystemConstants;
```

Add the `$localMediaFilesystemConfig` variable before the `$config[FileSystemConstants::FILESYSTEM_SERVICE]` array, and add the three services as entries inside that array. After the array, add the public URL config:

```php
$localMediaFilesystemConfig = [
    &apos;sprykerAdapterClass&apos; =&gt; LocalFilesystemBuilderPlugin::class,
    &apos;root&apos; =&gt; APPLICATION_ROOT_DIR . &apos;/public/Yves/assets/static/images&apos;,
    &apos;path&apos; =&gt; &apos;&apos;,
];

$config[FileSystemConstants::FILESYSTEM_SERVICE] = [
    // ... existing entries ...
    &apos;backoffice-media&apos; =&gt; $localMediaFilesystemConfig,
    &apos;storefront-media&apos; =&gt; $localMediaFilesystemConfig,
    &apos;merchant-portal-media&apos; =&gt; $localMediaFilesystemConfig,
];

$publicUrl = sprintf(
    &apos;%s%s&apos;,
    $config[ApplicationConstants::BASE_URL_YVES],
    &apos;/assets/static/images&apos;,
);

$config[FlysystemConstants::FLYSYSTEM_OPTIONS] = [
    &apos;public_url&apos; =&gt; $publicUrl,
];
```

{% info_block warningBox &quot;Verification&quot; %}

1. Log in to the Back Office.
2. Navigate to **Configuration &gt; Theme &gt; Logos**.
3. Upload a logo image using the file upload widget.
4. Verify the uploaded file is accessible at the public URL shown after upload.

{% endinfo_block %}

### 5) Clear caches

Clear the Twig cache and application cache to apply the new Twig functions:

```bash
console twig:cache:warmer
console cache:clear
```

## Configure the feature

After installing the feature, configure branding settings in the Back Office:

1. Log in to the Back Office.
2. Go to **Configuration &gt; Theme**.
3. Select the tab for the context you want to configure: **Storefront**, **Back Office**, **Merchant Portal**, or **Logos**.
4. Enter the desired values and click **Save**.

Changes to Storefront settings are published to key-value storage automatically. Back Office and Merchant Portal settings take effect on the next page load.

### Logo upload fields

Logo settings support direct file upload from the Back Office. Uploaded files are stored via the corresponding Flysystem media filesystem service (`storefront-media`, `backoffice-media`, `merchant-portal-media`) and served from the configured `public_url`.

| Context | Setting | Recommended size | Supported formats | Filesystem service |
|---------|---------|-----------------|-------------------|--------------------|
| Storefront | Storefront Logo | 186×50 px | GIF, PNG, JPEG, BMP, WebP, SVG | `storefront-media` |
| Back Office | Back Office Logo | 186×50 px | GIF, PNG, JPEG, BMP, WebP, SVG | `backoffice-media` |
| Merchant Portal | Merchant Portal Logo | 186×50 px | GIF, PNG, JPEG, BMP, WebP, SVG | `merchant-portal-media` |

In production, configure the `SPRYKER_S3_PUBLIC_ASSETS_BUCKET`, `SPRYKER_S3_PUBLIC_ASSETS_KEY`, `SPRYKER_S3_PUBLIC_ASSETS_SECRET`, and `AWS_REGION` environment variables to point to an S3 bucket (or compatible object storage). In development and CI, files are stored locally at `public/Yves/assets/static/images`.

### Store-level overrides

To configure a per-store override:

1. In the scope selector at the top of the Configuration page, switch from **Default** to the target store (for example, **DE**).
2. Adjust the setting value.
3. Click **Save**.

Stores without a store-level value inherit the global (Default) value.

## Theme configuration key reference

The following theme settings are registered by the feature&apos;s YAML schema. Use their compound keys in `configurationValue()` Twig calls or via `getModuleConfig()` in a module Config class.

| Compound Key | Context | Type | Default |
|-------------|---------|------|---------|
| `theme:storefront:colors:background_brand_primary` | Storefront | color | `#00bebe` |
| `theme:storefront:colors:background_brand_subtle` | Storefront | color | `#eb553c` |
| `theme:storefront:custom_css:yves_custom_css` | Storefront | text | (empty) |
| `theme:logos:logos:yves_logo_url` | Storefront | file | (empty) |
| `theme:backoffice:colors:bo_main_color` | Back Office | color | `#1ebea0` |
| `theme:backoffice:colors:bo_sidenav_color` | Back Office | color | `#23303c` |
| `theme:backoffice:colors:bo_sidenav_text_color` | Back Office | color | `#e4e4e4` |
| `theme:logos:logos:backoffice_logo_url` | Back Office | file | (empty) |
| `theme:merchant_portal:colors:spy_primary_color` | Merchant Portal | color | `#1ebea0` |
| `theme:logos:logos:merchant_portal_logo` | Merchant Portal | file | (empty) |

### Twig usage examples

Inject a theme color as a CSS custom property in a Back Office layout:

{% raw %}

```twig
&lt;style&gt;
    :root {
        --bo-main-color: {{ configurationValue(&apos;theme:backoffice:colors:bo_main_color&apos;, &apos;#1ebea0&apos;) | e(&apos;css&apos;) }};
    }
&lt;/style&gt;
```

{% endraw %}

Read multiple values at once:

{% raw %}

```twig
{% set themeValues = configurationValues([
    &apos;theme:backoffice:colors:bo_main_color&apos;,
    &apos;theme:logos:logos:backoffice_logo_url&apos;,
]) %}
```

{% endraw %}
</description>
            <pubDate>Tue, 07 Apr 2026 08:04:11 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/integrate-and-configure/integrate-basic-shop-theme.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/integrate-and-configure/integrate-basic-shop-theme.html</guid>
            
            
        </item>
        
        <item>
            <title>Configuration Management feature</title>
            <description>&lt;h2 id=&quot;what-it-does&quot;&gt;What It Does&lt;/h2&gt;
&lt;p&gt;Provides a centralized, schema-driven system for managing application settings across scopes (for example global, store, custom-scope). Settings are declared in YAML files, managed via the Back Office UI, to be consumed in different layers (Zed, Yves, Glue) through module Config classes.&lt;/p&gt;
&lt;h2 id=&quot;quick-start&quot;&gt;Quick Start&lt;/h2&gt;
&lt;h3 id=&quot;declare-settings-in-a-yaml-schema&quot;&gt;1. Declare settings in a YAML schema&lt;/h3&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# /data/configuration/my-module.configuration.yml&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;features&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;my_module&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;My Module&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;tabs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;general&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;General&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;groups&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;display&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Display Settings&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;scopes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;global&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;items_per_page&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Items Per Page&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;integer&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;default_value&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;24&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;scopes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;global&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;storefront&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;constraints&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;required&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Items per page is required&lt;/span&gt;
                  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;min&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Must be at least &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;sync-schemas&quot;&gt;2. Sync schemas&lt;/h3&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker/sdk cli console configuration:sync
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;consume-in-your-module-config&quot;&gt;3. Consume in your module Config&lt;/h3&gt;
&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Spryker\Yves\MyModule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Spryker\Yves\Kernel\AbstractBundleConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyModuleConfig&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AbstractBundleConfig&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DEFAULT_ITEMS_PER_PAGE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CONFIGURATION_KEY_MY_MODULE_GENERAL_DISPLAY_ITEMS_PER_PAGE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;my_module:general:display:items_per_page&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getItemsPerPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getModuleConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;CONFIGURATION_KEY_MY_MODULE_GENERAL_DISPLAY_ITEMS_PER_PAGE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DEFAULT_ITEMS_PER_PAGE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;getModuleConfig()&lt;/code&gt; method is available in Zed, Yves, Glue layers &lt;code&gt;AbstractBundleConfig&lt;/code&gt; and is the preferred way to read configuration values.&lt;/p&gt;
&lt;h2 id=&quot;reading-configuration-values&quot;&gt;Reading Configuration Values&lt;/h2&gt;
&lt;h3 id=&quot;the-codegetmoduleconfigcode-method&quot;&gt;The &lt;code&gt;getModuleConfig()&lt;/code&gt; Method&lt;/h3&gt;
&lt;p&gt;Every &lt;code&gt;AbstractBundleConfig&lt;/code&gt; in Zed, Yves, and Glue provides:&lt;/p&gt;
&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getModuleConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;mixed&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$default&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$configurationScopes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;mixed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$key&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Compound setting key: &lt;code&gt;feature:tab:group:setting&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$default&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;mixed&lt;/td&gt;
&lt;td&gt;Fallback when value is not found or Configuration module is not installed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$configurationScopes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ConfigurationScopeTransfer[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Optional scope context transfers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Layer behavior:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Yves / Glue&lt;/strong&gt;: Reads from key-value storage via &lt;code&gt;ConfigurationClient&lt;/code&gt; (fast, cached)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zed&lt;/strong&gt;: Reads from database via &lt;code&gt;ConfigurationFacade&lt;/code&gt; (supports secrets, full scope resolution)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Backward Compatible:&lt;/strong&gt; If the Configuration module is not installed, &lt;code&gt;getModuleConfig()&lt;/code&gt; silently returns &lt;code&gt;$default&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;real-world-examples&quot;&gt;Real-World Examples&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;AvailabilityWidget (Yves)&lt;/strong&gt; – boolean setting with constant fallback:&lt;/p&gt;
&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AvailabilityWidgetConfig&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AbstractBundleConfig&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;STOCK_DISPLAY_ENABLED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;STOCK_DISPLAY_MODE_INDICATOR_AND_QUANTITY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;indicator_and_quantity&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CONFIGURATION_KEY_CATALOG_INVENTORY_STOCK_OPTIONS_DISPLAY_STOCK_AVAILABILITY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;catalog:inventory:stock_options:display_stock_availability&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CONFIGURATION_KEY_CATALOG_INVENTORY_STOCK_OPTIONS_STOCK_INFO_OPTIONS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;catalog:inventory:stock_options:stock_info_options&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isStockDisplayEnabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getModuleConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;CONFIGURATION_KEY_CATALOG_INVENTORY_STOCK_OPTIONS_DISPLAY_STOCK_AVAILABILITY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;STOCK_DISPLAY_ENABLED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getStockDisplayMode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getModuleConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;CONFIGURATION_KEY_CATALOG_INVENTORY_STOCK_OPTIONS_STOCK_INFO_OPTIONS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;STOCK_DISPLAY_MODE_INDICATOR_AND_QUANTITY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;BuyBox (Yves)&lt;/strong&gt; – string setting with enum fallback:&lt;/p&gt;
&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BuyBoxConfig&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AbstractBundleConfig&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SORT_BY_PRICE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;price&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CONFIGURATION_KEY_MARKETPLACE_PDP_BUY_BOX_OFFER_SORT_RULE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;marketplace:pdp:buy_box:offer_sort_rule&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getSortingStrategy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getModuleConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;CONFIGURATION_KEY_MARKETPLACE_PDP_BUY_BOX_OFFER_SORT_RULE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SORT_BY_PRICE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;scope-specific-reads&quot;&gt;Scope-Specific Reads&lt;/h3&gt;
&lt;p&gt;Pass &lt;code&gt;ConfigurationScopeTransfer&lt;/code&gt; objects as the third argument when you need a scope-specific value:&lt;/p&gt;
&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Generated\Shared\Transfer\ConfigurationScopeTransfer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getItemsPerPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$storeName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CONFIGURATION_KEY_MY_MODULE_GENERAL_DISPLAY_ITEMS_PER_PAGE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;my_module:general:display:items_per_page&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getModuleConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;CONFIGURATION_KEY_MY_MODULE_GENERAL_DISPLAY_ITEMS_PER_PAGE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DEFAULT_ITEMS_PER_PAGE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ConfigurationScopeTransfer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;store&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$storeName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;integration-checklist&quot;&gt;Integration Checklist&lt;/h3&gt;
&lt;p&gt;When integrating Configuration into an existing module:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Identify hardcoded values or constants that should be configurable&lt;/li&gt;
&lt;li&gt;Declare them in a YAML schema in &lt;code&gt;data/configuration/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Replace hardcoded access in the module’s Config class with &lt;code&gt;getModuleConfig()&lt;/code&gt; calls&lt;/li&gt;
&lt;li&gt;Keep the original constant as &lt;code&gt;$default&lt;/code&gt; for backward compatibility&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;configuration:sync&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Values are now manageable via the Back Office Configuration Management page&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;yaml-schema-declaration-reference&quot;&gt;YAML Schema Declaration Reference&lt;/h2&gt;
&lt;h3 id=&quot;schema-validation&quot;&gt;Schema Validation&lt;/h3&gt;
&lt;p&gt;YAML schema files support IDE autocompletion via JSON Schema. Add this header to your file:&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# yaml-language-server: $schema=../../vendor/spryker/configuration/resources/configuration/configuration-schema-v1.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The schema file is located at &lt;code&gt;vendor/spryker/configuration/resources/configuration/configuration-schema-v1.json&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;hierarchy&quot;&gt;Hierarchy&lt;/h3&gt;
&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;features[]
  tabs[]
    groups[]
      settings[]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Each setting gets a compound key: &lt;code&gt;{featureKey}:{tabKey}:{groupKey}:{settingKey}&lt;/code&gt; used for persistence and lookups.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;feature-level&quot;&gt;Feature Level&lt;/h3&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;features&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;system&lt;/span&gt;                          &lt;span class=&quot;c1&quot;&gt;# Required. Unique feature identifier.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;System Configuration&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;# Required. Display name in backoffice.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Core system settings&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Optional. Feature description.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;order&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;                             &lt;span class=&quot;c1&quot;&gt;# Optional. Sort order (lower = first).&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;# Optional. Default: true.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;tabs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;                          &lt;span class=&quot;c1&quot;&gt;# Required. At least one tab.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Constraints&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;key&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;&lt;code&gt;^[a-z][a-z0-9_]*$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unique identifier. Part of compound setting key.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;1-255 chars&lt;/td&gt;
&lt;td&gt;Display name in backoffice sidebar.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;max 1000 chars&lt;/td&gt;
&lt;td&gt;Feature description text.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;order&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;Sort order for rendering. Lower values first.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enabled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;When &lt;code&gt;false&lt;/code&gt;, feature and all children are hidden.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tabs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;array&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;min 1 item&lt;/td&gt;
&lt;td&gt;List of tab objects.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;tab-level&quot;&gt;Tab Level&lt;/h3&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;tabs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;general&lt;/span&gt;                         &lt;span class=&quot;c1&quot;&gt;# Required. Unique within feature.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;General&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;# Required. Tab display name.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;settings&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;# Optional. Icon class for backoffice tab.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;General system settings&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Optional. Tab description.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;order&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;                             &lt;span class=&quot;c1&quot;&gt;# Optional. Sort order (lower = first).&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;# Optional. Default: true.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;groups&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;# Required. At least one group.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Constraints&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;key&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;&lt;code&gt;^[a-z][a-z0-9_]*$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unique within feature. Part of compound setting key.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;1-255 chars&lt;/td&gt;
&lt;td&gt;Tab label in backoffice.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;icon&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;max 100 chars&lt;/td&gt;
&lt;td&gt;Icon class (for example &lt;code&gt;settings&lt;/code&gt;, &lt;code&gt;cable&lt;/code&gt;, &lt;code&gt;trending_up&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;max 1000 chars&lt;/td&gt;
&lt;td&gt;Tab description text.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;order&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;Sort order for rendering. Lower values first.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enabled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;When &lt;code&gt;false&lt;/code&gt;, tab and all children are hidden.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;groups&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;array&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;min 1 item&lt;/td&gt;
&lt;td&gt;List of group objects.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;group-level&quot;&gt;Group Level&lt;/h3&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;groups&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;basic&lt;/span&gt;                           &lt;span class=&quot;c1&quot;&gt;# Required. Unique within tab.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Basic Settings&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;# Required. Group display name.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Basic system config&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# Optional. Group description.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;scopes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;global&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;              &lt;span class=&quot;c1&quot;&gt;# Required. Scopes this group is visible for.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;order&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;                             &lt;span class=&quot;c1&quot;&gt;# Optional. Sort order (lower = first).&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;# Optional. Default: true.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;                      &lt;span class=&quot;c1&quot;&gt;# Required. At least one setting.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Constraints&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;key&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;&lt;code&gt;^[a-z][a-z0-9_]*$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unique within tab.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;1-255 chars&lt;/td&gt;
&lt;td&gt;Group heading in backoffice.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;max 1000 chars&lt;/td&gt;
&lt;td&gt;Group description text.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scopes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string[]&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[&apos;global&apos;]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;min 1 item&lt;/td&gt;
&lt;td&gt;Scopes where this group is displayed in backoffice.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;order&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;Sort order for rendering. Lower values first.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enabled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;When &lt;code&gt;false&lt;/code&gt;, group and all settings are hidden.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;settings&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;array&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;min 1 item&lt;/td&gt;
&lt;td&gt;List of setting objects.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;setting-level&quot;&gt;Setting Level&lt;/h3&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;site_name&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;# Required. Unique within group.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Site Name&lt;/span&gt;                      &lt;span class=&quot;c1&quot;&gt;# Required. Setting label.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;The name of the site&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Optional. Displayed below the input.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;note&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Changes require cache clear&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Optional. Additional note below description.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Enter your store name&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# Optional. Input placeholder text.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;help_text&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Appears in page titles&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Optional. Tooltip or help area text.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;@MyModule/Configuration/custom-input.twig&apos;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Optional. Custom Twig template.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;string&lt;/span&gt;                         &lt;span class=&quot;c1&quot;&gt;# Required. Data type.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;default_value&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;My Store&lt;/span&gt;              &lt;span class=&quot;c1&quot;&gt;# Optional. Fallback value.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;                             &lt;span class=&quot;c1&quot;&gt;# Optional. For select/multiselect/radio types.&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;option_a&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Option A&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;scopes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;global&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;              &lt;span class=&quot;c1&quot;&gt;# Optional. Default: [&apos;global&apos;].&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;order&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;                             &lt;span class=&quot;c1&quot;&gt;# Optional. Sort order (lower = first).&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;# Optional. Default: true.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;# Optional. Default: false.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;storefront&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;                     &lt;span class=&quot;c1&quot;&gt;# Optional. Default: false.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;constraints&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;# Optional. Validation constraints.&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;dependencies&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;# Optional. Conditional visibility rules.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Constraints&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;key&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;&lt;code&gt;^[a-z][a-z0-9_]*$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unique within group. Part of compound key.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;1-255 chars&lt;/td&gt;
&lt;td&gt;Input label in backoffice.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;max 1000 chars&lt;/td&gt;
&lt;td&gt;Help text displayed below the input field.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;note&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;max 1000 chars&lt;/td&gt;
&lt;td&gt;Additional note displayed below the description in italic.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;placeholder&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;max 255 chars&lt;/td&gt;
&lt;td&gt;Placeholder text inside the input field.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;help_text&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;max 500 chars&lt;/td&gt;
&lt;td&gt;Extended help in tooltip or expandable area.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;template&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;max 255 chars&lt;/td&gt;
&lt;td&gt;Custom Twig template. Overrides type-based widget.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;type&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;See types table&lt;/td&gt;
&lt;td&gt;Value data type. Determines backoffice input widget.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;default_value&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;mixed&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Must match &lt;code&gt;type&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fallback when no value is saved at any scope.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;options&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;option[]&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;For select/multi/radio&lt;/td&gt;
&lt;td&gt;Available choices. See &lt;a href=&quot;#options&quot;&gt;Options&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scopes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string[]&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[&apos;global&apos;]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;min 1 item&lt;/td&gt;
&lt;td&gt;Scopes where this setting can be configured.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;order&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;Sort order for rendering. Lower values first.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enabled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;When &lt;code&gt;false&lt;/code&gt;, setting is excluded from schema.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;secret&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;When &lt;code&gt;true&lt;/code&gt;, value is encrypted in database. Never published to storage.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;storefront&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;When &lt;code&gt;true&lt;/code&gt;, value is published to key-value storage for Yves/Glue.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;constraints&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;array&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;Validation rules. See &lt;a href=&quot;#constraints&quot;&gt;Constraints&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dependencies&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;array&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;Conditional rules. See &lt;a href=&quot;#dependencies&quot;&gt;Dependencies&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;file_upload&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;object&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Required when &lt;code&gt;type: file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;File upload configuration. See &lt;a href=&quot;#file-upload-fields&quot;&gt;File upload fields&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;setting-types&quot;&gt;Setting Types&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Backoffice Input&lt;/th&gt;
&lt;th&gt;Requires &lt;code&gt;options&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Single-line text&lt;/td&gt;
&lt;td&gt;Text input&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;integer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Whole number&lt;/td&gt;
&lt;td&gt;Number input&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;float&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Decimal number&lt;/td&gt;
&lt;td&gt;Number input&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;True/false toggle&lt;/td&gt;
&lt;td&gt;Checkbox/switch&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;text&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Multi-line text or structured data&lt;/td&gt;
&lt;td&gt;Textarea&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;color&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Color hex value&lt;/td&gt;
&lt;td&gt;Color picker&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JSON structure&lt;/td&gt;
&lt;td&gt;Code editor&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;select&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Single choice from list&lt;/td&gt;
&lt;td&gt;Dropdown&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;multiselect&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Multiple choices from list&lt;/td&gt;
&lt;td&gt;Multi-select&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;radio&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Single choice from list&lt;/td&gt;
&lt;td&gt;Radio buttons&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;File upload (stored as public URL)&lt;/td&gt;
&lt;td&gt;File upload widget&lt;/td&gt;
&lt;td&gt;No, but requires &lt;code&gt;file_upload&lt;/code&gt; block&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;file-upload-fields&quot;&gt;File upload fields&lt;/h4&gt;
&lt;p&gt;Use &lt;code&gt;type: file&lt;/code&gt; for settings that accept a file upload (for example, logo images). The Back Office renders a file upload widget. After a successful upload, the public URL of the uploaded file is stored as the setting value. All file validation and storage are handled server-side using a configured Flysystem filesystem service.&lt;/p&gt;
&lt;p&gt;When &lt;code&gt;type: file&lt;/code&gt; is used, a &lt;code&gt;file_upload&lt;/code&gt; block must be present on the setting. It configures the Flysystem service, allowed file types, size limit, and recommended display dimensions.&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bo_logo_url&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Back Office Logo&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;file&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;file_upload&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;storage_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;backoffice-media&apos;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;allowed_mime_types&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;image/png&apos;&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;image/jpeg&apos;&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;image/gif&apos;&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;image/webp&apos;&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;image/svg+xml&apos;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;allowed_extensions&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.png&apos;&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.jpg&apos;&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.jpeg&apos;&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.gif&apos;&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.webp&apos;&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.svg&apos;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;max_file_size&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;10M&apos;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;recommended_width_px&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;290&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;recommended_height_px&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;77&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;default_value&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;scopes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;global&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;storefront&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h5 id=&quot;codefileuploadcode-properties&quot;&gt;&lt;code&gt;file_upload&lt;/code&gt; properties&lt;/h5&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;storage_name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Flysystem filesystem service name. Must be configured in &lt;code&gt;FileSystemConstants::FILESYSTEM_SERVICE&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;allowed_mime_types&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string[]&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;List of permitted MIME types. Upload is rejected if the file MIME type is not in the list.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;allowed_extensions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string[]&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;List of permitted file extensions including the leading dot (for example &lt;code&gt;.png&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max_file_size&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Maximum allowed file size (for example &lt;code&gt;10M&lt;/code&gt;, &lt;code&gt;2048K&lt;/code&gt;). Rejected if exceeded.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;recommended_width_px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Recommended display width in pixels. Shown as a hint in the Back Office UI.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;recommended_height_px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Recommended display height in pixels. Shown as a hint in the Back Office UI.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The stored value is always a public URL returned by the Flysystem service after upload. To render the image in a Twig template, read it with &lt;code&gt;configurationValue()&lt;/code&gt; and use it as an &lt;code&gt;src&lt;/code&gt; attribute:&lt;/p&gt;
&lt;div class=&quot;language-twig highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;logoUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;configurationValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;theme:logos:logos:yves_logo_url&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;logoUrl&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;logoUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;| &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;html_attr&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;alt=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Logo&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;For Flysystem service setup (S3 in production, local fallback in development and CI), see &lt;a href=&quot;/docs/dg/dev/integrate-and-configure/integrate-basic-shop-theme.html&quot;&gt;Install the Basic Shop Theme feature&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;options&quot;&gt;Options&lt;/h4&gt;
&lt;p&gt;Required for &lt;code&gt;select&lt;/code&gt;, &lt;code&gt;multiselect&lt;/code&gt;, and &lt;code&gt;radio&lt;/code&gt; types. Defines available choices.&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;indicator_only&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Indicator Only&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Show only in-stock/out-of-stock indicator&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;indicator_and_quantity&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Indicator and Quantity&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Show indicator and exact stock count&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Constraints&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;value&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;min 1 char&lt;/td&gt;
&lt;td&gt;Internal value stored when selected.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;label&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;1-255 chars&lt;/td&gt;
&lt;td&gt;Display label shown in backoffice.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;max 500 chars&lt;/td&gt;
&lt;td&gt;Additional explanation (for radio buttons).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;secret-vs-storefront-behavior&quot;&gt;Secret vs Storefront Behavior&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;secret&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;storefront&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Plain text in database. Accessible only via Zed (&lt;code&gt;getModuleConfig()&lt;/code&gt; in Zed Config).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Plain text. Published to key-value storage. Accessible in all layers via &lt;code&gt;getModuleConfig()&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Encrypted in database. Decrypted on read in Zed only. Never published to storage.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Invalid combination. Secrets are always excluded from storage.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;available-scopes&quot;&gt;Available Scopes&lt;/h4&gt;
&lt;p&gt;Built-in scopes (enabled out of the box):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Requires Identifier&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;global&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Application-wide default&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;store&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Store-specific override (for example DE, AT)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Default hierarchy: &lt;code&gt;store -&amp;gt; global -&amp;gt; default_value&lt;/code&gt;. Values resolve from most specific to least specific.&lt;/p&gt;
&lt;p&gt;For adding custom scopes, see &lt;a href=&quot;/docs/dg/dev/backend-development/configuration-management/custom-scopes.html&quot;&gt;Adding Custom Scopes&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;constraints&quot;&gt;Constraints&lt;/h3&gt;
&lt;p&gt;Validated server-side when saving values through the Back Office.&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;constraints&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;required&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Site name is required&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;min&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Must be at least &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;max&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Cannot exceed &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;100&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Constraints&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;type&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;See table&lt;/td&gt;
&lt;td&gt;Constraint type identifier.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;message&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;1-500 chars&lt;/td&gt;
&lt;td&gt;Error message shown when validation fails.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;options&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;object&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Depends on type&lt;/td&gt;
&lt;td&gt;Constraint-specific parameters.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;built-in-constraint-types&quot;&gt;Built-in Constraint Types&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Required Options&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;required&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Value must not be blank&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;Mandatory fields&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;min&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Minimum numeric value&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min&lt;/code&gt; (number)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;options: { min: 1 }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Maximum numeric value&lt;/td&gt;
&lt;td&gt;&lt;code&gt;max&lt;/code&gt; (number)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;options: { max: 100 }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;range&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Value within numeric range&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt; (number)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;options: { min: 0, max: 100 }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;length&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;String length limits&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min&lt;/code&gt; and/or &lt;code&gt;max&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;options: { min: 6, max: 128 }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;email&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Email format validation&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;Email input fields&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;url&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;URL format validation&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;URL input fields&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;regex&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pattern matching&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pattern&lt;/code&gt; (string)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;options: { pattern: &apos;^G-[A-Z0-9]{10}$&apos; }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;choice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Value from allowed list&lt;/td&gt;
&lt;td&gt;&lt;code&gt;choices&lt;/code&gt; (string[])&lt;/td&gt;
&lt;td&gt;&lt;code&gt;options: { choices: [&apos;a&apos;, &apos;b&apos;] }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;dependencies&quot;&gt;Dependencies&lt;/h3&gt;
&lt;p&gt;Control conditional visibility of settings in the Back Office UI. A setting with dependencies is only shown when at least one dependency rule matches (OR logic between rules). Each rule uses a &lt;code&gt;when&lt;/code&gt; clause with &lt;code&gt;any&lt;/code&gt; (OR) or &lt;code&gt;all&lt;/code&gt; (AND) condition grouping.&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;stock_info_options&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Stock Info Options&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;radio&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;dependencies&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;setting&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;catalog:inventory:stock_options:display_stock_availability&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;operator&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;equals&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;true&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Multiple conditions with &lt;code&gt;all&lt;/code&gt; (AND logic):&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;na&quot;&gt;dependencies&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;setting&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;system:general:basic:feature_enabled&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;operator&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;equals&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;true&quot;&lt;/span&gt;
            &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;setting&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;system:general:basic:mode&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;operator&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;not_equals&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;maintenance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;dependency-rule&quot;&gt;Dependency Rule&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;when&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;object&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Contains &lt;code&gt;any&lt;/code&gt; or &lt;code&gt;all&lt;/code&gt; array of conditions.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;when-clause&quot;&gt;When Clause&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;any&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;condition[]&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Setting is shown if &lt;strong&gt;any&lt;/strong&gt; condition matches (OR).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;all&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;condition[]&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Setting is shown if &lt;strong&gt;all&lt;/strong&gt; conditions match (AND).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;One of &lt;code&gt;any&lt;/code&gt; or &lt;code&gt;all&lt;/code&gt; must be provided.&lt;/p&gt;
&lt;h4 id=&quot;condition&quot;&gt;Condition&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;setting&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Compound key of the setting this depends on.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;operator&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Comparison operator.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;value&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Value to compare against.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;dependency-operators&quot;&gt;Dependency Operators&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operator&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;equals&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Setting value must equal the given value.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;not_equals&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Setting value must not equal the given value.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;greater_than&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Numeric: value must be greater than expected.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;less_than&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Numeric: value must be less than expected.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;contains&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;String: value must contain the expected text.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;in&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Value must be in the given list.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;schema-file-locations&quot;&gt;Schema File Locations&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Location&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Loaded By&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;{Module Folder}/resources/configuration/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Core module schemas&lt;/td&gt;
&lt;td&gt;&lt;code&gt;configuration:sync&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;data/configuration/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Project-level schema overrides&lt;/td&gt;
&lt;td&gt;&lt;code&gt;configuration:sync&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Project schemas override core schemas at the setting level. Settings with the same compound key are completely replaced.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Merged output:&lt;/strong&gt; &lt;code&gt;data/configuration/merged-schema.php&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;backoffice-management&quot;&gt;Backoffice Management&lt;/h2&gt;
&lt;p&gt;Settings are managed at &lt;strong&gt;The Back office &amp;gt; Configuration&lt;/strong&gt;. The page provides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Feature sidebar navigation&lt;/li&gt;
&lt;li&gt;Tabbed layout per feature&lt;/li&gt;
&lt;li&gt;Scope switcher (global, store with identifier)&lt;/li&gt;
&lt;li&gt;Input widgets matching setting types&lt;/li&gt;
&lt;li&gt;Inline validation with constraint error messages&lt;/li&gt;
&lt;li&gt;“Revert to default” to delete scope-specific overrides&lt;/li&gt;
&lt;li&gt;Batch save with per-field error reporting&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;twig-integration&quot;&gt;Twig Integration&lt;/h2&gt;
&lt;p&gt;The Configuration module exposes three Twig functions that let templates read configuration values directly without going through a PHP Config class. They are available through the following existing plugins — no additional registration is required:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;th&gt;Plugin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Storefront (Yves)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ShopUiTwigExtension&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Back Office and Merchant Portal (Zed)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;\Spryker\Zed\Twig\Communication\Plugin\Application\TwigApplicationPlugin&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;configurationValue(key, default)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Returns a single configuration value by compound key.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;configurationValues(keys)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Returns an associative array of values for a list of compound keys.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;codeconfigurationvaluecode&quot;&gt;&lt;code&gt;configurationValue&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Returns a single value for the given compound key. Falls back to &lt;code&gt;default&lt;/code&gt; if the key has no saved value.&lt;/p&gt;
&lt;div class=&quot;language-twig highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;configurationValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;theme:backoffice:colors:bo_main_color&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;#1ebea0&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-twig highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;py&quot;&gt;--bo-main-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;configurationValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;theme:backoffice:colors:bo_main_color&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;#1ebea0&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;| &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;css&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;codeconfigurationvaluescode&quot;&gt;&lt;code&gt;configurationValues&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Returns an associative array keyed by compound key. Useful when a template needs several values at once.&lt;/p&gt;
&lt;div class=&quot;language-twig highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;colors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;configurationValues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;theme:backoffice:colors:bo_main_color&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;theme:logos:logos:backoffice_logo_url&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;style&amp;gt;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;--bo-main-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;colors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;theme:backoffice:colors:bo_main_color&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;| &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;css&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;section class=&apos;info-block &apos;&gt;&lt;i class=&apos;info-block__icon icon-info&apos;&gt;&lt;/i&gt;&lt;div class=&apos;info-block__content&apos;&gt;&lt;div class=&quot;info-block__title&quot;&gt;Scope context&lt;/div&gt;
&lt;p&gt;Twig functions read values in the current request’s scope context. Store-specific values are resolved automatically when a store scope is active.&lt;/p&gt;
&lt;/div&gt;&lt;/section&gt;
&lt;h2 id=&quot;common-issues&quot;&gt;Common Issues&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;getModuleConfig()&lt;/code&gt; always returns default&lt;/td&gt;
&lt;td&gt;Setting &lt;code&gt;storefront: false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Yves/Glue can only read storefront-enabled settings. Set &lt;code&gt;storefront: true&lt;/code&gt; or use Zed Config.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;getModuleConfig()&lt;/code&gt; always returns default&lt;/td&gt;
&lt;td&gt;Configuration module not installed&lt;/td&gt;
&lt;td&gt;Expected behavior. Method gracefully falls back to &lt;code&gt;$default&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Value returns &lt;code&gt;null&lt;/code&gt; despite being saved&lt;/td&gt;
&lt;td&gt;Key mismatch&lt;/td&gt;
&lt;td&gt;Compound key format is &lt;code&gt;feature:tab:group:setting&lt;/code&gt;. Verify all four segments match the YAML schema.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secret value empty in Yves&lt;/td&gt;
&lt;td&gt;Expected behavior&lt;/td&gt;
&lt;td&gt;Secrets are never published to storage. Access only via Zed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Changes not visible after YAML edit&lt;/td&gt;
&lt;td&gt;Schema not synced&lt;/td&gt;
&lt;td&gt;Run &lt;code&gt;configuration:sync&lt;/code&gt; after YAML changes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Store-specific value not applied&lt;/td&gt;
&lt;td&gt;Missing scope context&lt;/td&gt;
&lt;td&gt;Pass &lt;code&gt;ConfigurationScopeTransfer&lt;/code&gt; in third argument or register request expander plugins. See &lt;a href=&quot;/docs/dg/dev/backend-development/configuration-management/custom-scopes.html&quot;&gt;Adding Custom Scopes&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</description>
            <pubDate>Tue, 07 Apr 2026 08:04:11 +0000</pubDate>
            <link>https://docs.spryker.com/docs/dg/dev/backend-development/configuration-management.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/dg/dev/backend-development/configuration-management.html</guid>
            
            
        </item>
        
        <item>
            <title>Basic Shop Theme feature overview</title>
            <description>&lt;p&gt;The Basic Shop Theme feature lets Business Admins configure the visual branding of a Spryker shop directly from the Back Office. Logos, theme colors, and custom CSS for the Storefront, Back Office, and Merchant Portal can all be set without code changes or redeployment.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;business-problems-it-solves&quot;&gt;Business problems it solves&lt;/h2&gt;
&lt;p&gt;Basic visual customization of a Spryker shop — such as applying a company logo or brand color — traditionally requires developer involvement, project-specific work, or code changes. This creates friction in critical moments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Demo preparation&lt;/strong&gt; by Solution Engineers — demos feel less customer-ready without brand-specific visuals.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Early project phases and proofs of concept&lt;/strong&gt; — customers cannot easily apply their own branding.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;First weeks after go-live&lt;/strong&gt; — unnecessary delivery work delays Time-to-First-Transaction.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Basic Shop Theme feature removes this dependency by providing a self-service branding interface in the Back Office.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;what-you-can-configure&quot;&gt;What you can configure&lt;/h2&gt;
&lt;p&gt;All theme settings are managed under &lt;strong&gt;Back Office &amp;gt; Configuration &amp;gt; Theme&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;storefront&quot;&gt;Storefront&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Theme Main Color&lt;/td&gt;
&lt;td&gt;Color picker&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#00bebe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Primary brand color applied across the storefront. Exposed as the &lt;code&gt;--theme-main-color&lt;/code&gt; CSS custom property.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Theme Alternative Color&lt;/td&gt;
&lt;td&gt;Color picker&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#eb553c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Secondary brand color for accents and highlights. Exposed as &lt;code&gt;--theme-alt-color&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storefront Logo&lt;/td&gt;
&lt;td&gt;File upload&lt;/td&gt;
&lt;td&gt;(empty)&lt;/td&gt;
&lt;td&gt;Logo displayed in the storefront header. Recommended size: 186×50 px. Supported formats: GIF, PNG, JPEG, BMP, WebP, SVG.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storefront Custom CSS&lt;/td&gt;
&lt;td&gt;Text area&lt;/td&gt;
&lt;td&gt;(empty)&lt;/td&gt;
&lt;td&gt;Custom CSS injected into storefront pages. Use with caution — invalid CSS may break page layout.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;back-office&quot;&gt;Back Office&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Backoffice Theme Color&lt;/td&gt;
&lt;td&gt;Color picker&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#1ebea0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Primary theme color for the Back Office interface. Exposed as the &lt;code&gt;--bo-main-color&lt;/code&gt; CSS custom property.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backoffice Side Navigation Background&lt;/td&gt;
&lt;td&gt;Color picker&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#23303c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Side navigation and login background. Exposed as the &lt;code&gt;--bo-sidenav-color&lt;/code&gt; CSS custom property.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backoffice Side Navigation Text Color&lt;/td&gt;
&lt;td&gt;Color picker&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#e4e4e4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Side navigation text color. Exposed as the &lt;code&gt;--bo-sidenav-text-color&lt;/code&gt; CSS custom property.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Back Office Logo&lt;/td&gt;
&lt;td&gt;File upload&lt;/td&gt;
&lt;td&gt;(empty)&lt;/td&gt;
&lt;td&gt;Logo displayed in the Back Office sidebar. Recommended size: 186×50 px. Supported formats: GIF, PNG, JPEG, BMP, WebP, SVG.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;merchant-portal&quot;&gt;Merchant Portal&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Merchant Portal Theme Color&lt;/td&gt;
&lt;td&gt;Color picker&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#1ebea0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Primary theme color for the Merchant Portal interface. Exposed as the &lt;code&gt;--mp-theme-color&lt;/code&gt; CSS custom property.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Merchant Portal Logo&lt;/td&gt;
&lt;td&gt;File upload&lt;/td&gt;
&lt;td&gt;(empty)&lt;/td&gt;
&lt;td&gt;Logo displayed in the Merchant Portal header. Recommended size: 186×50 px. Supported formats: GIF, PNG, JPEG, BMP, WebP, SVG.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The Basic Shop Theme feature is built on top of the &lt;a href=&quot;/docs/pbc/all/back-office/latest/base-shop/backoffice-configuration-framework.html&quot;&gt;Back Office Configuration Framework&lt;/a&gt;. All settings are declared in a YAML schema file bundled with the Spryker core modules. The Configuration module reads this file and renders the corresponding UI in the Back Office.&lt;/p&gt;
&lt;h3 id=&quot;storefront-theming-flow&quot;&gt;Storefront theming flow&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;A Business Admin sets a theme color or logo in the Back Office.&lt;/li&gt;
&lt;li&gt;The value is saved and published to key-value storage (Redis) via the Publish &amp;amp; Synchronize mechanism.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;configurationValue()&lt;/code&gt; Twig function reads the value from storage and injects it into the &lt;code&gt;page-blank&lt;/code&gt; layout as a CSS custom property or logo image tag.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;back-office-and-merchant-portal-theming-flow&quot;&gt;Back Office and Merchant Portal theming flow&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;A Business Admin sets a theme color or logo in the Back Office.&lt;/li&gt;
&lt;li&gt;The value is saved in the database.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;configurationValue()&lt;/code&gt; Twig function reads the value from the database and injects it into the respective layout template as a CSS custom property or logo image tag.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;css-custom-properties&quot;&gt;CSS custom properties&lt;/h3&gt;
&lt;p&gt;Theme colors are injected as CSS custom properties so that the design system can use them throughout component styles:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Custom Property&lt;/th&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--background-brand-primary&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Storefront&lt;/td&gt;
&lt;td&gt;Storefront primary brand color&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--background-brand-subtle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Storefront&lt;/td&gt;
&lt;td&gt;Storefront secondary accent color&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--bo-main-color&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Back Office&lt;/td&gt;
&lt;td&gt;Back Office primary theme color&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--bo-sidenav-color&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Back Office&lt;/td&gt;
&lt;td&gt;Back Office side navigation and login background&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--bo-sidenav-text-color&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Back Office&lt;/td&gt;
&lt;td&gt;Back Office side navigation text color&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--spy-primary-color&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Merchant Portal&lt;/td&gt;
&lt;td&gt;Merchant Portal primary theme color&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;logo-upload-fields&quot;&gt;Logo upload fields&lt;/h3&gt;
&lt;p&gt;Logo settings use a file upload widget in the Back Office. Uploaded files are stored via a configured Flysystem media filesystem service and served from a public URL. Each application context uses its own filesystem service:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;th&gt;Filesystem service&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Storefront&lt;/td&gt;
&lt;td&gt;&lt;code&gt;storefront-media&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Back Office&lt;/td&gt;
&lt;td&gt;&lt;code&gt;backoffice-media&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Merchant Portal&lt;/td&gt;
&lt;td&gt;&lt;code&gt;merchant-portal-media&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In production, these services write to an S3 bucket (or compatible object storage). In development and CI environments, files are stored locally at &lt;code&gt;public/Yves/assets/static/images&lt;/code&gt; and served via the Yves assets path.&lt;/p&gt;
&lt;p&gt;If the field is left empty, the default logo is displayed.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;store-level-customization&quot;&gt;Store-level customization&lt;/h2&gt;
&lt;p&gt;All theme settings support both global and store scopes. You can apply the same branding across all stores (global scope) or override individual settings per store (store scope).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Store&lt;/th&gt;
&lt;th&gt;Theme Main Color&lt;/th&gt;
&lt;th&gt;Behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Global&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#00bebe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Applied to all stores by default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#ff0000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Overrides the global value for DE only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AT&lt;/td&gt;
&lt;td&gt;(not set)&lt;/td&gt;
&lt;td&gt;Inherits &lt;code&gt;#00bebe&lt;/code&gt; from global&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;To switch scope, use the scope selector at the top of the Configuration Management page.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;security&quot;&gt;Security&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Twig access&lt;/strong&gt; — the &lt;code&gt;configurationValue()&lt;/code&gt; and &lt;code&gt;configurationValues()&lt;/code&gt; Twig functions are available in templates, but theme layout templates only read the specific compound keys they are designed for.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Color injection&lt;/strong&gt; — color values are escaped with &lt;code&gt;| e(&apos;css&apos;)&lt;/code&gt; to prevent CSS injection.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom CSS sanitization&lt;/strong&gt; — custom CSS input is sanitized using &lt;code&gt;symfony/html-sanitizer&lt;/code&gt; before being saved, reducing the risk of injecting malicious markup. The rendered output still uses &lt;code&gt;| raw&lt;/code&gt; since CSS must be injected verbatim, so this setting should only be accessible to trusted administrators.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;File uploads&lt;/strong&gt; — uploaded logo files are stored in isolated filesystem services per context. File types are validated on upload.&lt;/li&gt;
&lt;li&gt;All theme settings are protected by Back Office authentication and ACL.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;related-features&quot;&gt;Related features&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Link&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Back Office Configuration Framework&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;/docs/pbc/all/back-office/latest/base-shop/backoffice-configuration-framework.html&quot;&gt;Overview&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configuration Management&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;/docs/dg/dev/backend-development/configuration-management.html&quot;&gt;Developer guide&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Install the Basic Shop Theme&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;/docs/dg/dev/integrate-and-configure/integrate-basic-shop-theme.html&quot;&gt;Integration guide&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</description>
            <pubDate>Tue, 07 Apr 2026 08:04:11 +0000</pubDate>
            <link>https://docs.spryker.com/docs/pbc/all/back-office/latest/base-shop/basic-shop-theme-feature-overview.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/pbc/all/back-office/latest/base-shop/basic-shop-theme-feature-overview.html</guid>
            
            
        </item>
        
        <item>
            <title>Back Office Configuration Framework</title>
            <description>&lt;p&gt;The Back Office Configuration Framework is a structured approach to exposing business-relevant configuration options directly in the Spryker Back Office. Instead of defining configuration in code or YAML files that require redeployment, businesses can manage defined behaviors through structured UI pages. Developers define configuration options once in YAML, and the framework automatically renders them as configurable Back Office interfaces.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;business-problems-it-solves&quot;&gt;Business problems it solves&lt;/h2&gt;
&lt;p&gt;Managing configuration in traditional commerce platforms creates friction between technical and business teams:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Configuration changes require developer involvement, code modifications, and a full deployment cycle.&lt;/li&gt;
&lt;li&gt;Business teams depend on IT to adjust behaviors that are fundamentally business decisions.&lt;/li&gt;
&lt;li&gt;YAML and code-level configuration is inaccessible to non-technical stakeholders and prone to error.&lt;/li&gt;
&lt;li&gt;Each configuration change introduces risk, slows down operations, and increases the total cost of change.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Back Office Configuration Framework addresses these challenges by creating a clear, controlled boundary between what developers define and what business users can adjust.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;key-value-for-your-business&quot;&gt;Key value for your business&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Faster time to change&lt;/strong&gt;
Business users adjust configured behaviors directly in the Back Office. No code change, no pull request, no deployment required.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reduced operational risk&lt;/strong&gt;
Configuration is exposed through structured, validated UI pages. Business users work within defined options rather than editing raw configuration files.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Developer efficiency&lt;/strong&gt;
Developers define configuration options once in YAML. The framework handles rendering, validation, and persistence automatically, eliminating repetitive UI work.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Consistent experience&lt;/strong&gt;
All configuration pages follow the same structure and interaction patterns, making it easier for business users to navigate and manage settings across features.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Extensibility by design&lt;/strong&gt;
The framework supports both out of the box Spryker features and project-specific customizations, so teams can introduce new configurable behaviors without building new infrastructure.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;who-benefits-and-how&quot;&gt;Who benefits and how&lt;/h2&gt;
&lt;h3 id=&quot;for-business-leaders&quot;&gt;For business leaders&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lower cost of change&lt;/strong&gt;
Adjusting business behaviors no longer requires a development sprint or deployment window. Teams can respond to market conditions and business needs faster.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reduced dependency on IT&lt;/strong&gt;
Business teams gain direct control over selected configuration options without needing to involve developers for every adjustment.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Stable, governed configurability&lt;/strong&gt;
The framework exposes only explicitly defined options. Business users operate within guardrails set by the development team, reducing the risk of misconfiguration.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;for-product-and-commerce-teams&quot;&gt;For product and commerce teams&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Self-service configuration&lt;/strong&gt;
Manage feature behavior directly from the Back Office, using familiar UI patterns. No need to understand YAML syntax or request a deployment.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Faster iteration&lt;/strong&gt;
Test different configurations, observe results, and adjust without waiting for a release cycle.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Visibility into configurable options&lt;/strong&gt;
All available configuration options are surfaced in one place, making it easy to understand what can be changed and what the current settings are.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;for-developers-and-architects&quot;&gt;For developers and architects&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Define once, render automatically&lt;/strong&gt;
Declare configuration options in YAML. The framework generates the corresponding Back Office UI, saving significant development and maintenance effort.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Separation of concerns&lt;/strong&gt;
Configuration definition stays with the developer; configuration management becomes a business user activity. This boundary is enforced by the framework.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Standardized patterns&lt;/strong&gt;
Avoid building custom configuration UIs for each feature. The framework provides consistent infrastructure that all teams benefit from.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;key-capabilities&quot;&gt;Key capabilities&lt;/h2&gt;
&lt;h3 id=&quot;support-for-out-of-the-box-and-custom-features&quot;&gt;Support for out of the box and custom features&lt;/h3&gt;
&lt;p&gt;The framework supports configuration for existing Spryker out of the box features as well as project-specific customizations. Teams can use it to expose configuration options for both standard platform capabilities and bespoke features built for a specific project.&lt;/p&gt;
&lt;h3 id=&quot;structured-and-controlled-business-configurability&quot;&gt;Structured and controlled business configurability&lt;/h3&gt;
&lt;p&gt;Selected business-relevant configuration moves from code level to UI level without exposing low-level technical complexity. The developer controls which options are available, what values are valid, and how they are presented. The business user controls what value is set, within those defined parameters.&lt;/p&gt;
&lt;h3 id=&quot;out-of-the-box-implementations&quot;&gt;Out of the box implementations&lt;/h3&gt;
&lt;p&gt;The Back Office Configuration Framework ships with the following out of the box implementations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;B2B Product Availability Display&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The initial release ships with a configuration UI for B2B Product Availability Display. This implementation demonstrates the framework in a real-world use case, allowing business users to configure how product availability information is presented to B2B buyers directly from the Back Office.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Basic Shop Theme&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The second out of the box implementation provides a configuration UI for shop branding. Business Admins can set theme colors, logo URLs, and custom CSS for the Storefront, Back Office, and Merchant Portal without code changes or redeployment. For details, see &lt;a href=&quot;/docs/pbc/all/back-office/latest/base-shop/basic-shop-theme-feature-overview.html&quot;&gt;Basic Shop Theme feature overview&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The Back Office Configuration Framework follows a developer-first definition approach with a business-user-facing runtime experience:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Developer defines configuration options in YAML&lt;/strong&gt;
The developer declares the available configuration options, their data types, validation rules, and default values in a structured YAML definition.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Framework generates the Back Office UI&lt;/strong&gt;
The framework reads the YAML definition and automatically renders the corresponding configuration page in the Back Office, including form fields, labels, and validation feedback.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Business user manages configuration&lt;/strong&gt;
A Back Office user with appropriate permissions accesses the configuration page, adjusts the available options, and saves changes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Changes take effect without redeployment&lt;/strong&gt;
Configuration updates are stored and applied at runtime. No code changes or deployments are required.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;comparison-to-traditional-configuration-approaches&quot;&gt;Comparison to traditional configuration approaches&lt;/h2&gt;
&lt;h3 id=&quot;code-level-configuration&quot;&gt;Code-level configuration&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Traditional approach:&lt;/strong&gt; Configuration values are hardcoded or set in PHP configuration files. Changing a value requires a code change, review, and deployment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Back Office Configuration Framework:&lt;/strong&gt; Configuration values are managed in the Back Office UI. Changes take effect immediately, within the boundaries defined by the developer.&lt;/p&gt;
&lt;h3 id=&quot;yaml-based-configuration&quot;&gt;YAML-based configuration&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Traditional approach:&lt;/strong&gt; Configuration is declared in YAML files that are part of the codebase. Changing a value requires editing a file, committing the change, and triggering a deployment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Back Office Configuration Framework:&lt;/strong&gt; YAML is still used, but only by developers to define what options are available. Business users interact with the resulting UI, not with YAML directly.&lt;/p&gt;
&lt;h3 id=&quot;custom-configuration-uis&quot;&gt;Custom configuration UIs&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Traditional approach:&lt;/strong&gt; Each feature that requires business-user configuration needs a custom-built UI, resulting in inconsistent experiences and duplicated development effort.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Back Office Configuration Framework:&lt;/strong&gt; All configurable features share the same framework-generated UI infrastructure, reducing development effort and ensuring a consistent experience.&lt;/p&gt;
</description>
            <pubDate>Tue, 07 Apr 2026 08:04:11 +0000</pubDate>
            <link>https://docs.spryker.com/docs/pbc/all/back-office/latest/base-shop/backoffice-configuration-framework.html</link>
            <guid isPermaLink="true">https://docs.spryker.com/docs/pbc/all/back-office/latest/base-shop/backoffice-configuration-framework.html</guid>
            
            
        </item>
        
    </channel>
</rss>
