Skip to content
QuadDarv1nePublic

About

Современное веб-приложение для чтения книг с поддержкой EPUB, FB2, PDF, TXT, Markdown и HTML. Локальное хранение в IndexedDB, аккаунты с синхронизацией прогресса между устройствами

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

 

History

104 Commits

Folders and files

Repository files navigation

Читалка — удобная читалка книг

Современное веб-приложение для чтения книг с поддержкой EPUB, FB2, PDF, TXT, Markdown и HTML. Локальное хранение в IndexedDB, аккаунты с синхронизацией прогресса между устройствами.

Возможности

Чтение книг

  • 📚 Форматы: EPUB, FB2, PDF, TXT, Markdown, HTML, MP3 (аудиокниги)
  • 🎨 4 темы: светлая, тёмная, сепия, контраст
  • 🔤 3 шрифта: с засечками, без засечек, моноширинный
  • 📏 Настройки: размер шрифта (12-28px), межстрочный интервал, поля, ширина текста, выравнивание, переносы
  • 📖 Пагинация: автоматическая с разрывом на главах
  • 🔄 Позиция: сохранение прогресса между сессиями
  • 🎚️ Перемотка по книге — клик/перетаскивание по прогресс-бару
  • 🖱️ Перелистывание колесом мыши — как на электронных книгах (TXT/MD/HTML)
  • 🔊 TTS: чтение вслух через Web Speech API (TXT/MD/HTML/EPUB)
  • 🔁 Автоперелистывание при озвучке — TTS сам переворачивает страницы и продолжает читать до конца книги
  • 🎧 Аудиоплеер: воспроизведение MP3-аудиокниг (включая .mp3.zip архивы), скорость, громкость, автопереход между главами
  • 📱 Media Session — управление аудиокнигой с наушников и экрана блокировки (play/pause, главы, перемотка ±10 с)
  • 😴 Таймер сна в аудиоплеере — остановка воспроизведения через 10–90 минут (время слушания не идёт в статистику, пока стоит пауза)
  • 📑 Оглавление аудиокниги — список глав из mp3.zip архива, быстрый переход к треку
  • ⌨️ Размер шрифта с клавиатуры: Ctrl/⌘ + = / Ctrl/⌘ + − / Ctrl/⌘ + 0 (сброс)

Библиотека

  • 💾 Локальное хранение в IndexedDB (файлы не покидают браузер)
  • 🖼️ Обложки автоматически извлекаются из EPUB/FB2/PDF
  • 🏷️ Цветные бейджи форматов
  • 🔍 Поиск по названию и автору
  • 🔀 Сортировка: недавние, по дате, по названию, по прогрессу, по оценке
  • 🎯 Фильтр по формату и статусу чтения (в процессе / завершённые)
  • ⚡ Drag & Drop загрузка файлов
  • 🔗 Добавление по ссылке — импорт книги по прямой URL (EPUB/PDF/FB2/TXT/MD/HTML/MP3)
  • 🎲 Случайная книга — кнопка открывает случайную непрочитанную книгу
  • 📚 "Продолжить чтение" — карусель недавних книг
  • ℹ️ Карточка книги — размер, дата добавления, статистика чтения, закладки/выделения, оценка (1–5 ★), сброс прогресса
  • 💾 Backup в JSON
  • 📁 Импорт из коллекции — загрузка книг из серверной папки books/

Аккаунты и синхронизация

  • 🔐 Регистрация с email и паролем
  • ✉️ Верификация email — токен действителен 7 дней
  • 🔑 Восстановление пароля по email
  • 🎟️ Управление сессиями — список всех устройств, завершение сессий
  • 🔒 Remember me — 30 дней или 1 год
  • ☁️ Синхронизация прогресса чтения между устройствами
  • ⚙️ Синхронизация настроек читалки
  • 📤 Экспорт данных аккаунта
  • 🗑️ Удаление аккаунта с подтверждением

Чтение и заметки

  • 📑 Оглавление: для EPUB из navigation.xml, для FB2/TXT — автоопределение "Глава N."
  • 🔖 Закладки с быстрым переходом
  • 🖍️ Выделения — 5 цветов с заметками
  • 🔍 Полнотекстовый поиск по книге (Ctrl+F)
  • 📊 Статистика чтения: время, страницы, streak
  • 🗓️ Тепловая карта года — активность чтения за последние 52 недели
  • 🎯 Цели дня с прогресс-баром

