Современное веб-приложение для чтения книг с поддержкой 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 (amvera.yaml + Dockerfile,
сборка через Docker, Next.js standalone). База данных SQLite хранится в постоянном
хранилище /data, поэтому аккаунты и прогресс переживают пересборки.
- Создайте проект в Amvera и подключите этот репозиторий (GitHub) или запушьте
его в
https://git.amvera.ru/<user>/<project>.git. - В разделе "Настройки" добавьте бесплатное доменное имя:
https://<project>.<user>.amvera.io. - В разделе "Переменные и секреты" задайте (оба обязательны — без них
вход/регистрация будут отключены с ошибкой в логах):
JWT_SECRET—openssl rand -hex 32NEXT_PUBLIC_APP_URL—https://<project>.<user>.amvera.io
- Запустите сборку. Приложение слушает порт 3000, на старте автоматически
применяет схему Prisma (
prisma db push) кfile:/data/chitalka.db. - Письма в 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 фолбэков нет — работа с аккаунтами
отключается, а не деградирует до небезопасного режима).
В 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
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— подтверждение emailPOST /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— завершить сессию
POST /api/books/sync— синхронизация метаданныхGET /api/books/sync— получение синхронизированных книгGET /api/books/manifest— список файлов из коллекции (папкаbooks/)GET /api/books/download/[filename]— скачивание файла из коллекции
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. См. раздел "Лицензия".