Настройка бренда компании#

Настройка branding.json в Sherpa AI Server#

Назначение#

Файл branding.json позволяет изменить оформление и часть поведения интерфейса Sherpa AI Server без пересборки frontend:

  • название и логотипы;
  • основные цвета, скругления и шрифт;
  • фон сообщений пользователя и Ассистента;
  • язык по умолчанию и доступные языки;
  • отображение кнопки входа через OpenID;
  • дополнительные ссылки в боковом меню;
  • информационную кнопку на странице входа.

Настройки применяются в браузере при загрузке приложения. Отдельного экрана администрирования брендинга в Sherpa AI Server нет.

Где находится файл#

В исходном коде#

Основной файл:

frontend/src/assets/branding/branding.json

Он входит во frontend-сборку и используется как набор настроек по умолчанию для поставки.

В клиентской поставке#

При подготовке клиентского архива файл копируется сюда:

frontend/config/branding.json

Чтобы контейнер nginx использовал этот файл, в docker-compose.yml нужно включить bind mount в сервисе aiserver-nginx:

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

В поставляемом docker-compose.yml эта строка может быть закомментирована. После первого включения mount пересоздайте контейнер:

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

Если mount уже включён, изменения файла на хосте сразу видны внутри контейнера. Для их применения в интерфейсе достаточно перезагрузить страницу.

Как загружается конфигурация#

При старте frontend запрашивает:

/assets/branding/branding.json

Конфигурация загружается до запуска Angular-приложения. Поэтому язык, логотипы и CSS-переменные брендинга доступны уже при начальной отрисовке интерфейса.

Правила загрузки:

  1. Встроенные значения Sherpa AI Server используются как база.
  2. Поля из branding.json заменяют соответствующие встроенные значения.
  3. Если файл недоступен или содержит некорректный JSON, приложение продолжает работу со встроенными значениями.
  4. Отсутствующие верхнеуровневые поля можно не указывать: для них сохраняются встроенные значения.
  5. Вложенные объекты и элементы массивов не дополняются автоматически — их нужно задавать целиком.

Файл _comments внутри стандартного branding.json содержит справочные описания. Это обычное служебное поле JSON, интерфейс его не использует.

Быстрый старт#

  1. Скопируйте или отредактируйте frontend/config/branding.json.

  2. Убедитесь, что bind mount включён в docker-compose.yml.

  3. Проверьте синтаксис JSON:

    jq empty frontend/config/branding.json
    
  4. При первом подключении файла пересоздайте aiserver-nginx:

    docker compose up -d --force-recreate aiserver-nginx
    
  5. Проверьте, какой файл отдаёт сервер:

    curl -fsS https://<адрес-сервера>/assets/branding/branding.json | jq .
    
  6. Перезагрузите страницу Sherpa AI Server. Если браузер показывает старые ресурсы, выполните принудительное обновление страницы.

Полный пример#

{
  "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"
}

Описание параметров#

Параметр Формат Назначение
app_name строка Название рядом с логотипом в боковом меню и текст alt логотипа. Не изменяет заголовок карточки входа и <title> страницы — там сейчас используется Sherpa AI Server.
logo_url строка URL Резервный логотип для совместимости. Используется, если отдельный логотип нужной темы не задан.
logo_url_light строка URL Логотип для светлой темы.
logo_url_dark строка URL Логотип для тёмной темы.
disable_openid true или false При true скрывает кнопку Войти через OpenID на странице входа. Параметр управляет интерфейсом и сам по себе не отключает OpenID на backend.
default_language ru или en Язык по умолчанию. Значение должно присутствовать в available_languages.
available_languages массив ru и/или en Языки, доступные пользователю. Другие значения отбрасываются.
additional_menu_items массив объектов Дополнительные постоянные пункты в боковом меню перед разделом Чат.
additional_login_button объект или null Информационная кнопка на странице входа. При нажатии открывается диалог с локализованным текстом. null скрывает кнопку.
primary_color #RRGGBB Основной цвет кнопок, ссылок, активных элементов, таблиц и элементов форм.
primary_dark_color #RRGGBB Тёмный оттенок основного цвета для состояний наведения, нажатия и части переключателей.
primary_light_color #RRGGBB Светлый оттенок для подсветки и вторичных состояний.
primary_rgb строка R, G, B RGB-компоненты primary_color для полупрозрачных фонов, теней и выделений.
secondary_color CSS-цвет Вторичный цвет. В том числе используется для поверхностей карточек в тёмной теме и заставки.
border_radius CSS-размер Скругление элементов, например 0px, 6px или 16px.
font_family CSS font-family Семейство шрифта, применяемое к интерфейсу.
font_url URL CSS-файла Таблица стилей, из которой браузер загружает шрифт. Пустая строка отключает дополнительную загрузку.
chat_user_bg CSS-цвет Фон сообщений пользователя на экране Чат.
chat_assistant_bg CSS-цвет Фон ответов Ассистента на экране Чат.

