From e9ad25995797eefde3409479a4e2a76850a40883 Mon Sep 17 00:00:00 2001 From: 3252a8 <3252a8@proton.me> Date: Fri, 15 May 2026 15:46:08 +0300 Subject: [PATCH] docs: update web app theme specific docs --- README.md | 5 +- docs/admin.md | 9 ++ docs/configuration.md | 12 +- docs/deployment.md | 6 +- docs/webapp-themes.md | 366 ++++++++++++++++++++++++++++++++++++++++++ docs/webapp.md | 10 +- 6 files changed, 391 insertions(+), 17 deletions(-) create mode 100644 docs/webapp-themes.md diff --git a/README.md b/README.md index a23d9c4..afe9b61 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Remnawave Minishop - Telegram-бот и Web App (Mini App) для продажи - [Тарифы](docs/tariffs.md) - каталог тарифов, period- и traffic-модели, обычные и premium-докупки, premium-сквады, смена тарифа, HWID-лимиты и обработка трафика. - [Админ-панель](docs/admin.md) - права доступа, настройки, редактор тарифов, premium-сквады и сохранение JSON-каталога. - [Web App / Mini App](docs/webapp.md) - отдельный порт, домен, Telegram OAuth, email-вход и реферальные ссылки. +- [Темы Web App](docs/webapp-themes.md) - кастомные темы, настройка внешнего вида, логотипы, CSS/ассеты и пайплайн создания новой темы. - [Развертывание](docs/deployment.md) - Docker Compose, reverse proxy, Nginx, Caddy, вебхуки, запуск из образа и обновление версии (`IMAGE_TAG`). - [Миграция с remnawave-tg-shop](docs/migration-to-minishop.md) - перенос данных из прежнего стека. @@ -82,10 +83,10 @@ docker compose logs -f remnawave-minishop Для каталога тарифов используется `TARIFFS_CONFIG_PATH` со значением по умолчанию `data/tariffs.json`. Пример формата лежит в [data/tariffs.example.json](data/tariffs.example.json), подробности - в [docs/tariffs.md](docs/tariffs.md). -Если в Docker Compose включаете bind mount `./data:/app/data`, заранее создайте каталог и отдайте его пользователю контейнера. Это нужно для сохранения `data/tariffs.json`, кеша логотипа Web App и animated emoji: +Если в Docker Compose включаете bind mount `./data:/app/data`, заранее создайте каталог и отдайте его пользователю контейнера. Это нужно для сохранения `data/tariffs.json`, каталога тем `data/themes`, кеша логотипа Web App и animated emoji: ```bash -mkdir -p data/webapp-logo data/webapp-emoji +mkdir -p data/themes data/webapp-logo data/webapp-emoji chown -R 10001:10001 data chmod -R u+rwX data ``` diff --git a/docs/admin.md b/docs/admin.md index 6e24843..9ccee4e 100644 --- a/docs/admin.md +++ b/docs/admin.md @@ -9,6 +9,7 @@ - блокировка пользователей, рассылки, промокоды и просмотр логов; - ручная синхронизация с Remnawave; - редактор разрешенных настроек приложения из manifest-файла; +- раздел **Внешний вид** для логотипа, emoji-логотипа, выбора темы, accent-цвета, масштаба логотипа и предпросмотра тем; - редактор JSON-каталога тарифов; - загрузка Internal Squads из Remnawave для выбора в тарифах. @@ -46,6 +47,14 @@ Секретные поля помечены как secret и не должны использоваться для произвольного просмотра старых значений. Настройки, которых нет в manifest, остаются только в `.env` или коде. +## Внешний вид + +Раздел **Внешний вид** объединяет настройки бренда и темы Web App. Логотип можно загрузить файлом или по HTTPS-ссылке; backend сохраняет файл в `data/webapp-logo/uploads` и подставляет локальный URL. Если включен emoji-логотип, картинка скрывается, а для emoji можно выбрать системный, Twemoji, Noto Color, animated Noto и другие варианты отрисовки. + +В блоке тем админка читает каталог из `WEBAPP_THEMES_DIR`, показывает встроенные и кастомные темы, позволяет выбрать текущую тему, изменить accent, включить или выключить тему для админки и настроить масштаб логотипа на главной и экране входа. Кнопка предпросмотра открывает `/home?theme_preview=` и не меняет глобальную тему до сохранения. + +Подробный формат `theme.json`, CSS/asset-роуты и пошаговый пайплайн создания новой темы описаны в [webapp-themes.md](webapp-themes.md). + ## Тарифы Раздел **Система -> Тарифы** работает с файлом `TARIFFS_CONFIG_PATH` (по умолчанию `data/tariffs.json`). При сохранении backend валидирует payload через `TariffsConfig`, пишет JSON в UTF-8 и сбрасывает кеш публичных данных Web App. diff --git a/docs/configuration.md b/docs/configuration.md index f4b2f41..9864358 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -96,10 +96,10 @@ nano .env Если файл из `TARIFFS_CONFIG_PATH` существует, бот использует каталог тарифов. Если файла нет, применяется конфигурация из переменных `.env`. -В штатном `docker-compose.yml` том `./data:/app/data` у сервиса приложения **закомментирован по умолчанию**. Раскомментируйте блок `volumes`, чтобы админка сохраняла `data/tariffs.json`, кеш логотипа Web App (`data/webapp-logo`) и animated emoji (`data/webapp-emoji`). Отдельный `docker-compose-dev.yml` в репозиторий не входит (может быть у вас локально); логика та же — монтирование `./data` в `/app/data`. Если bind mount включён на Ubuntu-сервере, создайте подкаталоги и отдайте `data` UID `10001`, под которым работает приложение внутри контейнера: +В штатном `docker-compose.yml` том `./data:/app/data` у сервиса приложения **закомментирован по умолчанию**. Раскомментируйте блок `volumes`, чтобы админка сохраняла `data/tariffs.json`, каталог тем (`data/themes`), кеш логотипа Web App (`data/webapp-logo`) и animated emoji (`data/webapp-emoji`). Отдельный `docker-compose-dev.yml` в репозиторий не входит (может быть у вас локально); логика та же — монтирование `./data` в `/app/data`. Если bind mount включён на Ubuntu-сервере, создайте подкаталоги и отдайте `data` UID `10001`, под которым работает приложение внутри контейнера: ```bash -mkdir -p data/webapp-logo data/webapp-emoji +mkdir -p data/themes data/webapp-logo data/webapp-emoji chown -R 10001:10001 data chmod -R u+rwX data ``` @@ -122,10 +122,8 @@ docker compose up -d --build --force-recreate | `WEBAPP_SERVER_HOST` / `WEBAPP_SERVER_PORT` | Хост и порт Web App. По умолчанию порт `8081`. | | `SUBSCRIPTION_MINI_APP_URL` | Публичный URL Web App. | | `WEBAPP_TITLE` | Заголовок Web App. | -| `WEBAPP_PRIMARY_COLOR` | Основной цвет интерфейса. | -| `WEBAPP_LOGO_URL` | URL логотипа Web App; если пусто — показывается emoji из `WEBAPP_LOGO_EMOJI`. | -| `WEBAPP_LOGO_EMOJI` | Emoji-заглушка вместо картинки логотипа. | -| `WEBAPP_LOGO_EMOJI_FONT` | Набор/шрифт для отрисовки emoji (например `system`, `twemoji`, `noto-color-animated`). | +| `WEBAPP_THEMES_DIR` | Каталог тем Web App. По умолчанию `data/themes`; внутри ожидаются папки `/theme.json` и опциональные CSS/ассеты. | +| `WEBAPP_DEFAULT_THEME` | Опциональный override темы по ключу, например `light` или `neon`. Если пусто, используется `default` из дескрипторов тем. | | `WEBAPP_SESSION_SECRET` | HMAC-секрет сессий Web App. | | `WEBHOOK_SECRET_TOKEN` | Секретный токен, с которым Telegram шлёт обновления на вебхук. | | `WEBAPP_SESSION_TTL_SECONDS` | Время жизни сессии Web App. | @@ -146,7 +144,7 @@ docker compose up -d --build --force-recreate | `BRUTE_FORCE_LOCK_SECONDS` | Длительность временной блокировки. | | `MY_DEVICES_SECTION_ENABLED` | Показывает раздел "Мои устройства" и включает API устройств. | -Настройка домена, BotFather и callback URL описана в [webapp.md](webapp.md). +Логотип, emoji-логотип, основной accent-цвет и тема редактируются в разделе **Админка -> Внешний вид** и сохраняются как overrides в базе. Переменные `WEBAPP_PRIMARY_COLOR`, `WEBAPP_LOGO_URL`, `WEBAPP_LOGO_USE_EMOJI`, `WEBAPP_LOGO_EMOJI` и `WEBAPP_LOGO_EMOJI_FONT` в `.env` считаются устаревшими для первичной настройки и игнорируются при загрузке env. Настройка домена, BotFather и callback URL описана в [webapp.md](webapp.md), а создание кастомных тем - в [webapp-themes.md](webapp-themes.md). ### SMTP и вход по email diff --git a/docs/deployment.md b/docs/deployment.md index a4292cb..e15dc52 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -26,7 +26,7 @@ IMAGE_TAG=3.1.0 docker compose -f docker-compose-remote-server.yml up -d Перед запуском или после добавления mount выполните на сервере из каталога проекта: ```bash -mkdir -p data/webapp-logo data/webapp-emoji +mkdir -p data/themes data/webapp-logo data/webapp-emoji chown -R 10001:10001 data chmod -R u+rwX data docker compose up -d --force-recreate remnawave-minishop @@ -35,10 +35,10 @@ docker compose up -d --force-recreate remnawave-minishop Проверка прав: ```bash -docker compose exec remnawave-minishop sh -lc 'id; ls -ldn /app/data /app/data/webapp-emoji; touch /app/data/webapp-emoji/test && rm /app/data/webapp-emoji/test' +docker compose exec remnawave-minishop sh -lc 'id; ls -ldn /app/data /app/data/themes /app/data/webapp-emoji; touch /app/data/themes/test /app/data/webapp-emoji/test && rm /app/data/themes/test /app/data/webapp-emoji/test' ``` -Если проверочный `touch` проходит без `Permission denied`, Web App сможет сохранять каталог тарифов, кеш `WEBAPP_LOGO_URL` в `/app/data/webapp-logo` и кеш animated emoji в `/app/data/webapp-emoji`. +Если проверочный `touch` проходит без `Permission denied`, Web App сможет сохранять каталог тарифов, темы в `/app/data/themes`, кеш логотипов в `/app/data/webapp-logo` и кеш animated emoji в `/app/data/webapp-emoji`. ## Обновление версии diff --git a/docs/webapp-themes.md b/docs/webapp-themes.md new file mode 100644 index 0000000..2df8e37 --- /dev/null +++ b/docs/webapp-themes.md @@ -0,0 +1,366 @@ +# Темы и внешний вид Web App + +Web App поддерживает файловые темы, предпросмотр и базовую настройку внешнего вида из админ-панели. Тема может быть простой цветовой схемой на JSON-токенах или полноценным скином с собственным CSS, шрифтами, иконками и графикой. + +## Что можно поменять + +Через раздел **Админка -> Внешний вид** можно: + +- выбрать глобальную тему Web App; +- изменить accent-цвет конкретной темы; +- включить или выключить применение темы в админ-панели; +- настроить масштаб логотипа на главной и экране входа; +- загрузить логотип файлом или по HTTPS-ссылке; +- включить emoji-логотип и выбрать способ его отрисовки; +- открыть предпросмотр темы через `/home?theme_preview=`. + +Через файлы темы можно менять намного больше: + +- базовые цвета Mini App и админки; +- радиусы, семейства шрифтов и размер главного логотипа; +- любые компоненты через CSS: карточки, навигацию, таблицы, модалки, кнопки, скелетоны, прогресс-бары, состояния hover/active и мобильную/desktop-верстку; +- иконки и изображения, если CSS ссылается на ассеты темы; +- стили только пользовательской части, только админки или обеих частей сразу. + +Готовые темы лежат в `bot/app/web/themes`: `dark`, `light`, `windows95`, `ascii`. При первом запуске они копируются в `WEBAPP_THEMES_DIR`, по умолчанию `data/themes`. + +## Где живут темы + +Каждая тема - отдельная папка: + +```text +data/themes/ + neon/ + theme.json + style.css + icons/ + save.png +``` + +Путь настраивается переменной: + +```env +WEBAPP_THEMES_DIR=data/themes +WEBAPP_DEFAULT_THEME= +``` + +`WEBAPP_DEFAULT_THEME` опционален. Если он задан и совпадает с ключом темы, он переопределяет `default: true` в `theme.json`. Если переменная пустая, дефолт выбирается из дескрипторов тем. + +Важно: `WEBAPP_PRIMARY_COLOR`, `WEBAPP_LOGO_URL`, `WEBAPP_LOGO_USE_EMOJI`, `WEBAPP_LOGO_EMOJI` и `WEBAPP_LOGO_EMOJI_FONT` больше не являются рабочим способом первичной настройки через `.env`. Эти значения редактируются в админке и сохраняются как overrides в базе. Тема при этом может использовать сохраненный primary color как fallback accent. + +## Контракт `theme.json` + +Минимальная тема: + +```json +{ + "key": "neon", + "names": { + "ru": "Неон", + "en": "Neon" + }, + "enabled": true, + "default": true, + "use_primary_accent": true, + "use_in_admin": true, + "tokens": { + "color_scheme": "dark", + "bg": "#05040a", + "panel": "#11101c", + "text": "#f8f7ff", + "muted": "#b8b2d8", + "accent": "#a855f7", + "radius": "14px" + } +} +``` + +Тема с CSS: + +```json +{ + "key": "neon", + "names": { + "ru": "Неон", + "en": "Neon" + }, + "enabled": true, + "default": false, + "use_primary_accent": false, + "use_in_admin": true, + "css_file": "style.css", + "assets_version": 1, + "tokens": { + "color_scheme": "dark", + "style_preset": "none", + "accent": "#a855f7", + "bg": "#05040a", + "panel": "#11101c", + "panel_2": "#090815", + "panel_3": "#1a1830", + "border": "rgba(168, 85, 247, 0.28)", + "border_strong": "rgba(168, 85, 247, 0.48)", + "text": "#f8f7ff", + "muted": "#b8b2d8", + "dim": "#756f9b", + "danger": "#ff6b8a", + "blue": "#38bdf8", + "radius": "14px", + "font_sans": "Inter, system-ui, sans-serif", + "font_logo": "Inter, system-ui, sans-serif", + "font_mono": "\"JetBrains Mono\", \"Fira Code\", monospace", + "home_logo_scale": 120, + "admin_bg": "#05040a", + "admin_surface": "#11101c", + "admin_surface_2": "#090815", + "admin_elev": "#1a1830", + "admin_border": "rgba(168, 85, 247, 0.28)", + "admin_border_strong": "rgba(168, 85, 247, 0.48)", + "admin_text": "#f8f7ff", + "admin_muted": "#b8b2d8", + "admin_dim": "#756f9b" + } +} +``` + +Поля верхнего уровня: + +| Поле | Назначение | +| --- | --- | +| `key` | Уникальный ключ темы, 1-64 символа: латиница, цифры, `_` и `-`. Если ключ не указан, берется имя папки. | +| `names` | Локализованные названия, например `ru` и `en`. | +| `enabled` | Показывать тему пользователям. Отключенная тема не попадает в публичный каталог. | +| `default` | Делает тему выбранной по умолчанию, если `WEBAPP_DEFAULT_THEME` не задан. | +| `use_primary_accent` | Если `true`, тема может получить accent из настройки внешнего вида, когда в `tokens.accent` ничего нет. | +| `use_in_admin` | Если `false`, пользовательская часть использует тему, но админка откатывается на `dark`. | +| `css_file` | CSS-файл внутри папки темы. Может быть `style.css` или вложенный путь вроде `css/theme.css`. | +| `assets_version` | Версия ассетов. Для встроенных тем используется для обновления старых файлов в `data/themes`. | +| `tokens` | Дизайн-токены, которые превращаются в CSS-переменные на `.app-shell`. | + +## Токены + +Поддерживаемые токены: + +| Токен | CSS-переменная | Что меняет | +| --- | --- | --- | +| `color_scheme` | `color-scheme` | Нативная светлая/темная схема браузера: `dark` или `light`. | +| `style_preset` | CSS-класс пресета | Сейчас `win95`/`windows95` добавляет `theme-preset-win95`; остальные значения не дают специального класса. | +| `accent` | `--accent` | Главный акцент: активные элементы, кнопки, прогресс, фокус. Только hex `#RGB` или `#RRGGBB`. | +| `bg` | `--bg` | Основной фон приложения. | +| `panel` | `--panel` | Основные карточки и поверхности. | +| `panel_2` | `--panel-2` | Вторичные поверхности. | +| `panel_3` | `--panel-3` | Поверхности повышенной вложенности, dropdown/popover. | +| `border` | `--border` | Обычные границы. | +| `border_strong` | `--border-strong` | Усиленные границы и hover-состояния. | +| `text` | `--text` | Основной текст. | +| `muted` | `--muted` | Вторичный текст. | +| `dim` | `--dim` | Еще более тихий текст и служебные подписи. | +| `danger` | `--danger` | Ошибки и опасные действия. | +| `blue` | `--blue` | Синий вспомогательный цвет. | +| `radius` | `--radius` | Базовый радиус карточек, кнопок и контролов. | +| `font_sans` | `--font-sans` | Основной шрифт интерфейса. | +| `font_logo` | `--font-logo` | Шрифт бренда и заголовка. | +| `font_mono` | `--font-mono` | Моноширинный шрифт. | +| `home_logo_scale` | `--home-logo-scale` | Масштаб логотипа на главной и входе, от `50` до `300` процентов. | +| `admin_bg` | `--admin-bg` | Фон админ-панели. | +| `admin_surface` | `--admin-surface` | Основные карточки админки. | +| `admin_surface_2` | `--admin-surface-2` | Вторичные поверхности админки. | +| `admin_elev` | `--admin-elev` | Elevated-поверхности админки. | +| `admin_border` | `--admin-border` | Границы админки. | +| `admin_border_strong` | `--admin-border-strong` | Усиленные границы админки. | +| `admin_text` | `--admin-text` | Основной текст админки. | +| `admin_muted` | `--admin-muted` | Вторичный текст админки. | +| `admin_dim` | `--admin-dim` | Тихие подписи админки. | + +Если `css_file` не задан, интерфейс полностью строится на токенах и общих стилях. Если `css_file` задан, токены все равно применяются первыми, а CSS темы может уточнить или полностью переопределить внешний вид. + +## CSS-слой темы + +CSS темы подключается как: + +```text +/webapp-theme-css// +``` + +Например `data/themes/neon/style.css` будет доступен как `/webapp-theme-css/neon/style.css`. + +Корневой контейнер получает классы: + +```text +app-shell theme-dark theme-key-neon theme-css-style +``` + +Для светлой схемы будет `theme-light`. Класс `theme-key-` - основной якорь для CSS темы. Всегда начинайте селекторы с него, чтобы тема не задевала другие режимы: + +```css +.theme-key-neon.app-shell { + --surface-sheen: rgba(168, 85, 247, 0.12); + --shadow-soft: 0 18px 48px rgba(12, 5, 30, 0.44); +} + +.theme-key-neon .card { + border-color: color-mix(in srgb, var(--accent) 34%, var(--border)); + background: + linear-gradient(135deg, rgba(168, 85, 247, 0.14), rgba(56, 189, 248, 0.05)), + var(--panel); +} + +.theme-key-neon .bottom-nav button.active, +.theme-key-neon .admin-nav-item.active { + box-shadow: 0 0 18px color-mix(in srgb, var(--accent) 24%, transparent); +} +``` + +CSS можно писать для пользовательской части и админки одновременно: + +```css +.theme-key-neon .period-card, +.theme-key-neon .method-card, +.theme-key-neon .option-row { + border-radius: 16px; +} + +.theme-key-neon .admin-card, +.theme-key-neon .admin-stat-card, +.theme-key-neon .admin-revenue-panel { + border-radius: 16px; +} +``` + +Ограничения: + +- CSS-файл должен быть внутри папки темы; +- размер CSS - до 512 KiB; +- путь не может содержать `..`; +- удаленные CSS, `data:` и protocol-relative URL в `css_file` не подключаются. + +## Ассеты темы + +Картинки темы кладутся рядом с `theme.json` и отдаются через: + +```text +/webapp-theme-assets// +``` + +Пример: + +```css +.theme-key-neon .btn-primary::before { + content: ""; + width: 16px; + height: 16px; + background: url("/webapp-theme-assets/neon/icons/spark.png") center / contain no-repeat; +} +``` + +Разрешены `png`, `jpg`, `jpeg`, `gif`, `webp`, `svg`, `ico`. Один asset - до 1 MiB. Для шрифтов лучше использовать внешние источники, уже разрешенные CSP (`fonts.googleapis.com`, `fonts.gstatic.com`, `cdn.jsdelivr.net`) или системные fallback-цепочки в `font_*` токенах. + +## Пайплайн создания новой темы + +1. Выберите ключ темы. + + Ключ должен быть стабильным: по нему сохраняется выбранная тема и строятся URL ассетов. Используйте короткий slug: `neon`, `brand_dark`, `terminal-blue`. Не переименовывайте ключ после публикации без миграции файлов и сохраненных настроек. + +2. Создайте папку в `WEBAPP_THEMES_DIR`. + + В Docker по умолчанию это `data/themes`. Если включен bind mount `./data:/app/data`, убедитесь, что контейнер может писать в `data`. + + ```bash + mkdir -p data/themes/neon + ``` + +3. Скопируйте ближайшую базовую тему. + + Для обычной брендовой темы чаще всего удобнее начать с `dark` или `light`. Для глубокого CSS-скина можно взять `ascii` или `windows95` как пример того, насколько далеко можно уйти от стандартного вида. + + ```bash + cp bot/app/web/themes/dark/theme.json data/themes/neon/theme.json + ``` + +4. Отредактируйте `theme.json`. + + Сначала поменяйте `key`, `names`, `default`, `use_primary_accent` и базовые токены. На этом этапе можно вообще не создавать CSS: приложение уже увидит тему как новый набор токенов. + +5. Запустите приложение и откройте админку. + + Раздел **Внешний вид** загружает `/api/admin/themes`, backend читает `WEBAPP_THEMES_DIR`, добавляет обязательные базовые темы и возвращает каталог. Нажмите **Обновить**, если папка была создана во время работы приложения. + +6. Проверьте тему через предпросмотр. + + В карточке темы нажмите **Предпросмотр** или откройте: + + ```text + https://app.domain.com/home?theme_preview=neon + ``` + + Предпросмотр не меняет глобальную тему и удобен для проверки CSS до публикации. + +7. Подберите accent и масштаб логотипа. + + В админке можно менять accent и `home_logo_scale` без ручного редактирования JSON. При сохранении backend перепишет `theme.json` в `WEBAPP_THEMES_DIR`, выставит ровно один `default` и сбросит кеш публичных настроек. + +8. Добавьте `style.css`, если токенов мало. + + Создайте файл, укажите его в `theme.json`: + + ```json + { + "css_file": "style.css" + } + ``` + + Начинайте с переопределения CSS-переменных на `.theme-key-neon.app-shell`, затем переходите к конкретным компонентам. Проверяйте минимум: главная, оплата, настройки, модалки, админский дашборд, таблица пользователей, редактор тарифов. + +9. Добавьте ассеты при необходимости. + + Положите картинки в подпапку темы и ссылайтесь на них через `/webapp-theme-assets//...`. Не используйте относительные пути вроде `url("icons/x.png")`, если CSS может быть подключен с другого URL-уровня; явный `/webapp-theme-assets/neon/icons/x.png` надежнее. + +10. Настройте поведение админки. + + Если тема сильно декоративная и мешает рабочей админке, выставьте `use_in_admin: false`. Пользователи увидят тему, а администраторы в разделе админки получат `dark` как fallback. + +11. Сделайте тему дефолтной. + + Есть два способа: + + - в админке выбрать тему и сохранить; + - указать `WEBAPP_DEFAULT_THEME=neon` в `.env`, если нужен жесткий override на уровне окружения. + +12. Зафиксируйте тему. + + Для темы, которая должна ехать вместе с проектом, добавьте ее в репозиторий в `bot/app/web/themes` и при необходимости расширьте `DEFAULT_THEME_KEYS` в `config/webapp_themes_config.py`. Для приватной инсталляции достаточно хранить ее в `data/themes`. + +## Насколько глубоко можно менять вид + +Уровни кастомизации: + +1. **Быстрый бренд** - токены `accent`, `bg`, `panel`, `text`, `radius`, логотип в админке. Код не нужен. +2. **Полная палитра** - все пользовательские и admin-токены, отдельные шрифты, масштаб логотипа. +3. **CSS-скин** - переопределение карточек, навигации, таблиц, модалок, progress/skeleton/toast, desktop/mobile раскладок. +4. **Почти новый UI** - тема вроде `windows95` или `ascii`: можно менять форму контролов, иконки, эффекты, таблицы и визуальный язык целиком, пока сохраняется DOM и интерактивные состояния. + +Не стоит менять через CSS смысловые состояния: скрывать ошибки, отключать фокус, перекрывать кнопки невидимыми слоями или делать `display: none` для обязательных действий оплаты и авторизации. Тема должна менять внешний вид, а не бизнес-логику. + +## Диагностика + +Если тема не появилась: + +- проверьте, что `theme.json` лежит ровно в `WEBAPP_THEMES_DIR//theme.json`; +- ключ состоит только из латиницы, цифр, `_` и `-`; +- JSON валиден; +- тема не отключена через `enabled: false`; +- в логах нет предупреждения `Ignoring theme descriptor`. + +Если CSS не применился: + +- проверьте `css_file` и URL `/webapp-theme-css//`; +- убедитесь, что файл меньше 512 KiB; +- начинайте селекторы с `.theme-key-`; +- откройте `/home?theme_preview=` в новом окне, чтобы исключить сохраненный старый выбор. + +Если ассеты не грузятся: + +- используйте путь `/webapp-theme-assets//`; +- проверьте расширение: `png`, `jpg`, `jpeg`, `gif`, `webp`, `svg`, `ico`; +- размер каждого файла должен быть до 1 MiB; +- путь не должен содержать пробелы, кириллицу или `..`. diff --git a/docs/webapp.md b/docs/webapp.md index b018d64..d0878f3 100644 --- a/docs/webapp.md +++ b/docs/webapp.md @@ -24,10 +24,8 @@ WEBAPP_SERVER_HOST=0.0.0.0 WEBAPP_SERVER_PORT=8081 SUBSCRIPTION_MINI_APP_URL=https://app.domain.com/ WEBAPP_TITLE="Моя подписка" -WEBAPP_PRIMARY_COLOR="#00fe7a" -WEBAPP_LOGO_URL= -WEBAPP_LOGO_EMOJI="🫥" -WEBAPP_LOGO_EMOJI_FONT=system +WEBAPP_THEMES_DIR=data/themes +WEBAPP_DEFAULT_THEME= WEBAPP_SESSION_SECRET= WEBHOOK_SECRET_TOKEN= WEBAPP_SESSION_TTL_SECONDS=86400 @@ -49,7 +47,9 @@ SMTP_FROM_EMAIL=no-reply@domain.com SMTP_FROM_NAME=Remnawave Minishop ``` -Если `WEBAPP_LOGO_URL` пустой, в шапке и на экране входа показывается запасной **emoji-логотип** (`WEBAPP_LOGO_EMOJI`) и при необходимости стиль отрисовки (`WEBAPP_LOGO_EMOJI_FONT`: например `system`, `noto-color`, `noto-color-animated`, `twemoji`). Если SMTP-настройки не заполнены, вход по email скрывается. +Внешний вид настраивается в админке: раздел **Внешний вид** управляет логотипом, emoji-логотипом, accent-цветом, выбранной темой и масштабом логотипа. Кастомные темы читаются из `WEBAPP_THEMES_DIR`, а `WEBAPP_DEFAULT_THEME` может принудительно выбрать тему по ключу. Подробный контракт `theme.json`, CSS/asset-роуты и пайплайн создания темы описаны в [webapp-themes.md](webapp-themes.md). + +Если SMTP-настройки не заполнены, вход по email скрывается. ## Telegram-авторизация