Безопасность

  • 🔐 bcrypt хеширование паролей (12 rounds)
  • 🎫 JWT сессии в httpOnly cookies
  • 🛡️ Rate limiting: login 10/15мин, register 5/час, forgot 5/час
  • 🚫 Email enumeration защита
  • 🔁 Одноразовые токены для reset/verify
  • 🍪 SameSite=lax, secure в production

Технологии

  • Frontend: Next.js 16 (App Router), React 19, TypeScript
  • UI: Tailwind CSS 4, shadcn/ui, Framer Motion
  • Backend: Next.js API Routes, Prisma ORM, SQLite
  • Auth: bcryptjs, jose (JWT)
  • Storage: IndexedDB (idb), localStorage (Zustand persist)
  • Чтение: epubjs, pdfjs-dist, собственный парсер FB2
  • Графики: Recharts
  • State: Zustand

Установка

# Установить зависимости
bun install

# Применить схему БД
bun run db:push

# Запуск в dev-режиме
bun run dev

# Сборка для production
bun run build
bun run start

Развертывание на Amvera Cloud

Проект готов к деплою на Amvera (amvera.yaml + Dockerfile, сборка через Docker, Next.js standalone). База данных SQLite хранится в постоянном хранилище /data, поэтому аккаунты и прогресс переживают пересборки.

  1. Создайте проект в Amvera и подключите этот репозиторий (GitHub) или запушьте его в https://git.amvera.ru/<user>/<project>.git.
  2. В разделе "Настройки" добавьте бесплатное доменное имя: https://<project>.<user>.amvera.io.
  3. В разделе "Переменные и секреты" задайте (оба обязательны — без них вход/регистрация будут отключены с ошибкой в логах):
    • JWT_SECRET — openssl rand -hex 32
    • NEXT_PUBLIC_APP_URL — https://<project>.<user>.amvera.io
  4. Запустите сборку. Приложение слушает порт 3000, на старте автоматически применяет схему Prisma (prisma db push) к file:/data/chitalka.db.
  5. Письма в production доставляются через Resend (HTTP API, без доп. зависимостей). Задайте RESEND_API_KEY и, при необходимости, RESEND_FROM. Без них письма не отправляются, но регистрация/сброс пароля продолжают работать (ошибка доставки логируется).

Переменные окружения

Создайте .env файл:

DATABASE_URL="file:./db/custom.db"
JWT_SECRET="your-32-char-secret-here-change-in-production"
NEXT_PUBLIC_APP_URL="http://localhost:3000"

В production JWT_SECRET и NEXT_PUBLIC_APP_URL строго обязательны (в src/lib/auth.ts и src/lib/url.ts фолбэков нет — работа с аккаунтами отключается, а не деградирует до небезопасного режима).

Email-сервис для production

В dev-режиме используется mock email-сервис (src/lib/email.ts), который логирует письма в консоль и временный файл. В production, если задан RESEND_API_KEY, письма отправляются через Resend HTTP API:

RESEND_API_KEY="re_..."
RESEND_FROM="Читалка <no-reply@yourdomain.com>"

Адрес отправителя должен быть подтверждён в аккаунте Resend. Если ключ не задан — доставка пропускается, а ошибка логируется (регистрация и сброс пароля при этом продолжают работать). Для другого провайдера замените sendViaResend() в src/lib/email.ts.

Структура проекта

src/
├── app/
│   ├── api/
│   │   ├── auth/           # Auth endpoints
│   │   │   ├── register/
│   │   │   ├── login/
│   │   │   ├── logout/
│   │   │   ├── me/
│   │   │   ├── forgot-password/
│   │   │   ├── reset-password/
│   │   │   ├── verify-email/
│   │   │   ├── resend-verification/
│   │   │   ├── update-profile/
│   │   │   ├── change-password/
│   │   │   ├── delete-account/
│   │   │   ├── sessions/
│   │   │   └── emails/      # Dev-only inbox
│   │   ├── books/sync/      # Book metadata sync
│   │   └── user/
│   │       ├── settings/    # User settings sync
│   │       └── export/      # Account data export
│   ├── layout.tsx
│   └── page.tsx
├── components/
│   ├── account/             # Account page
│   ├── auth/                # Auth dialogs, UserMenu
│   ├── library/             # Library page
│   ├── reader/              # Reader + panels
│   ├── stats/               # Stats page
│   └── ui/                  # shadcn/ui components
├── hooks/
│   ├── use-auth.tsx         # Auth context
│   ├── use-book-sync.ts     # Book progress sync
│   ├── use-reading-tracker.ts
│   └── use-tts.ts           # Text-to-speech
├── lib/
│   ├── auth.ts              # Password, JWT, sessions
│   ├── book-parser.ts       # EPUB/FB2/PDF parsers
│   ├── email.ts             # Mock email service
│   ├── export-utils.ts      # Markdown/JSON export
│   ├── highlights-utils.tsx # Highlight rendering
│   ├── library.ts           # IndexedDB storage
│   ├── rate-limit.ts        # Rate limiting
│   ├── session.ts           # Session helpers
│   └── db.ts                # Prisma client
└── store/
    └── reader-store.ts      # Zustand store

