Settings reference guide#

This is a summary of all the configuration options and what they control.


This list is still incomplete, contributions are welcomed!

Main settings#

They are exposed in config.settings:


For additional toolbar menus, the menu body component needs to be added to the on-demand loaded components.

config.settings.additionalToolbarComponents = {
  bookmarksMenu: {
    component: BookmarksEditorComponent,
    wrapper: null,

The plug:

<Plug pluggable="main.toolbar.bottom" id="bookmarks-menu">
  {({ onClickHandler }) => {
    return (
        onClick={(e) => onClickHandler(e, 'bookmarksMenu')}

You can configure the API expanders in Volto using settings.apiExpanders, as in the following example.

import { GET_CONTENT } from '@plone/volto/constants/ActionTypes';

export default function applyConfig (config) {
  config.settings.apiExpanders = [
        match: '',
        GET_CONTENT: ['mycustomexpander'],
        match: '/de',
        GET_CONTENT: ['myothercustomexpander'],
        match: '/de',
        GET_CONTENT: ['navigation'],
        querystring: {
          'expand.navigation.depth': 3,

  return config;

If you want Volto to make only a single request, combining all the expanders in it, then configure apiExpanders as shown.

config.settings.apiExpanders = [
    match: '',
    GET_CONTENT: ['breadcrumbs', 'navigation', 'actions', 'types'],

The configuration accepts a list of matchers, with the ability to filter by the request path and action type for maximum flexibility. It also accepts a querystring object that allows configuring the expanders via query string parameters, such as the navigation expander. The querystring object accepts a querystring object or a function that returns a querystring object.

export default function applyConfig (config) {
  config.settings.apiExpanders = [
        match: '',
        GET_CONTENT: ['mycustomexpander'],
        match: '/de',
        GET_CONTENT: ['myothercustomexpander'],
        match: '/de',
        GET_CONTENT: ['navigation'],
        querystring: (config) => ({
          'expand.navigation.depth': config.settings.navDepth,

  return config;

This is used in case that you want to pass current (as in resultant, in place) config options to the querystring object.


Per-route customizable asyncConnect action dispatcher. These enable proper server-side rendering of content that depends on additional async props coming from backend calls. It is a list of route-like configuration objects (they are matched using matchRoutes. Instead of the component key you should provide an extend method with signature asyncItems => asyncItems, so it receives a list of asyncConnect "prop" objects and returns a similar list. You can add new asyncConnected props as well as removing them, so you could, for example, have something like this to exclude the breadcrumbs from being requested:

config.settings.asyncPropsExtenders = [
    path: '/',
    extend: (dispatchActions) => dispatchActions.filter(asyncAction=> asyncAction.key !== 'breadcrumb')

Before Volto 10, the main content-grabbing request, triggered as a result of getContent action, always used the fullobjects flag, which fully serialized the immediate children of the context request. If your code depends on this behavior, set this flag to true in the settings object.


You should probably refactor your code to avoid depending on this behavior. It can cause performance issues when you have large children (for example content with lots of text) and you need to batch requests anyway, if you want to be sure to display all the children.


A Boolean, true by default. The fieldsets in the blocks settings tab start by default as non-collapsed (opened), you can decide to have them collapsed (closed) by default setting this to false.


With this property you can configure Content Types icons. Those are visible in Contents view (ex "Folder contents"). The default ones are in config/ContentIcons.jsx and you can extend them in your project's config for custom content types using settings.contentIcons.

In Volto projects, you can configure this for custom content types like:

import * as config from '@plone/volto/config';
import courseSVG from './icons/course.svg';

export const settings = {
  contentIcons: {
    Course: courseSVG,

The OpenGraph image that will represent this content item, will be used in the metadata HEAD tag as og:image for SEO purposes. Defaults to image. See the OpenGraph Protocol for more details.


Register a component as control panel.

Example configuration in config.js of your project or add-on:

config.settings.controlpanels = [
    '@id': '/manage-myaddon-subscriptions',
    group: 'Add-on Configuration',
    title: 'Breaking News Manage Subscriptions',

config.addonRoutes = [
    path: '/controlpanel/manage-myaddon-subscriptions',
    component: ManageSubscriptions,

The group can be one of the default groups 'General', 'Content', 'Security', 'Add-on Configuration', 'Users and Groups' or a custom group.


The name of the default block type used when a new block is added. The default value of this setting is slate, which uses the current Slate-based implementation for the rich text editor. If you change this to a different type of block, make sure the block configuration includes the blockHasValue function.


A list of error handlers that will be called when there is an unhandled exception. Each error handler is a function that receives a single argument, the error object.


A Boolean, false by default. The content menu links to the Links and references view per default. Exclude this menu item by setting excludeLinksAndReferencesMenuItem to true.


If another application is published under the same top domain as Volto, you could have a route like /abc which should be not rendered by Volto. This can be achieved by a rule in the reverse proxy (Apache or nginx for example) but, when navigating client side, you may have references to that route so Volto is handling that as an internal URL and fetching the content will break. You can disable that path in config.settings.externalRoutes so it will be handled as an external link.

config.settings.externalRoutes = [
    match: {
      path: '/news',
      exact: false,
      strict: false,
    url(payload) {
      return payload.location.pathname;

It can also be simplified as:

config.settings.externalRoutes = [
  { match: "/news" },
  { match: "/events" },

A schema factory for a control panel. It is used internally, to tweak the schemas provided by the controlpanel endpoint, to make them fit for Volto.


This setting will enable working copy support in your site. You need to install the add-on in your Plone site in order to make it working.


The initial state passed from server to browser needs to be minimal in order to optimize the resultant html generated. This state gets stored in window.__data and received in client.

You can blacklist a few reducers that you don't want to be part of window.__data,thus decreasing the initial html size for performance gains.

import * as config from '@plone/volto/config';

export const settings = {
  initialReducersBlacklist: [

A mapping of bundles to list of lazy library names. Create new bundles (or change the already provided cms bundle to be able to preload multiple lazy libraries (with preloadLazyLibs) or quickly load them with injectLazyLibs.


A mapping of loadable libraries that can be injected into components using the injectLazyLibs HOC wrapper. See the Lazy loading page for more details.


The maximum allowed size of file uploads (in bytes). Default: null (no limit enforced by Volto).


The library that we use to get files and images from the backend (superagent) has a response size limit of 200 mb, so if you want to get a file bigger than 200 mb from Plone, the SSR will throw an error.

You can edit this limit in the settings object setting a new value in bytes (for example, to set 500 mb you need to write 5000000000).


Navigation levels depth used in the navigation endpoint calls. Increasing this is useful for implementing fat navigation menus. Defaults to 1.


Volto provides an /ok URL where it responds with a text/plain ok response, with an HTTP 200 status code, to signal third party health check services that the Volto process is running correctly.

Using this setting, one can modify such an URL and configure it to respond with another URL.

The provided default URL matches the existing Plone Classic UI URL.

  config.settings.okRoute = '/site-is-ok'

A list of reducer names that should use the browser's localstorage to persist their data.


Volto uses HTTP POST requests to query the @querystring-search endpoint. This can create a lot of traffic between Volto and the backend, and can also create a lot of cache misses.

By modifying this configuration setting and setting it to true, the endpoint queries will be executed as HTTP GET requests. Thus any proxy cache in between Volto and the backend may cache those queries, improving your site performance.

Please be aware that this could break some other functionality in your site, or some of your queries may break, when they contain more than 2000 characters. See an explanation of character limits in URLs. Please test this setting properly before enabling in a production site.


In Volto 16.0.0.alpha.45, Sentry integration was moved from core to the add-on @plone-collective/volto-sentry.

See also

See Integration with Sentry.


Volto lets you modify how the site title is built. By default the site title only includes the title of the current page.

By modifying this configuration setting, you can decide whether to use the title of the navigation root (either the site root or the language root folder) as the second part of the title.

You can also decide the separator character between the current page title and the site title.

    siteTitleFormat: {
      includeSiteTitle: true,
      titleAndSiteTitleSeparator: '-',

A list of callables with signature (middlewaresList) => middlewaresList. These callables receive the whole stack of middlewares used in Volto and they can add new middleware or tweak this list.


An object with functions used by the style wrapper helpers to convert style data to actual class names. You can customize the generated classname by registering fieldnames with names such as <fieldname>:<converterName>, where the converter is registered here.


An array containing functions that extends how the StyleWrapper builds a list of styles. These functions have the signature ({ block, content, data, classNames }) => classNames. Here are some examples of useful ones, for simplicity, they are compacted in one extender:

  import { getPreviousNextBlock } from '@plone/volto/helpers';

  config.settings.styleClassNameExtenders = [
    ({ block, content, data, classNames }) => {
      let styles = [];
      const [previousBlock, nextBlock] = getPreviousNextBlock({

      // Inject a class depending of which type is the next block
      if (nextBlock?.['@type']) {

      // Inject a class depending if previous is the same type of block
      if (data?.['@type'] === previousBlock?.['@type']) {

      // Inject a class depending if next is the same type of block
      if (data?.['@type'] === nextBlock?.['@type']) {

      // Inject a class depending if it's the first of block type
      if (data?.['@type'] !== previousBlock?.['@type']) {

      // Inject a class depending if it's the last of block type
      if (data?.['@type'] !== nextBlock?.['@type']) {

      // Given a StyleWrapper defined `backgroundColor` style
      const previousColor =
        previousBlock?.styles?.backgroundColor ?? 'transparent';
      const currentColor = data?.styles?.backgroundColor ?? 'transparent';
      const nextColor = nextBlock?.styles?.backgroundColor ?? 'transparent';

      // Inject a class depending if the previous block has the same `backgroundColor`
      if (currentColor === previousColor) {
      } else if (currentColor !== previousColor) {

      // Inject a class depending if the next block has the same `backgroundColor`
      if (currentColor === nextColor) {
      } else if (currentColor !== nextColor) {

      return [...classNames, ...styles];

It's an object that defines the mapping between workflow states/transitions and the color that should show in the change Workflow dropdown. This is the default:

export const workflowMapping = {
  published: { value: 'published', color: '#007bc1' },
  publish: { value: 'publish', color: '#007bc1' },
  private: { value: 'private', color: '#ed4033' },
  pending: { value: 'pending', color: '#f6a808' },
  send_back: { value: 'private', color: '#ed4033' },
  retract: { value: 'private', color: '#ed4033' },
  reject: { value: 'private', color: '#ed4033' },
  submit: { value: 'review', color: '#f4e037' },

It's meant to be extended with your own workflows/transitions. It is recommended to assign the same color to the transition as the destination state, so the user can have the visual hint to which state are they transitioning to.

Views settings#

They are exposed in config.views:


Plone's layout views are identified by a simple string. This object maps this string with a nice literal (in English as default). These view names are exposed in the Display component in the toolbar's more menu. The keys are the name of the Plone layout, and the values are the i18n string id:

export const layoutViewsNamesMapping = {
  album_view: 'Album view',
  event_listing: 'Event listing',
  full_view: 'All content',
  listing_view: 'Listing view',
  summary_view: 'Summary view',
  tabular_view: 'Tabular view',
  layout_view: 'Mosaic layout',
  document_view: 'Document view',
  folder_listing: 'Folder listing',
  newsitem_view: 'News item view',
  link_redirect_view: 'Link redirect view',
  file_view: 'File view',
  image_view: 'Image view',
  event_view: 'Event view',
  view: 'Default view',

You can customize this object to add or modify the existing entries. They are i18n aware, so you can add the corresponding i18n message in your project's src/config.js or your add-on's src/index.js:

import { defineMessages } from 'react-intl';
  album_view: {
    id: 'Album view',
    defaultMessage: 'Album view',

Server-specific serverConfig#

Settings that are relevant to the Express-powered Volto SSR server are stored in the config.settings.serverConfig object.


A path relative to the project root that points to an optional CSS file. If this file exists it is loaded and its content is embedded inline into the generated HTML. By default this path is public/critical.css. See the critical.css (above the fold) optimizations section for more details.


A list of ExpressJs middleware that can extend the built-in functionality of Volto's server. See the Express section for more details.