Настройка логотипов#

Приоритет выбора логотипа для каждой темы:

logo_url_light или logo_url_dark → logo_url → встроенный логотип

Можно использовать:

  • относительный путь внутри frontend, например assets/branding/logo-light-v1.svg;
  • абсолютный путь от корня сайта, например /assets/branding/logo-light-v1.svg;
  • абсолютный URL, например https://static.example.org/logo-light-v1.svg.

Если логотип хранится рядом с клиентской конфигурацией, подключите его в docker-compose.yml отдельным mount:

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

В production изображения, шрифты и другие статические файлы могут кэшироваться браузером на срок до года. При изменении содержимого логотипа используйте новое имя, например logo-light-v2.svg, и обновите путь в branding.json.

Настройка цветов#

primary_color и primary_rgb описывают один и тот же цвет в разных форматах. Они не синхронизируются автоматически.

Пример:

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

Для primary_color, primary_dark_color и primary_light_color следует использовать полный HEX-формат #RRGGBB. Сервис рассчитывает контраст основного цвета для текста и иконок, поэтому сокращённый HEX и значения rgb(...) или rgba(...) для этих трёх полей использовать не следует.

Для secondary_color, chat_user_bg и chat_assistant_bg допустимы обычные CSS-цвета, например HEX или rgba(...).

После изменения цветов проверьте обе темы, таблицы, поля форм, кнопки и читаемость сообщений в чате.

Настройка шрифта#

font_url должен указывать на CSS-файл со шрифтом, а font_family — на имя семейства из этого CSS-файла:

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

Для собственного шрифта можно смонтировать CSS и файлы шрифта в каталог frontend и использовать относительный URL. Убедитесь, что URL доступен из браузеров пользователей, а не только с сервера Sherpa AI Server.

Чтобы не загружать дополнительный CSS-файл, оставьте font_url пустым:

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

Языки интерфейса#

Поддерживаются только значения ru и en.

Если available_languages пуст, имеет неверный формат или не содержит поддерживаемых значений, Sherpa AI Server включает оба языка. Если default_language отсутствует в списке доступных языков, языком по умолчанию становится первый элемент available_languages.

Пример интерфейса только на русском языке:

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

Кнопка текущего языка остаётся видимой, но меню переключения не открывается.

Фактический язык выбирается в следующем порядке:

  1. параметр lang или locale в URL;
  2. ранее выбранный язык из браузера;
  3. default_language из branding.json.

Значение из URL или браузера применяется только тогда, когда язык присутствует в available_languages.

Дополнительные пункты меню#

Каждый элемент additional_menu_items должен содержать:

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

Правила:

  • нужен хотя бы один непустой перевод названия;
  • url должен быть внутренним путём с одним начальным / либо URL с протоколом http или https;
  • значения с другими протоколами и некорректные URL игнорируются;
  • внутренние ссылки открываются через маршрутизатор Sherpa AI Server;
  • внешние ссылки открываются в текущей вкладке;
  • элементы выводятся в том же порядке, что и в массиве;
  • для стандартной иконки укажите имя Eva Icons, например book-open-outline;
  • строка с / или окончанием .svg воспринимается как путь к собственной SVG-иконке.

Для отсутствующего перевода используется русский, затем английский вариант.

Информационная кнопка на странице входа#

Пример:

{
  "additional_login_button": {
    "button_name": {
      "ru": "Забыли пароль?",
      "en": "Forgot your password?"
    },
    "message": {
      "ru": "Обратитесь в службу поддержки.",
      "en": "Contact the support team."
    }
  }
}

Кнопка отображается, если заполнены хотя бы одно название и хотя бы один текст сообщения. Текст выводится как обычный текст, а не как HTML. Для отсутствующего перевода используется русский, затем английский вариант.

Чтобы скрыть кнопку:

{
  "additional_login_button": null
}