feat(branding): update UltiAI branding and configuration
Some checks are pending
CI / Go tests (push) Waiting to run
CI / Integration tests (push) Waiting to run
CI / DB migrations (push) Waiting to run

- Added WEBUI_NAME variable to .env.example and Docker Compose for consistent branding.
- Enhanced Nginx configuration with sub_filters to replace 'Open WebUI' with 'UltiAI' in responses.
- Introduced custom CSS for UltiAI branding and added logo and favicon assets.
- Implemented routing adjustments in Nginx to support SPA navigation without prefix issues.
This commit is contained in:
R3D347HR4Y 2026-06-13 22:55:35 +02:00
parent bda75aeb0d
commit 1e4e373f93
7 changed files with 57 additions and 0 deletions

View File

@ -178,6 +178,7 @@ WEBUI_SECRET_KEY=changeme-openwebui-dev-secret
AI_GATEWAY_API_KEY=ulti-gateway AI_GATEWAY_API_KEY=ulti-gateway
# OpenWebUI embed : modèles ultid visibles sans entrée DB par modèle # OpenWebUI embed : modèles ultid visibles sans entrée DB par modèle
BYPASS_MODEL_ACCESS_CONTROL=true BYPASS_MODEL_ACCESS_CONTROL=true
WEBUI_NAME=UltiAI
AI_ASSISTANT_PUBLIC_PATH=/ai AI_ASSISTANT_PUBLIC_PATH=/ai
ULTIMAIL_MCP_URL=http://ultimail-mcp:3100 ULTIMAIL_MCP_URL=http://ultimail-mcp:3100
# OpenWebUI utilise POSTGRES_USER/POSTGRES_PASSWORD (base openwebui créée dans init-db.sh) # OpenWebUI utilise POSTGRES_USER/POSTGRES_PASSWORD (base openwebui créée dans init-db.sh)

View File

