Files
jellybit/openspec/changes/archive/2026-06-30-web-ui-design-port/proposal.md
T
avandClaude Opus 4.8 4e2593ac31 Перенос дизайна в server-rendered веб-UI (web-ui)
Новая capability web-ui: презентационный перенос готового дизайна
(семантический HTML + единый jellybit.css, тёмная тема по настройке ОС)
в html/template без шага сборки.

- Встроенная (go:embed) отдача статики под /static с Cache-Control и
  cache-busting (?v=<hash> по содержимому css/js).
- Шрифты IBM Plex self-hosted (@font-face, cyrillic+latin), без CDN.
- Наколеночный менеджер зависимостей: вендор (htmx + шрифты) не хранится
  в репо (gitignore), идемпотентно добывается `task assets` по
  web/assets.manifest с проверкой sha256; task build/run зависят от assets.
- Общие партиалы: шапка, бейдж статуса (карта всех 14 состояний),
  виджет «файл источника → раскладка» (общий для review и download).
- Страницы: список с фильтром/поиском, ревью, новая страница просмотра
  загрузки (/download/{id}). deleted скрыт по умолчанию.
- Превью раскладки берётся из единой логики internal/layout
  (buildFileRows), без дублирования правил имён в шаблонах.
- Убраны meta-refresh и инлайн-стили; copyHash на vanilla с fallback
  на execCommand и честной индикацией (целевой деплой — HTTP LAN).

Вне scope (отдельный change): живые обновления прогресса и раздел
раздачи, клиентский режим ручной раскладки файл→серия (с Alpine.js).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 19:59:19 +03:00

5.4 KiB

Why

Текущий веб-UI — черновой: инлайн <style>, хардкод цветов, грубый <meta http-equiv="refresh" content="5"> для «живости». Готов полноценный дизайн (tmp/design/) — семантический HTML + один CSS-файл, заточенный ровно под нашу архитектуру (server-rendered Go, без сборки/npm/React). Пора перенести его в прод, чтобы «единое окно» стало пригодным для ежедневного использования.

Это презентационный change: поведение ядра (приём, распознавание, раскладка, петля ревью) не меняется — оформляем уже существующие действия и состояния.

What Changes

  • Отдача статики: роут /static/* через http.FileServer над web.FS, go:embed для web/static/{css,js,fonts,vendor}, разумные Cache-Control.
  • Шрифты self-hosted: IBM Plex Sans + IBM Plex Mono кладём локально и подключаем через @font-face (без Google Fonts CDN — не зависим от внешней сети, не светим referrer).
  • Дизайн-система: jellybit.css (токены, тёмная тема по настройке ОС) как единственный CSS; новые цвета не вводим — только из токенов.
  • Зависимости фронта: вендорные ассеты (htmx + шрифты) не храним в репоweb/static/vendor/ в gitignore. task assets идемпотентно добывает их по манифесту (имя/версия/URL/sha256): нет файла или хеш не сошёлся — качает, иначе берёт с диска. Без Node и бандлера. Авторские css/js — обычный коммит.
  • Общие партиалы: шапка .app-header, бейдж статуса (карта state→class), виджет «файл источника → раскладка» (общий для review и download).
  • Шаблоны: переносим index и review, добавляем download (просмотр одной загрузки). Референсные states.html/directions.html в прод не идут.
  • Убираем meta-refresh и инлайн-стили; до отдельного change живых обновлений список остаётся статичным (без авто-обновления прогресса).
  • Клиентский JS по минимуму: copyHash (vanilla), спойлер контекста (нативный <details>). Реактивных виджетов нет — все действия идут через формы/htmx.
  • Превью путей на экране ревью отображается из серверного расчёта (internal/layout), без дублирования правил в шаблоне.
  • Формы: проставить name полей, совпадающие с Go-структурами обработчиков.

Capabilities

New Capabilities

  • web-ui: презентационный слой веб-интерфейса — встроенная отдача статики и шрифтов, единая дизайн-система, рендеринг страниц (список/ревью/просмотр), бейджи статусов и клиентские взаимодействия без сборки (копирование infohash, спойлер, режим ручной раскладки с live-превью).

Modified Capabilities

Impact

  • Код: internal/httpapi (роут статики, новые/обновлённые хендлеры рендера, партиалы), web/web.go (go:embed статики), новые web/static/** и web/templates/{index,review,download}.html. Превью зовёт internal/naming.
  • Зависимости: вендор (htmx + шрифты) добывается task assets по манифесту с checksum, не npm/не Go-модуль; Node не вводим. web/static/vendor/ в gitignore. go:embed требует ассеты на сборке, поэтому task build/task run зависят от task assets (идемпотентного) — бинарь остаётся самодостаточным, но голый go build без фетча неполноценен (осознанный размен).
  • Поведение: без изменений в API/ядре. Вне scope: живые обновления прогресса (отдельный change web-live-updates) и клиентский режим ручной раскладки файл→серия (отложен до реальной необходимости — операция редкая).