BOOK-LIBRARY: React-админка и операционный центр
React-админка в BOOK-LIBRARY появилась не ради смены стека и не как отдельная «панель ради панели». В раннем варианте админские экраны жили рядом с публичной SvelteKit-витриной, но со временем стало понятно: человек, который ведёт библиотеку, работает совсем в другом режиме, чем читатель. Читателю нужен каталог и понятный путь к книге. Администратору нужно видеть очереди, статусы, ошибки, внешний поиск, переводы, провайдеров и настройки безопасности.
Поэтому старая Svelte-admin часть удалена, а целевая админка вынесена в отдельное React-приложение. Публичная витрина остаётся спокойной страницей библиотеки, а React становится операционным центром — местом, где каталог не просто показывают, а поддерживают в рабочем состоянии.
Почему отдельная админка
У админки другой ритм работы. В ней нужно не просто нажать «добавить книгу», а понять, что происходит с системой прямо сейчас:
- какие задачи сейчас выполняются;
- какие импорты завершились ошибкой;
- где есть дубли или спорные категории;
- какие переводы ждут проверки;
- какой LLM-провайдер используется;
- всё ли в порядке с доступом и паролем.
Если смешивать это с публичной витриной, интерфейс быстро становится шумным: читателю начинают мешать служебные детали, а администратору — ограничения публичной страницы. Отдельная React-админка держит операционные сценарии в одном месте и не усложняет читательскую часть.
Dashboard и operations
Dashboard нужен как короткий обзор состояния библиотеки. Это не декоративная главная страница, а вход в работу: быстро понять, где всё спокойно, где импорт требует внимания, какие переводы идут дальше и какие настройки могут повлиять на следующие операции.
Operations-слой связан с durable jobs. Одиночный импорт, batch ZIP, Anna’s Archive, Flibusta и LLM-переводы не должны зависеть от одного длинного HTTP-запроса. Backend создаёт задачу, хранит её состояние, а админка показывает прогресс через polling.
Для администратора это меняет поведение интерфейса. Вместо ощущения, что форма зависла где-то между загрузкой файла и появлением карточки, он видит queued, running, failed, cancelled или completed. Если задача упала, можно разобрать причину и повторить отдельный этап, не превращая каждую ошибку в ручное расследование с нуля.
Durable import queue
Очередь импорта — один из главных операционных узлов. Через неё проходят:
- одиночные загрузки файлов;
- batch ZIP;
- импорт найденных книг из внешних источников;
- повтор неудачных операций;
- отчёты по skipped, failed и possible duplicates.
Такой подход особенно полезен при больших коллекциях. Импорт — это не одна функция, а цепочка решений: принять файл, извлечь метаданные, подобрать категорию, проверить дубль, найти обложку, сохранить карточку. Очередь делает эту цепочку видимой, а значит управляемой: понятно, на каком шаге книга застряла и что с ней делать дальше.
SearchPage: Anna’s Archive и Flibusta
Отдельная страница поиска объединяет Anna’s Archive и Flibusta. Это удобнее, чем держать два разрозненных сценария и каждый раз заново вспоминать, откуда брать нужное издание. Администратор вводит запрос, сравнивает найденные варианты и запускает импорт выбранной книги.
Внешний поиск не считается источником истины. У результата может быть неверное описание, не та обложка или несколько похожих изданий. Поэтому SearchPage важен не как кнопка «автоматически скачать всё», а как точка принятия решения: посмотреть candidates, выбрать подходящий вариант и запустить контролируемый import job.
Переводы в админке
LLM-переводы требуют отдельного интерфейса, потому что это уже не простое поле «перевести описание». Перевод книги — долгий pipeline: подготовка canonical document, segmentation, batch translation, QA findings, assembly, artifacts и publish/unpublish.
В админке нужно видеть:
- список translation jobs;
- текущий этап задачи;
- ошибки провайдера или сегмента;
- сегменты, которые требуют ручной проверки;
- QA findings;
- готовые EPUB/PDF artifacts;
- состояние публикации.
Публичная витрина показывает только published translations. Всё, что требует проверки, остаётся в админке, чтобы читатель видел аккуратный результат, а не внутреннюю кухню длинного процесса.
Settings, providers и security
LLM providers стали runtime-настройками в SQLite. Их можно включать, выключать, менять priority и использовать fallback. Это важно для переводов и метаданных: один provider может быть дорогим, нестабильным или временно недоступным, а работу библиотеки всё равно нужно продолжать без правки кода.
Security-настройки тоже вынесены ближе к администратору. В проекте есть SQLite-backed sessions, admin_users, смена пароля и emergency env override. State-changing admin API закрыты CSRF-защитой, а CORS разделён для публичных и admin origins.
Это не заменяет нормальную инфраструктурную дисциплину, но убирает раннюю прототипную слабость, когда админский доступ держится только на одном значении из окружения и плохо подходит для реального рабочего места.
Proxy и hosted admin bundle
Backend может обслуживать production-hosted bundle React-админки. Это удобно для операционной части: backend и админка выкатываются вместе, поэтому рабочий инструмент администратора остаётся рядом с API и задачами, которыми он управляет. Публичная SvelteKit-витрина при этом может разворачиваться отдельно, если она нужна как самостоятельная поверхность.
Такое разделение не мешает Quartz-интеграции. Quartz может показывать отобранный каталог, но не становится местом управления книгами. Все операции импорта, переводов, провайдеров и скачивания остаются в BOOK-LIBRARY.
Визуальный подход
React-админка использует shadcn/ui-подход и тёмную нейтральную палитру. Это подходит задаче: интерфейс должен быть спокойным, плотным и читаемым, без лишней декоративности. В админке важнее быстро понять состояние задачи, чем впечатлить анимацией.
Хорошая админка в таком проекте — это не «красивый dashboard ради dashboard». Это место, где видно, что было импортировано, что сломалось, что требует ручной проверки и что уже можно показать читателю. Именно поэтому React-часть здесь важна не сама по себе, а как рабочая поверхность для человека, который каждый день удерживает каталог в порядке.
Связанные заметки
- Архитектура — где React-админка находится среди backend, SvelteKit и legacy UI.
- Импорт и каталог — как durable jobs меняют импорт книг.
- LLM-переводы книг — почему перевод вынесен в отдельный pipeline.