@ -383,6 +383,11 @@ server {
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade; proxy_set_header Connection $connection_upgrade;
proxy_set_header Accept-Encoding "";
sub_filter_once off;
sub_filter_types application/json text/plain;
sub_filter 'UltiAI (Open WebUI)' 'UltiAI';
sub_filter 'Open WebUI' 'UltiAI';
proxy_read_timeout 86400s; proxy_read_timeout 86400s;
proxy_send_timeout 86400s; proxy_send_timeout 86400s;
} }
@ -643,6 +648,20 @@ server {
# SvelteKit base path — without this, /ai/ routes 404 (base "" expects site root) # SvelteKit base path — without this, /ai/ routes 404 (base "" expects site root)
sub_filter 'base: ""' 'base: "/ai"'; sub_filter 'base: ""' 'base: "/ai"';
sub_filter "base: ''" 'base: "/ai"'; sub_filter "base: ''" 'base: "/ai"';
# In-app links that escape to site root (e.g. "Nouvelle conversation" → /)
sub_filter 'href="/"' 'href="/ai/"';
sub_filter "href='/'" "href='/ai/'";
sub_filter 'href="/notes' 'href="/ai/notes';
sub_filter 'href="/workspace' 'href="/ai/workspace';
sub_filter 'href="/home' 'href="/ai/home';
sub_filter 'href="/c/' 'href="/ai/c/';
sub_filter 'href="/automations' 'href="/ai/automations';
sub_filter 'href="/calendar' 'href="/ai/calendar';
sub_filter 'href="/channels' 'href="/ai/channels';
sub_filter 'href="/playground' 'href="/ai/playground';
# UltiAI branding (WEBUI_NAME env still appends " (Open WebUI)" in backend)
sub_filter 'UltiAI (Open WebUI)' 'UltiAI';
sub_filter 'Open WebUI' 'UltiAI';
} }
location = /ai { location = /ai {
@ -692,6 +711,10 @@ server {
sub_filter_types application/javascript text/javascript; sub_filter_types application/javascript text/javascript;
sub_filter '"/api/' '"/ai/api/'; sub_filter '"/api/' '"/ai/api/';
sub_filter "'/api/" "'/ai/api/"; sub_filter "'/api/" "'/ai/api/";
sub_filter 'href="/"' 'href="/ai/"';
sub_filter "href='/'" "href='/ai/'";
sub_filter 'Open WebUI' 'UltiAI';
sub_filter 'UltiAI (Open WebUI)' 'UltiAI';
} }
location ^~ /_app/ { location ^~ /_app/ {
@ -718,6 +741,10 @@ server {
sub_filter_types application/javascript text/javascript application/json; sub_filter_types application/javascript text/javascript application/json;
sub_filter '"/api/' '"/ai/api/'; sub_filter '"/api/' '"/ai/api/';
sub_filter "'/api/" "'/ai/api/"; sub_filter "'/api/" "'/ai/api/";
sub_filter 'href="/"' 'href="/ai/"';
sub_filter "href='/'" "href='/ai/'";
sub_filter 'Open WebUI' 'UltiAI';
sub_filter 'UltiAI (Open WebUI)' 'UltiAI';
} }
location = /manifest.json { location = /manifest.json {
@ -1002,6 +1029,12 @@ server {
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
} }
# OpenWebUI SPA routes without /ai prefix (client nav + hard reload in UltiAI iframe).
# Do not include "auth" — Ultimail OIDC uses /auth/application/o/… (Authentik).
location ~ ^/(notes|workspace|c|home|automations|calendar|channels|playground|watch|s|error)(/|$) {
return 302 /ai$uri$is_args$args;
}
location / { location / {
default_type text/plain; default_type text/plain;
return 404 "Not found\n"; return 404 "Not found\n";

View File

@ -11,6 +11,7 @@ services:
ENABLE_PERSISTENT_CONFIG: "false" ENABLE_PERSISTENT_CONFIG: "false"
ENABLE_DIRECT_CONNECTIONS: "false" ENABLE_DIRECT_CONNECTIONS: "false"
BYPASS_MODEL_ACCESS_CONTROL: "true" BYPASS_MODEL_ACCESS_CONTROL: "true"
WEBUI_NAME: UltiAI
OPENAI_API_BASE_URL: http://ultid:8080/api/v1/ai OPENAI_API_BASE_URL: http://ultid:8080/api/v1/ai
OPENAI_API_KEY: ${AI_GATEWAY_API_KEY:-ulti-gateway} OPENAI_API_KEY: ${AI_GATEWAY_API_KEY:-ulti-gateway}
WEBUI_URL: http://${DOMAIN:-localhost}/ai WEBUI_URL: http://${DOMAIN:-localhost}/ai
@ -20,6 +21,9 @@ services:
volumes: volumes:
- openwebui_data:/app/backend/data - openwebui_data:/app/backend/data
- ../services/openwebui/pipelines:/app/pipelines/custom:ro - ../services/openwebui/pipelines:/app/pipelines/custom:ro
- ../services/openwebui/static/logo.png:/app/backend/open_webui/static/logo.png:ro
- ../services/openwebui/static/favicon.png:/app/backend/open_webui/static/favicon.png:ro
- ../services/openwebui/static/custom.css:/app/backend/open_webui/static/custom.css:ro
networks: networks:
- ulti-net - ulti-net
depends_on: depends_on:

View File

@ -0,0 +1,4 @@
/* UltiAI branding overrides (OpenWebUI custom.css hook) */
:root {
--ultiai-brand: #1a73e8;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40" fill="none" aria-hidden="true">
<!-- UltiAI: sparkle 4 quadrants plats (ordre UltiDrive) + sparkle secondaire jaune -->
<defs>
<clipPath id="uai-spark">
<path d="M17 3c.9 7.4 2.5 10.8 4.7 13s5.6 3.8 13 4.7c-7.4.9-10.8 2.5-13 4.7s-3.8 5.6-4.7 13c-.9-7.4-2.5-10.8-4.7-13s-5.6-3.8-13-4.7c7.4-.9 10.8-2.5 13-4.7S16.1 10.4 17 3z"/>
</clipPath>
</defs>
<g clip-path="url(#uai-spark)">
<rect x="0" y="0" width="17" height="20.7" fill="#EA4335"/>
<rect x="17" y="0" width="23" height="20.7" fill="#4285F4"/>
<rect x="0" y="20.7" width="17" height="20" fill="#FBBC04"/>
<rect x="17" y="20.7" width="23" height="20" fill="#34A853"/>
</g>
<path fill="#FBBC04" d="M31.5 2c.5 3.6 1.2 5.3 2.3 6.4 1.1 1.1 2.8 1.8 6.4 2.3-3.6.5-5.3 1.2-6.4 2.3-1.1 1.1-1.8 2.8-2.3 6.4-.5-3.6-1.2-5.3-2.3-6.4-1.1-1.1-2.8-1.8-6.4-2.3 3.6-.5 5.3-1.2 6.4-2.3 1.1-1.1 1.8-2.8 2.3-6.4z"/>
</svg>

After

Width:  |  Height:  |  Size: 960 B