API Reference

Auth

  • POST /api/auth/register — регистрация
  • POST /api/auth/login — вход
  • POST /api/auth/logout — выход
  • GET /api/auth/me — текущий пользователь
  • POST /api/auth/forgot-password — запрос сброса пароля
  • POST /api/auth/reset-password — сброс пароля по токену
  • POST /api/auth/verify-email — подтверждение email
  • POST /api/auth/resend-verification — повторная отправка письма
  • PATCH /api/auth/update-profile — обновление профиля
  • POST /api/auth/change-password — смена пароля
  • POST /api/auth/delete-account — удаление аккаунта
  • GET /api/auth/sessions — список сессий
  • DELETE /api/auth/sessions?id=X — завершить сессию

Books

  • POST /api/books/sync — синхронизация метаданных
  • GET /api/books/sync — получение синхронизированных книг
  • GET /api/books/manifest — список файлов из коллекции (папка books/)
  • GET /api/books/download/[filename] — скачивание файла из коллекции

User

  • GET /api/user/settings — получить настройки
  • PUT /api/user/settings — обновить настройки
  • GET /api/user/export — экспорт данных аккаунта

Горячие клавиши

  • ← / → — перелистывание страниц
  • Home / End — в начало / в конец книги
  • Пробел / PgDn / PgUp / Backspace — перелистывание страниц
  • Ctrl/⌘ + F — поиск по книге
  • Ctrl/⌘ + B — закладки
  • Ctrl/⌘ + = / Ctrl/⌘ + − — размер шрифта
  • Ctrl/⌘ + 0 — сбросить размер шрифта
  • + / - — масштаб PDF
  • ? — справка
  • Esc — закрыть окно

Правовая защита (законодательство РФ)

Проект и его интеллектуальная собственность защищаются следующими нормативными актами Российской Федерации:

Авторские права и код

  • Гражданский кодекс РФ, часть четвёртая (гл. 69–70, ст. 1225–1301) — основной закон об интеллектуальной собственности. Программы для ЭВМ охраняются как литературные произведения (ст. 1261 ГК РФ), авторское право действует в течение всей жизни автора и 70 лет после его смерти (ст. 1281 ГК РФ). Правообладателю принадлежат исключительные права на использование программы любым способом (ст. 1270 ГК РФ).
  • Федеральный закон № 149-ФЗ "Об информации, информационных технологиях и о защите информации" — регулирует распространение информации, работу интернет-сервисов и обязанности операторов информационных систем.
  • Федеральный закон № 152-ФЗ "О персональных данных" — проект собирает и обрабатывает персональные данные пользователей (email, пароли в bcrypt-хешах, статистика чтения). Оператор обязан уведомить Роскомнадзор об обработке ПДн, получить согласие субъекта, обеспечивать защиту данных и предоставить право на их удаление и экспорт (реализовано в разделе "Аккаунт").
  • Федеральный закон № 38-ФЗ "О рекламе" — актуален при размещении рекламы в проекте.
  • Закон РФ № 2124-1 "О средствах массовой информации" — при необходимости регистрации проекта как СМИ (для массовой публикации контента).

Данные пользователей

  • 152-ФЗ "О персональных данных" — хранение, передача и удаление персональных данных пользователей.
  • 149-ФЗ "Об информации…" — обязанности по хранению и защите данных, в том числе локализация баз данных на территории РФ (ст. 18, ч. 5).
  • 124-ФЗ "Об электронной подписи" — при использовании электронных подписей (в проекте не используется, указано для полноты).

Ответственность за нарушение

Нарушение авторских прав влечёт гражданско-правовую (ст. 1252, 1301 ГК РФ), административную (ст. 7.12 КоАП РФ) и уголовную (ст. 146 УК РФ) ответственность. Несанкционированный доступ к данным — ст. 272 УК РФ, нарушение правил обработки персональных данных — ст. 13.11 КоАП РФ.

Проект распространяется по лицензии MIT. См. раздел "Лицензия".

About

Современное веб-приложение для чтения книг с поддержкой EPUB, FB2, PDF, TXT, Markdown и HTML. Локальное хранение в IndexedDB, аккаунты с синхронизацией прогресса между устройствами

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages