BOOK-LIBRARY: обзор и сценарии
BOOK-LIBRARY — каталог электронной библиотеки с публичной витриной, отдельной React-админкой и backend-слоем для файлов, очередей и переводов. Но точнее думать о ней не как о «папке с книгами в красивой оболочке», а как о системе, где у каждой книги есть путь: её находят или загружают, приводят карточку в порядок, раскладывают по дереву категорий, при необходимости переводят и только после проверки показывают читателю.
Проект не маскируется под книжную социальную сеть и не пытается заменить всё вокруг рекомендациями и лайками. Это рабочая библиотека: читатель открывает каталог и скачивает книгу через временную ссылку, администратор управляет данными, а долгие операции идут как задачи с понятным статусом. Главная идея статьи — показать, как из этих отдельных действий складывается аккуратный библиотечный процесс, а не просто список файлов.
Сценарий читателя
Публичная витрина собрана на SvelteKit. Для читателя вход в библиотеку начинается не с технических деталей, а с понятной навигации: дерева категорий, верхнего уровня, подкатегорий, breadcrumbs и счётчиков книг по веткам. Категории теперь не плоский список, поэтому каталог можно вести ближе к реальной библиотечной структуре: отделять крупные направления от более узких полок и помогать человеку быстрее понять, где он находится.
На странице категории читатель получает:
- название и путь до текущей категории;
- подкатегории, если они есть;
- список книг с обложкой, автором, описанием и форматом;
- постраничную загрузку книг внутри категории;
- кнопку скачивания через временный token;
- опубликованные переводы, если они есть у книги.
Пагинация важна для больших разделов: полка может расти, но читатель не должен ждать, пока интерфейс пытается вытащить всю ветку за один запрос. API возвращает limit, offset, hasMore и total, поэтому витрина спокойно догружает книги порциями. Для старых клиентов оставлен legacy-режим через format=legacy или all=1.
Скачивание не раскрывает постоянный путь к файлу. Публичная часть сначала запрашивает временную ссылку, backend создаёт token, а уже по нему отдаёт файл. Это не сложная DRM-схема, а нормальная гигиена для частного каталога: читателю достаточно нажать кнопку, а система сама держит файловую часть под контролем.
Сценарий администратора
Основная админка вынесена в отдельное React-приложение. Это важное разделение: публичная витрина остаётся спокойным читательским интерфейсом, а вся ежедневная работа с библиотекой уходит в операционный центр. Старая Svelte-admin часть удалена, чтобы эти роли не смешивались. В React-админке собраны dashboard, операции импорта, поиск, переводы, настройки, безопасность и управление LLM-провайдерами.
Администратор работает с несколькими зонами:
- dashboard для общего состояния библиотеки и операций;
- управление категориями и книгами;
- durable import queue для одиночных и пакетных загрузок;
- SearchPage для Anna’s Archive и Flibusta;
- раздел переводов с job-статусами, сегментами и артефактами;
- настройки провайдеров, пароля и security-параметров.
Авторизация держится на SQLite-backed sessions. Есть таблица admin_users, смена пароля и emergency override через окружение на случай, если доступ к админке нужно восстановить. State-changing admin API закрыты CSRF-защитой, а CORS разделён для public и admin origins. В результате админка выглядит не как временная панель «для своих», а как место, где можно безопасно разбирать реальные библиотечные задачи.
Сценарий внешнего поиска и импорта
Пополнение каталога здесь устроено ближе к рабочему процессу библиотекаря, чем к разовой загрузке файла. Не обязательно сначала скачивать книгу вручную, а потом переносить её в форму. В React-админке есть общий SearchPage, который объединяет Anna’s Archive и Flibusta. Администратор вводит запрос, сравнивает найденные варианты и запускает импорт выбранной книги.
Сам импорт оформлен как durable job. Это значит, что операция не пропадает только потому, что вкладка закрылась или HTTP-запрос оборвался. Backend сохраняет состояние задачи, обновляет прогресс, а интерфейс опрашивает его через polling. Для администратора это превращает импорт из нервного ожидания в наблюдаемую процедуру: видно, что происходит и где задача остановилась.
В этом сценарии особенно важны не только успешные результаты, но и спорные места:
- дубли нужно распознать и не размножить одну книгу в каталоге;
- категорию лучше сопоставить с уже существующим деревом, а не создавать случайные ветки;
- обложку стоит проверить перед заменой;
- ошибки внешнего источника должны быть видны как состояние задачи, а не как молчаливый сбой.
Поэтому импорт работает как операционная процедура, а не как кнопка «сделать всё само»: система помогает довести книгу до каталога, но оставляет контроль там, где автоматике нельзя слепо доверять.
Сценарий перевода книги
LLM-переводы вынесены в отдельный pipeline. Это осознанное решение: целую книгу нельзя нормально переводить одним prompt и сразу считать результат готовым. Нужны подготовка документа, нарезка на сегменты, выбор провайдера, повтор неудачных частей, проверка качества и сборка результата. Такой подход делает перевод частью библиотечного workflow, а не экспериментом, который живёт отдельно от каталога.
Типовой путь выглядит так:
- администратор выбирает книгу и запускает translation job;
- backend готовит canonical document;
- текст разбивается на сегменты;
- сегменты уходят в LLM batch translation с учётом priority и fallback провайдеров;
- система фиксирует QA findings;
- администратор проверяет спорные сегменты;
- результат собирается в EPUB/PDF artifacts;
- перевод публикуется или остаётся внутренним черновиком.
LLM providers хранятся в SQLite как runtime-сущности. Их можно настраивать из админки: включать, менять priority, использовать fallback. Это удобнее, чем держать один захардкоженный endpoint в коде, особенно когда перевод — не единичная демонстрация, а повторяемая операция с разными состояниями и результатами.
Сценарий публикации перевода
Публичная витрина показывает только опубликованные переводы. Если translation job собрал artifact, это ещё не значит, что он сразу виден читателю. Между технически готовым файлом и книгой на полке остаётся человеческое решение: администратор должен проверить результат и явно опубликовать его.
Такой шаг нужен по нескольким причинам:
- машинный перевод может ошибаться в терминах и именах;
- часть сегментов может требовать ручной правки;
- QA findings могут указывать на пропуски или подозрительные места;
- не каждый технически собранный файл стоит показывать в каталоге.
После публикации читатель видит доступные artifacts, обычно EPUB или PDF. Снятие с публикации тоже остаётся управляемым действием: файл может быть сохранён в системе, но исчезнуть из публичной витрины. Так библиотека не подменяет качество фактом генерации: видимым становится только то, что администратор готов показать.
Где здесь Quartz
Quartz-интеграция уже частично реализована, но она не меняет смысл BOOK-LIBRARY. Этот сайт может показывать curated-представление библиотеки, подборки и карточки, но не становится прямым зеркалом файлового хранилища. Иными словами, Quartz показывает выбранный срез, а не берёт на себя роль самой библиотечной системы.
Для этого в Quartz есть отдельная страница библиотеки, компонент витрины, generated catalog и mirrored covers. Скачивание при этом остаётся на стороне BOOK-LIBRARY через временные токены. Подробнее этот слой описан в отдельной заметке.
Что важно для портфолио
Для портфолио эта статья важна не списком технологий, а тем, что показывает связку пользовательских сценариев и технических ограничений:
- публичная витрина не перегружена админскими задачами;
- админка вынесена в React и стала операционным центром;
- долгие операции оформлены как устойчивые jobs;
- внешние источники подключены через понятный сценарий поиска и импорта;
- переводы отделены от обычного импорта книг;
- публикация перевода требует ручного решения;
- legacy EJS UI оставлен как простой запасной интерфейс.
Главная ценность проекта — в нормальном рабочем цикле вокруг книг. BOOK-LIBRARY не обещает автоматическую идеальность и не делает вид, что любой импорт или перевод сразу готов к публикации. Зато в системе есть места, где администратор может увидеть проблему, поправить данные и только потом показать результат читателю. Именно поэтому это не просто каталог файлов, а рабочая библиотечная система с понятными ролями, состояниями и точками контроля.