Pimcore Studio Setup Guide: Backend & Infrastructure for Developers

Marta Marija Picić
Backend Developer

Pimcore Studio is the newest addition to the Pimcore platform, that replaces current ExtJS-based admin interface. It is built with React, and it provides a more modern and improved user experience.

In order to access Studio UI features, multiple services need to be installed and configured beforehand. This guide will walk you through the required installation steps and give you an overview of the required services.

Note: We used DDEV for the local setup. The starting point for this guide is an existing DDEV-based Pimcore/Symfony project, which already provides the base local services. From there, we add and configure the extra services required for Studio UI. If you are new to DDEV, see the official documentation.

Architecture Overview

Before jumping into the set-up process, we need to understand how Pimcore Studio fits into the overall system.

Pimcore Studio architecture diagram showing Studio UI, REST API, OpenSearch, Mercure, and Symfony Messenger services

At a high level, Pimcore Studio requires the following:

  • Studio UI - administration interface for Pimcore built in React.
  • Studio Backend - central hub for API endpoints (provides docs via swagger-ui).
  • Several supporting services:
    • OpenSearch - indexing and search
    • Symfony Messenger - background processing
    • Mercure - real-time updates

Local Setup (DDEV)

This section covers everything required to get Studio UI running locally using DDEV.

OpenSearch

Studio UI relies on indexed data. Without OpenSearch, object trees and search functionality won’t work. To set up OpenSearch using DDEV, do the following:

1 - Install addon

 
ddev get ddev/ddev-opensearch 
ddev restart 

2 - Environment configuration

.env.local
OPENSEARCH_HOST=opensearch 
OPENSEARCH_PORT=9200 

3 - Bundle configuration

config/config.yaml
pimcore_generic_data_index: 
  search_client: 
      hosts: 
          - '%env(OPENSEARCH_HOST)%:%env(OPENSEARCH_PORT)%' 

Symfony Messenger

Studio UI depends on data in OpenSearch. To avoid manually running the command for index generation after each change on Pimcore elements, you can do the following:

1 - Add to .ddev/config.pimcore.yaml

.ddev/config.pimcore.yaml
web_extra_daemons: 
- name: consumer 
  command: >- 
    while true; do 
      /var/www/html/bin/console messenger:consume 
        pimcore_core 
        pimcore_maintenance 
        pimcore_scheduled_tasks 
        pimcore_image_optimize 
        pimcore_asset_update 
        pimcore_generic_data_index_queue 
        pimcore_generic_execution_engine 
        --memory-limit=250M 
        --time-limit=3600; 
    done 
  directory: /var/www/html 

2 - Restart DDEV

 
ddev restart 

Mercure

Mercure enables real-time updates like job progress and notifications. To set up Mercure using DDEV, do the following:

1 - Install addon

 
ddev get Rindula/ddev-mercure
ddev restart

2 - Environment configuration

.env.local
MERCURE_URL=https://<your-project>.ddev.site/hub
MERCURE_INTERNAL_URL=http://mercure:3000/.well-known/mercure
MERCURE_PUBLISHER_JWT_KEY=!ChangeThisMercureHubJWTSecretKey!

3 - Bundle configuration

 
pimcore_studio_backend:
    mercure_settings:
        jwt_key: "%env(MERCURE_PUBLISHER_JWT_KEY)%"
        hub_url_client: '%env(MERCURE_URL)%'
        hub_url_server: '%env(MERCURE_INTERNAL_URL)%'

Cross-origin issues with Mercure

By default, DDEV exposes Mercure on its own subdomain, such as mercure.your-project.ddev.site. If the Studio UI connects to that URL directly from your-project.ddev.site, the browser treats it as a different origin. In local setups, that leads to CORS-related issues.

The solution is to proxy the Mercure hub through the main site's nginx, so the browser only communicates with the same origin as the Pimcore application. Add the following location block inside the server block in .ddev/nginx_full/nginx-site.conf. If that file still contains the #ddev-generated marker at the top, remove it first so DDEV does not overwrite your changes:

.ddev/nginx_full/nginx-site.conf
location /hub {
    proxy_pass http://mercure:3000/.well-known/mercure;
    proxy_read_timeout 24h;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_buffering off;
    proxy_cache off;
}

With this in place, requests to https://your-project.ddev.site/hub are proxied internally to the Mercure container. MERCURE_INTERNAL_URL should still point directly to the Mercure container, for example http://mercure:3000/.well-known/mercure, because Pimcore publishes updates server-side over Docker’s internal network and does not need to go through the public nginx route.

Note: This nginx proxy is only necessary because Mercure runs on a different subdomain than the main application. In setups where Mercure already shares the same origin as the app (or is configured as an external service with its own public URL and proper CORS headers), this step can be skipped. You can read more about Mercure setup options in the [Pimcore documentation].

Upgrading to Pimcore 2025.4

Upgrading to version 2025.4 is a prerequisite for installing Pimcore Studio. If you are already on Pimcore version 12, you can follow the following steps:

1 - Update platform version

 
composer require pimcore/platform-version:2025.4 

