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, а не экспериментом, который живёт отдельно от каталога.

Типовой путь выглядит так:

  1. администратор выбирает книгу и запускает translation job;
  2. backend готовит canonical document;
  3. текст разбивается на сегменты;
  4. сегменты уходят в LLM batch translation с учётом priority и fallback провайдеров;
  5. система фиксирует QA findings;
  6. администратор проверяет спорные сегменты;
  7. результат собирается в EPUB/PDF artifacts;
  8. перевод публикуется или остаётся внутренним черновиком.

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 не обещает автоматическую идеальность и не делает вид, что любой импорт или перевод сразу готов к публикации. Зато в системе есть места, где администратор может увидеть проблему, поправить данные и только потом показать результат читателю. Именно поэтому это не просто каталог файлов, а рабочая библиотечная система с понятными ролями, состояниями и точками контроля.