Company branding setup#

Configuring branding.json in Sherpa AI Server#

Purpose#

The branding.json file lets you change the appearance and part of the behavior of the Sherpa AI Server interface without rebuilding the frontend:

  • name and logos;
  • main colors, border radius, and font;
  • user and Assistant message backgrounds;
  • default language and available languages;
  • display of the OpenID sign-in button;
  • additional links in the side menu;
  • an information button on the sign-in page.

The settings are applied in the browser when the application loads. There is no separate branding administration screen in Sherpa AI Server.

Where the file is located#

In source code#

Main file:

frontend/src/assets/branding/branding.json

It is included in the frontend build and is used as the default settings set for the distribution.

In the client distribution#

When preparing the client archive, the file is copied here:

frontend/config/branding.json

To make nginx use this file, enable a bind mount in the docker-compose.yml file for the aiserver-nginx service:

services:
  aiserver-nginx:
    volumes:
      - ./frontend/config/branding.json:/opt/SherpaAIServer/frontend/dist/assets/branding/branding.json:ro

In the distributed docker-compose.yml, this line may be commented out. After enabling the mount for the first time, recreate the container:

docker compose up -d --force-recreate aiserver-nginx

If the mount is already enabled, changes to the file on the host are visible inside the container immediately. Reloading the page is enough to apply them in the interface.

How the configuration is loaded#

When the frontend starts, it requests:

/assets/branding/branding.json

The configuration is loaded before the Angular application starts. Because of that, the language, logos, and branding CSS variables are available during the initial rendering of the interface.

Loading rules:

  1. Built-in Sherpa AI Server values are used as the base.
  2. Fields from branding.json replace the corresponding built-in values.
  3. If the file is unavailable or contains invalid JSON, the application continues to work with the built-in values.
  4. Missing top-level fields do not need to be specified: the built-in values are preserved for them.
  5. Nested objects and array items are not filled in automatically — they must be set in full.

The _comments field inside the standard branding.json file contains reference descriptions. This is a normal JSON helper field; the interface does not use it.

Quick start#

  1. Copy or edit frontend/config/branding.json.

  2. Make sure the bind mount is enabled in docker-compose.yml.

  3. Check the JSON syntax:

    jq empty frontend/config/branding.json
    
  4. When connecting the file for the first time, recreate aiserver-nginx:

    docker compose up -d --force-recreate aiserver-nginx
    
  5. Check which file the server is serving:

    curl -fsS https://<server-address>/assets/branding/branding.json | jq .
    
  6. Reload the Sherpa AI Server page. If the browser shows stale resources, perform a hard refresh.

Complete example#

{
  "app_name": "Корпоративный AI",
  "logo_url": "assets/branding/logo-light-v1.svg",
  "logo_url_light": "assets/branding/logo-light-v1.svg",
  "logo_url_dark": "assets/branding/logo-dark-v1.svg",
  "disable_openid": false,
  "default_language": "ru",
  "available_languages": ["ru", "en"],
  "additional_menu_items": [
    {
      "button_name": {
        "ru": "Поддержка",
        "en": "Support"
      },
      "url": "https://support.example.org",
      "icon": "question-mark-circle-outline"
    },
    {
      "button_name": {
        "ru": "Инструкции",
        "en": "Documentation"
      },
      "url": "/main/documents",
      "icon": "book-open-outline"
    }
  ],
  "additional_login_button": {
    "button_name": {
      "ru": "Как получить доступ?",
      "en": "How do I get access?"
    },
    "message": {
      "ru": "Для получения доступа обратитесь в службу поддержки.",
      "en": "Contact the support team to request access."
    }
  },
  "primary_color": "#2563eb",
  "primary_dark_color": "#1d4ed8",
  "primary_light_color": "#60a5fa",
  "primary_rgb": "37, 99, 235",
  "secondary_color": "#1f2937",
  "border_radius": "8px",
  "font_family": "Inter, sans-serif",
  "font_url": "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap",
  "chat_user_bg": "#eff6ff",
  "chat_assistant_bg": "#ffffff"
}

Parameter descriptions#

Parameter Format Purpose
app_name string Name next to the logo in the side menu and the logo alt text. It does not change the sign-in card title or the page <title>Sherpa AI Server is currently used there.
logo_url URL string Fallback logo for compatibility. Used if a separate logo for the required theme is not set.
logo_url_light URL string Logo for the light theme.
logo_url_dark URL string Logo for the dark theme.
disable_openid true or false When true, hides the Sign in with OpenID button on the sign-in page. The parameter controls the interface and by itself does not disable OpenID on the backend.
default_language ru or en Default language. The value must be present in available_languages.
available_languages array of ru and/or en Languages available to the user. Other values are discarded.
additional_menu_items array of objects Additional permanent items in the side menu before the Chat section.
additional_login_button object or null Information button on the sign-in page. Clicking it opens a dialog with localized text. null hides the button.
primary_color #RRGGBB Main color for buttons, links, active elements, tables, and form controls.
primary_dark_color #RRGGBB Darker shade of the main color for hover and press states and some switches.
primary_light_color #RRGGBB Lighter shade for highlights and secondary states.
primary_rgb R, G, B string RGB components of primary_color for translucent backgrounds, shadows, and highlights.
secondary_color CSS color Secondary color. It is also used for card surfaces in the dark theme and the splash screen.
border_radius CSS size Element rounding, for example 0px, 6px, or 16px.
font_family CSS font-family Font family applied to the interface.
font_url CSS file URL Stylesheet from which the browser loads the font. An empty string disables the extra download.
chat_user_bg CSS color Background of user messages on the Chat screen.
chat_assistant_bg CSS color Background of Assistant responses on the Chat screen.

Configuring logos#

Logo selection priority for each theme:

logo_url_light or logo_url_dark → logo_url → built-in logo

You can use:

  • a relative path inside the frontend, for example assets/branding/logo-light-v1.svg;
  • an absolute path from the site root, for example /assets/branding/logo-light-v1.svg;
  • an absolute URL, for example https://static.example.org/logo-light-v1.svg.

If the logo is stored alongside the client configuration, mount it separately in docker-compose.yml:

services:
  aiserver-nginx:
    volumes:
      - ./frontend/config/branding.json:/opt/SherpaAIServer/frontend/dist/assets/branding/branding.json:ro
      - ./frontend/config/logo-light-v1.svg:/opt/SherpaAIServer/frontend/dist/assets/branding/logo-light-v1.svg:ro
      - ./frontend/config/logo-dark-v1.svg:/opt/SherpaAIServer/frontend/dist/assets/branding/logo-dark-v1.svg:ro

In production, images, fonts, and other static files can be cached by the browser for up to a year. When the logo content changes, use a new name, for example logo-light-v2.svg, and update the path in branding.json.

Configuring colors#

primary_color and primary_rgb describe the same color in different formats. They are not synchronized automatically.

Example:

{
  "primary_color": "#2563eb",
  "primary_rgb": "37, 99, 235"
}

For primary_color, primary_dark_color, and primary_light_color, use the full #RRGGBB HEX format. The service calculates the contrast of the main color for text and icons, so shortened HEX and rgb(...) or rgba(...) values should not be used for these three fields.

For secondary_color, chat_user_bg, and chat_assistant_bg, regular CSS colors such as HEX or rgba(...) are allowed.

After changing colors, check both themes, tables, form fields, buttons, and the readability of chat messages.

Configuring the font#

font_url must point to a CSS file with the font, and font_family must point to the family name from that CSS file:

{
  "font_family": "Inter, sans-serif",
  "font_url": "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
}

For a custom font, you can mount the CSS and font files into the frontend directory and use a relative URL. Make sure the URL is accessible from the users' browsers, not only from the Sherpa AI Server backend.

To avoid loading an extra CSS file, leave font_url empty:

{
  "font_family": "Roboto, 'Helvetica Neue', sans-serif",
  "font_url": ""
}

Interface languages#

Only ru and en values are supported.

If available_languages is empty, has an invalid format, or does not contain supported values, Sherpa AI Server enables both languages. If default_language is missing from the available languages list, the first available_languages item becomes the default language.

Example of an interface in Russian only:

{
  "default_language": "ru",
  "available_languages": ["ru"]
}

The current-language button remains visible, but the switcher menu does not open.

The actual language is selected in the following order:

  1. the lang or locale parameter in the URL;
  2. the previously selected browser language;
  3. default_language from branding.json.

The value from the URL or browser is applied only when the language is present in available_languages.

Additional menu items#

Each additional_menu_items entry must contain:

{
  "button_name": {
    "ru": "Поддержка",
    "en": "Support"
  },
  "url": "https://support.example.org",
  "icon": "question-mark-circle-outline"
}

Rules:

  • at least one non-empty translation of the name is required;
  • url must be an internal path with a single leading / or a URL with the http or https protocol;
  • values with other protocols and invalid URLs are ignored;
  • internal links open through the Sherpa AI Server router;
  • external links open in the current tab;
  • items are displayed in the same order as in the array;
  • for a standard icon, specify an Eva Icons name, for example book-open-outline;
  • a string ending in / or .svg is treated as a path to a custom SVG icon.

If a translation is missing, Russian is used first, then English.

Information button on the sign-in page#

Example:

{
  "additional_login_button": {
    "button_name": {
      "ru": "Forgot your password?",
      "en": "Forgot your password?"
    },
    "message": {
      "ru": "Contact the support team.",
      "en": "Contact the support team."
    }
  }
}

The button is shown if at least one name and at least one message text are filled in. The text is displayed as plain text, not HTML. If a translation is missing, Russian is used first, then English.

To hide the button:

{
  "additional_login_button": null
}