2 - Update dependencies 

 
composer update pimcore/* symfony/* 

3 - Run migrations

 
bin/console doctrine:migrations:migrate 

Check deprecated bundles

Note that the following bundles will become deprecated and Pimcore currently doesn’t offer replacements for them:

  • pimcore/file-explorer-bundle
  • pimcore/system-info-bundle
  • pimcore/seo-bundle

Bundle installation

Once the infrastructure is ready, you can start setting up the bundles. There are four bundles that you need to install:

Generic Data Index

Generic Data Index bundle indexes Pimcore elements (assets, objects, documents) into OpenSearch. To install it, follow the steps below:

1 - Install the required dependencies:

 
composer require pimcore/generic-data-index-bundle 

2 - Make sure the bundle is enabled in the config/bundles.php file. The following line should be added:

config/bundles.php
Pimcore\Bundle\GenericDataIndexBundle\PimcoreGenericDataIndexBundle::class => ['all' => true],  

3 - Install the bundle:

 
bin/console pimcore:bundle:install PimcoreGenericDataIndexBundle 

Generic Execution Engine

Generic Execution Engine bundle enables progress tracking of long-running background jobs. To install it, follow the steps below:

1- Install the required dependencies:

 
composer require phpdocumentor/reflection-docblock symfony/property-info 

2 - Make sure the bundle is enabled in the config/bundles.php file. The following line should be added:

config/bundles.php
Pimcore\Bundle\GenericExecutionEngineBundle\PimcoreGenericExecutionEngineBundle::class => ['all' => true], 

3 - Install the bundle:

 
bin/console pimcore:bundle:install PimcoreGenericExecutionEngineBundle 

Pimcore Studio Backend

Pimcore Studio Backend bundle serves as the central hub for API endpoints and RPC calls. To install it, follow the steps below:

1 - Install the required dependencies:

 
composer require pimcore/studio-backend-bundle

2 - Make sure the bundle is enabled in the config/bundles.php file. The following line should be added:

config/bundles.php
Pimcore\Bundle\GenericExecutionEngineBundle\PimcoreGenericExecutionEngineBundle::class => ['all' => true], 

3 - Install the bundle:

 
bin/console pimcore:bundle:install PimcoreGenericExecutionEngineBundle 

4 - Add the firewall configuration:

config/packages/security.yaml
security:
    firewalls:
        pimcore_studio: '%pimcore_studio_backend.firewall_settings%'
    access_control:
        - { path: ^/pimcore-studio/api/(docs|docs/json|translations|user/reset-password)$, roles: PUBLIC_ACCESS }
        - { path: ^/pimcore-studio/api, roles: ROLE_PIMCORE_USER }

Pimcore Studio UI

PimcoreStudioUiBundle provides React-based admin interface. To install it, follow the steps below:

1 - Install the required dependencies:

 
composer require pimcore/studio-ui-bundle 

2 - Make sure the bundle is enabled in the config/bundles.php file. The following line should be added:

config/bundles.php
Pimcore\Bundle\StudioUiBundle\PimcoreStudioUiBundle::class => ['all' => true],  

3 - Install the bundle: 

 
bin/console pimcore:bundle:install PimcoreStudioUiBundle 

Index creation

After successfully installing all four bundles, the next step is to understand how index creation and updates work. The main command used for managing indexes is:

 
bin/console generic-data-index:update:index 

It provides several options for building and updating indexes:

Option

Shortcut

Description

--class-definition-id=ID

-c

Update mapping and data for a specific data object class definition.

--update-asset-index

-a

Update mapping and data for the asset index.

--recreate_index

-r

Delete and recreate search indices.

--update-global-aliases-only

(none)

Update only global index aliases for data-object and element-search indices.

After the command finishes with index creation, you should be able to see your Pimcore elements in the React-based UI at its default URL {your-domain}/pimcore-studio.

Common Use Cases

If you create a new class definition or add a new attribute, you can update only that class:

 
bin/console generic-data-index:update:index -c Product 

If you modify or remove an attribute, you should recreate the index for that class: 

 
bin/console generic-data-index:update:index -c Product -r 

Using the -c and -r options together allows you to rebuild only the affected index instead of all indexes, which helps reduce downtime and speeds up the update process. 

After setting up Studio UI, you can start extending it using SDK hooks. Read more about customizing Pimcore Studio UI.

Conclusion

Pimcore Studio introduces a different way of working with the platform, but getting there requires more than enabling a new interface. As shown in this guide, Studio depends on a set of supporting services and bundles that work together to provide search, background processing, and real-time updates.

Once these components are correctly set up, Studio UI becomes fully operational and ready for everyday use. From that point on, teams can start working with Pimcore through a modern interface, while developers gain access to a more structured and maintainable foundation for further customization.

If you are planning a broader transition from the Classic Admin UI, this setup is only the first step. Understanding how Studio changes daily work, how to extend it, and how to approach migration should be considered next.

Looking for Exponential Growth? Let’s Get Started.
Explore next

Pimcore Whitepapers

Our Pimcore knowledge in your hands. Read and download our free whitepapers.

Discover more