Настройка бренда компании#
Настройка 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
Для загрузки клиентской конфигурации необходимо включить в 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 эта строка может быть закомментирована. После первого подключения файла необходимо пересоздать контейнер:
docker compose up -d --force-recreate aiserver-nginx
Если mount уже включен, изменения файла на хосте сразу видны внутри контейнера. Для их применения в интерфейсе достаточно перезагрузить страницу.
Как загружается конфигурация#
При старте frontend запрашивает:
/assets/branding/branding.json
Конфигурация загружается до запуска Angular-приложения. Поэтому язык, логотипы и CSS-переменные брендинга доступны уже при начальной отрисовке интерфейса.
Правила загрузки:
- Встроенные значения Sherpa AI Server используются как база.
- Поля из
branding.jsonзаменяют соответствующие встроенные значения. - Если файл недоступен или содержит некорректный JSON, приложение продолжает работу со встроенными значениями.
- Если верхнеуровневое поле не указано, сохраняется его встроенное значение.
- Вложенные объекты и элементы массивов необходимо задавать целиком. Исключение —
chat_model_picker_text: его верхнеуровневые подполя дополняются встроенными значениями.
Поле _comments внутри стандартного branding.json содержит справочные описания. Это обычное служебное поле JSON, интерфейс его не использует.
Быстрый старт#
Перед изменением необходимо сохранить копию
frontend/config/branding.json. Затем требуется подготовить или изменить рабочий файл.Необходимо проверить, что bind mount включен в
docker-compose.yml.Для обнаружения ошибок в JSON используется команда:
jq empty frontend/config/branding.jsonПри первом подключении файла необходимо пересоздать
aiserver-nginx:docker compose up -d --force-recreate aiserver-nginxДля проверки файла, который отдает сервер, используется команда. Адрес
ai.example.orgнеобходимо заменить адресом своей установки:curl -fsS https://ai.example.org/assets/branding/branding.json | jq .Для загрузки настроек необходимо перезагрузить страницу 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",
"favicon_url": "favicon.ico",
"disable_openid": false,
"hide_chat_scope_switch": false,
"hide_language_selector": false,
"hide_unavailable_menu_items": false,
"auto_expand_sidebar_sections": 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>). |
logo_url |
строка URL | Резервный логотип для совместимости. Используется, если отдельный логотип нужной темы не задан. |
logo_url_light |
строка URL | Логотип для светлой темы. |
logo_url_dark |
строка URL | Логотип для темной темы. |
favicon_url |
строка URL | Иконка вкладки браузера. Относительный путь внутри frontend или абсолютный URL; по умолчанию favicon.ico. |
disable_openid |
true или false |
При true скрывает кнопку Войти через OpenID на странице входа. Параметр управляет интерфейсом и сам по себе не отключает OpenID на backend. |
hide_chat_scope_switch |
true или false |
При true скрывает переключатель "Общие / Личные чаты" в обычной и компактной боковой панели. По умолчанию false. Список чатов по-прежнему выбирается по типу входа: Пользователь — личные, Аккаунт — общие. |
hide_language_selector |
true или false |
При true скрывает переключатель языка на странице входа и в шапке. Язык определяется настройками и доступными языками. По умолчанию false. |
hide_unavailable_menu_items |
true или false |
При true скрывает пункты меню, недоступные Пользователю по его Роли. По умолчанию false: пункты остаются видимыми, но неактивными. |
auto_expand_sidebar_sections |
true или false |
При false разделы Чат, Ассистенты и API не раскрываются автоматически при входе и переходах между экранами. Для ручного раскрытия используется стрелка у названия раздела. По умолчанию true: разделы раскрываются автоматически. |
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-цвет | Фон ответов Ассистента на экране Чат. |
Скрытие переключателя чатов#
Для скрытия переключателя "Общие / Личные чаты" в боковой панели необходимо задать в branding.json:
{
"hide_chat_scope_switch": true
}
После проверки JSON необходимо обновить страницу и открыть раздел Чат. Переключатель должен исчезнуть в обычной и компактной панели; "Новый диалог" и список чатов остаются. При входе Пользователя загружаются личные чаты, при входе под Аккаунтом — общие. Для возврата переключателя необходимо установить false или удалить параметр и обновить страницу.
Настройка логотипов#
Приоритет выбора логотипа для каждой темы:
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.
Для иконки вкладки необходимо задать favicon_url. Если файл находится в клиентской поставке, необходимо указать доступный браузеру путь и при необходимости смонтировать файл в nginx-контейнер так же, как логотип. Новое имя файла при изменении иконки предотвращает загрузку прежней версии из кэша.
Настройка цветов#
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. Этот адрес должен открываться в браузерах Пользователей, а не только на сервере 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"]
}
Кнопка текущего языка остается видимой, но меню переключения не открывается.
Для скрытия кнопки языка на странице входа и в шапке необходимо задать "hide_language_selector": true. Если Пользователям нужен видимый переключатель, сохраняется значение false.
Фактический язык выбирается в следующем порядке:
- параметр
langилиlocaleв URL; - ранее выбранный язык из браузера;
default_languageизbranding.json.
Значение из URL или браузера применяется только тогда, когда язык присутствует в available_languages.
Параметр hide_unavailable_menu_items управляет только видимостью пунктов бокового меню: права доступа по Роли он не меняет. При значении true недоступные разделы исчезнут; при false они отображаются неактивными.
Дополнительные пункты меню#
Каждый элемент 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
}
Карточки Главной#
Параметр home_featured_cards задает карточки блока "Начните с главного". Порядок элементов массива определяет порядок карточек; количество не ограничено четырьмя. Чтобы добавить, удалить или переименовать карточку, необходимо изменить массив в клиентском branding.json и перезагрузить страницу.
В примере задана одна карточка чата. Необходимо добавить поле в существующую конфигурацию, сохранив остальные настройки:
{
"home_featured_cards": [
{
"id": "chat",
"title": { "ru": "Чат", "en": "Chat" },
"description": { "ru": "Новый диалог", "en": "New conversation" },
"icon": "message-circle-outline",
"action": { "type": "route", "url": "/main/new-chat" }
}
]
}
Для каждой карточки необходимо указать уникальный id, непустые title и description на ru и en, имя icon и действие action. Действие route открывает доступный внутренний маршрут. Действие assistant с полем assistant_guid открывает новый чат с указанным Ассистентом; GUID необходимо взять у существующего доступного Ассистента.
Корректный массив полностью заменяет стандартный набор. Если поле отсутствует, равно null, содержит пустой массив или некорректные карточки, используются стандартные карточки из приложения. Пустой массив не скрывает все карточки. Недоступные по правам разделы отфильтровываются. Карточка с действием assistant отображается только при правах чтения Чата и Ассистентов; настройка не изменяет права Роли и доступ к Ассистентам.
Закрепленные Ассистенты добавляются после карточек из home_featured_cards автоматически. Этот параметр не управляет их закреплением. Если Ассистент уже указан в конфигурации, второй карточки для него не будет.
Если изменения не появились, необходимо проверить синтаксис JSON, загрузку нужного файла и права учетной записи. При неверном GUID Ассистента требуется исправить значение в конфигурации. Отдельный редактор карточек в интерфейсе не используется.