9.7 KiB
Бизнес-требования: Портал приложений (apps.mva154.duckdns.org)
1. Проблема
Сейчас веб-приложения разбросаны по разным адресам:
• openclaw.mva154.duckdns.org/noisemap/
• openclaw.mva154.duckdns.org/snowbike-rag/
• и т.д.
Нет единой точки входа. При добавлении нового приложения нужно править конфиг nginx.
2. Что хотим получить
Страницу-портал по адресу apps.mva154.duckdns.org, на которой отображаются кнопки/карточки наших приложений. Нажал — перешёл на нужное приложение.
Главное требование: добавление нового приложения — это только добавление строки в конфиг-файл приложения, без правки nginx.
3. Функциональные требования
3.1 Главная страница
• Адрес: apps.mva154.duckdns.org
• Сетка карточек приложений (grid, 2–4 колонки на десктопе, 1 колонка на мобильном)
• Каждая карточка:
- Иконка (emoji или SVG)
- Название приложения
- Краткое описание (1 строка)
- Клик → переход на приложение
3.2 Карточки приложений
• Приложения загружаются из JSON-конфига (не из кода)
• Новые приложения добавляются в конфиг — портал обновляется автоматически
• Порядок: из конфига (поле order)
• Активные/неактивные: поле enabled: true/false — скрыть если false
3.3 Навигация
• Клик по карточке → переход на URL приложения
• Открывается в той же вкладке (или в новой — настройка в конфиге)
• URL приложений — относительные пути на openclaw.mva154.duckdns.org
4. Архитектура
4.1 Схема
apps.mva154.duckdns.org
│
▼
Nginx (location /)
│
▼
Flask (порт 5560) ← читает config.json
│
▼
HTML (карточки приложений)
│
▼
Клик → переход на openclaw.mva154.duckdns.org/{путь}
4.2 Конфиг приложений
Файл: config/apps.json
[
{
"id": "noisemap",
"name": "Карта шума",
"description": "Карта шумового загрязнения от авиации",
"icon": "🛩️",
"url": "https://openclaw.mva154.duckdns.org/noisemap/",
"enabled": true,
"order": 1
},
{
"id": "snowbike-rag",
"name": "Snowbike Поиск",
"description": "Семантический поиск по базе знаний сноубайков",
"icon": "🏔️",
"url": "https://openclaw.mva154.duckdns.org/snowbike-rag/",
"enabled": true,
"order": 2
}
]
Поля:
• id — уникальный ID (используется для имени файла аватарки)
• name — название
• description — описание
• icon — emoji для аватарки (используется при генерации)
• url — ссылка на приложение
• enabled — показывать на портале
• order — порядок сортировки
• avatar — (опционально) путь к кастомной аватарке; если отсутствует — генерируется автоматически
4.3 Добавление нового приложения
- Добавить строку в
config/apps.json - При первом запуске Flask автоматически сгенерирует аватарку в
static/avatars/{id}.png - Готово — портал показывает новое приложение
НЕ нужно: • Править nginx • Перезапускать Flask (конфиг перечитывается при старте) • Создавать аватарку вручную
5. Требования к дизайну
5.1 Стиль
• Светлая тема (по мотивам snowbike-rag, но светлее) • Фон: #F8FAFC (светло-серый) • Карточки: белые (#FFFFFF), скруглённые углы (16px), лёгкая тень • Шрифт: Inter • Акцентный цвет: #3B82F6 (синий) • Текст: #0F172A (тёмный)
5.2 Карточка приложения
┌────────────────────────┐
│ │
│ ┌──────────┐ │
│ │ аватарка │ │
│ │ 80×80 │ │
│ └──────────┘ │
│ │
│ Название приложения │
│ Краткое описание │
│ │
└────────────────────────┘
• Аватарка: квадратная, скруглённая (12px), 80×80px, по центру карточки • Название: жирный шрифт, 18px, тёмный • Описание: обычный шрифт, 14px, серый (#64748B) • Hover: подсветка рамки синим, lift-эффект (тень), масштаб 1.02 • Аватарка — первое что бросается в глаза
5.3 Аватарки приложений
Автоматическая генерация при добавлении нового приложения:
При добавлении строки в config/apps.json Flask автоматически генерирует аватарку, если файл не существует.
Способ генерации:
• Градиентный фон (по хэшу названия приложения → уникальный цвет)
• По центру — первая буква названия или emoji иконка (крупно, белым цветом)
• Сохраняется в static/avatars/{app_id}.png
• Генерация: Python PIL/Pillow (без внешних API)
• Размер: 200×200px (масштабируется в CSS)
Примеры:
🛩️ на синем градиенте → «Карта шума»
🏔️ на зелёном градиенте → «Snowbike Поиск»
🔍 на оранжевом градиенте → «Портал поиска»
Правила:
• Если в конфиге указано поле avatar — используется указанное изображение
• Если avatar отсутствует — генерируется автоматически
• Цвет градиента определяется по хэшу name (детерминированно — всегда одинаковый для одного названия)
• Формат: PNG, 200×200px
5.4 Заголовок
• Название портала: «Мои приложения» • Подзаголовок: «N активных приложений» • Светлый фон, тёмный текст
5.5 Адаптивность
• Десктоп: 3–4 колонки • Планшет: 2 колонки • Мобильный: 1 колонка
6. Технические требования
6.1 Стек
• Flask (порт 5560) • HTML + CSS + JS (один файл, inline) • Tailwind CSS через CDN • Google Fonts (Inter) через CDN
6.2 Nginx
• Домен apps.mva154.duckdns.org → location / → proxy_pass http://172.19.0.2:5560/
• Один location block, без правок при добавлении приложений
• SSL через Certbot (как у основного домена)
6.3 Flask
• GET / — главная страница (рендерит HTML из конфига)
• GET /api/apps — JSON-список приложений (для отладки)
• Конфиг: config/apps.json
7. Что НЕ входит
• Авторизация • Админка для добавления приложений (через JSON-файл) • Мониторинг статуса приложений (online/offline) • Уведомления о новых приложениях
8. Критерии приёмки
✅ Открывается apps.mva154.duckdns.org — видно карточки приложений
✅ Клик по карточке — переход на нужное приложение
✅ Добавил строку в apps.json — портал показывает новое приложение с аватаркой
✅ Аватарка генерируется автоматически (градиент + emoji)
✅ НЕ нужно править nginx для нового приложения
✅ Хорошо выглядит на телефоне
✅ Светлая тема, похожая на snowbike-rag
9. Приоритет
Сейчас: Главная страница + карточки + автогенерация аватарок Позже: Анимации, кастомные аватарки, мониторинг статуса