diff --git a/README.en.md b/README.en.md
new file mode 100644
index 0000000..4359291
--- /dev/null
+++ b/README.en.md
@@ -0,0 +1,121 @@
+# Tablo
+
+[Русский](README.md) · **English**
+
+[](https://github.com/EDeev/tablo/actions/workflows/ci.yml)
+[](https://github.com/EDeev/tablo/actions/workflows/docker.yml)
+[](https://github.com/EDeev/tablo/releases)
+
+A web app for students: upload a photo of your timetable, and AI turns it into an editable schedule
+with per-subject progress trackers you can share by link.
+
+**Status:** coursework project (2026), completed · live at [tablo.deev.su](https://tablo.deev.su)
+
+
+
+**Stack:** Python 3.12 · Flask · SQLAlchemy + Alembic · PostgreSQL · OpenAI-compatible Vision API · Playwright · Jinja2 + vanilla JS
+
+## Features
+
+- Timetable recognition from a photo or scan
+- Editing of schedules, subjects and classes; periods may span New Year
+- 11 tracker types (attendance, grades, deadlines, day streaks, etc.) on a drag-and-drop grid
+- Tracker generation from a description such as "8 labs and an exam"
+- Link sharing: view, edit, or copy as a template
+- Merging several schedules into one, with classes of the same subject combined
+- Export to JSON, CSV, PNG and a print-ready version
+
+## Quick start
+
+```bash
+git clone https://github.com/EDeev/tablo.git && cd tablo
+cp .env.example .env # set SECRET_KEY and your AI provider key
+docker compose up -d
+```
+
+Open `http://localhost:8000`. Compose starts the app and PostgreSQL; migrations run on startup.
+Prebuilt image: `docker pull ghcr.io/edeev/tablo` or `docker pull dcr.deev.su/edeev/tablo`.
+
+## Installing without Docker
+
+Requires Python 3.11+ and PostgreSQL.
+
+```bash
+python -m venv .venv && source .venv/bin/activate
+pip install -r requirements.txt
+playwright install --with-deps chromium # for PNG export
+cp .env.example .env
+flask --app run db upgrade
+python run.py
+```
+
+## Configuration
+
+| Variable | Purpose |
+|---|---|
+| `SECRET_KEY` | Flask session signing; the app will not start without it |
+| `DATABASE_URL` or `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD` | PostgreSQL connection |
+| `OPENAI_API_KEY` | AI provider key |
+| `OPENAI_BASE_URL` | OpenAI-compatible API URL, if not OpenAI |
+| `OPENAI_MODEL` | model for recognition and trackers, `gpt-4o` by default |
+
+> [!IMPORTANT]
+> Without `OPENAI_API_KEY`, timetable recognition and tracker generation are disabled. Everything else
+> works: you can create and edit a schedule manually.
+
+## Screenshots
+
+| My schedules | Subject and trackers | Phone |
+|---|---|---|
+|  |  |  |
+
+## How it works
+
+```mermaid
+flowchart LR
+ B[Browser] --> F[Flask: auth · schedules · subjects · shares · export]
+ F --> S[Services: ai_scan · ai_metrics · merge · export]
+ F --> P[(PostgreSQL)]
+ S --> A[OpenAI-compatible API]
+ S --> C[Chromium via Playwright]
+```
+
+Details (in Russian):
+
+- [docs/architecture.md](docs/architecture.md) — structure, schedule format, trackers, access rules
+- [docs/deploy.md](docs/deploy.md) — Docker and the production setup
+- [docs/explanatory_note.pdf](docs/explanatory_note.pdf) — coursework explanatory note
+
+## Deployment
+
+[tablo.deev.su](https://tablo.deev.su) runs on a VPS: gunicorn under systemd behind nginx with a
+Let's Encrypt certificate; PostgreSQL runs on a separate server; AI is Timeweb Cloud AI. GitHub Actions
+builds the Docker image on every `v*` tag and publishes it to GitHub Packages and to `dcr.deev.su`.
+
+## Development
+
+```bash
+pip install -r requirements-dev.txt
+export TEST_DATABASE_URL=postgresql://tablo:tablo@localhost:5432/tablo_test
+ruff check . && pytest
+```
+
+Tests run against a real PostgreSQL: access rules and export, share links, sign-in and open-redirect
+protection, period and time parsing, schedule merging. CI starts the database as a service container
+and runs the same checks on every push.
+
+## License
+
+Coursework project (Moscow Polytechnic University, 2025/26). The code is open for study; there is no
+separate license.
+
+## Author
+
+**Egor Deev** — [GitHub](https://github.com/EDeev) · [Telegram](https://t.me/DeevEgor) · [egor@deev.space](mailto:egor@deev.space)
+
+---
+
+
+
⭐ If you find this project useful, give it a star on GitHub!
+
Made with ❤️ — deev.space
+
diff --git a/README.md b/README.md
index e2fbd69..e581947 100644
--- a/README.md
+++ b/README.md
@@ -1,77 +1,121 @@
# Tablo
-Веб-приложение для работы с учебным расписанием: распознавание расписания из изображения с помощью ИИ, персональные трекеры успеваемости и совместный доступ по ссылке.
+**Русский** · [English](README.en.md)
-Сайт: [tablo.deev.su](https://tablo.deev.su)
+[](https://github.com/EDeev/tablo/actions/workflows/ci.yml)
+[](https://github.com/EDeev/tablo/actions/workflows/docker.yml)
+[](https://github.com/EDeev/tablo/releases)
-## Функциональность
+Веб-приложение для студентов: по фото расписания ИИ собирает редактируемое расписание, к каждому
+предмету можно добавить трекеры успеваемости и поделиться всем по ссылке.
-- Загрузка фотографии или скана расписания и автоматическое извлечение структурированных данных через AI Vision API
-- Полный CRUD для расписаний, предметов и слотов занятий
-- 11 типов виджетов трекеров успеваемости (посещаемость, оценки, дедлайны, серии дней и др.)
-- Дашборд с перетаскиваемыми виджетами на сетке 12 колонок
-- Совместный доступ по токен-ссылке с тремя режимами: просмотр, редактирование, клонирование как шаблон
-- Объединение нескольких расписаний с разрешением конфликтов по предметам
+**Статус:** учебный проект (курсовая работа, 2026), завершён · работает на [tablo.deev.su](https://tablo.deev.su)
-## Технологический стек
+
-- **Backend:** Python, Flask, SQLAlchemy, Flask-Migrate, Flask-Login
-- **База данных:** PostgreSQL (JSONB для хранения структуры расписания)
-- **ИИ:** Gemini 3.1 Flash через OpenAI-совместимый API (Timeweb Cloud AI)
-- **Frontend:** Jinja2, Bootstrap 5.3, Vanilla JS, Fetch API
+**Стек:** Python 3.12 · Flask · SQLAlchemy + Alembic · PostgreSQL · OpenAI-совместимый Vision API · Playwright · Jinja2 + vanilla JS
-## Установка
+## Возможности
-**Требования:** Python 3.11+, PostgreSQL
+- Распознавание расписания по фото или скану
+- Редактирование расписаний, предметов и занятий, периоды с переходом через Новый год
+- 11 видов трекеров (посещаемость, оценки, дедлайны, серии дней и др.) на сетке с перетаскиванием
+- Генерация трекера по описанию: «8 лабораторных и экзамен»
+- Доступ по ссылке: просмотр, редактирование или копия как шаблон
+- Объединение нескольких расписаний в одно: занятия одного предмета сводятся вместе
+- Экспорт в JSON, CSV, PNG и версию для печати
+
+## Быстрый старт
```bash
-git clone https://github.com/EDeev/tablo.git
-cd tablo
-python -m venv venv
-venv\Scripts\activate # Windows
-# source venv/bin/activate # Linux/macOS
-pip install -r requirements.txt
+git clone https://github.com/EDeev/tablo.git && cd tablo
+cp .env.example .env # задайте SECRET_KEY и ключ ИИ-провайдера
+docker compose up -d
```
-Заполните файл `.env` в корне проекта
+Откройте `http://localhost:8000`. Compose поднимает приложение и PostgreSQL, миграции применяются
+при старте. Готовый образ: `docker pull ghcr.io/edeev/tablo` или `docker pull dcr.deev.su/edeev/tablo`.
-Примените миграции и запустите приложение:
+## Установка без Docker
+
+Нужны Python 3.11+ и PostgreSQL.
```bash
-flask db upgrade
+python -m venv .venv && source .venv/bin/activate
+pip install -r requirements.txt
+playwright install --with-deps chromium # для экспорта в PNG
+cp .env.example .env
+flask --app run db upgrade
python run.py
```
-Приложение будет доступно по адресу `http://localhost:5000`.
+## Конфигурация
-## Структура проекта
+| Переменная | Назначение |
+|---|---|
+| `SECRET_KEY` | подпись сессий Flask; без неё приложение не запустится |
+| `DATABASE_URL` или `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD` | подключение к PostgreSQL |
+| `OPENAI_API_KEY` | ключ ИИ-провайдера |
+| `OPENAI_BASE_URL` | адрес OpenAI-совместимого API, если это не OpenAI |
+| `OPENAI_MODEL` | модель для распознавания и трекеров, по умолчанию `gpt-4o` |
+> [!IMPORTANT]
+> Без `OPENAI_API_KEY` не работают распознавание расписаний и генерация трекеров. Всё остальное работает:
+> расписание можно завести и править вручную.
+
+## Как выглядит
+
+| Мои расписания | Предмет и трекеры | Телефон |
+|---|---|---|
+|  |  |  |
+
+## Как устроено
+
+```mermaid
+flowchart LR
+ B[Браузер] --> F[Flask: auth · schedules · subjects · shares · export]
+ F --> S[Сервисы: ai_scan · ai_metrics · merge · export]
+ F --> P[(PostgreSQL)]
+ S --> A[OpenAI-совместимый API]
+ S --> C[Chromium через Playwright]
```
-tablo/
-├── app/
-│ ├── models/ # Модели SQLAlchemy
-│ ├── routes/ # Блюпринты (auth, schedules, subjects, shares)
-│ ├── services/ # Бизнес-логика (AI-распознавание, AI-генерация метрик)
-│ └── templates/ # HTML-шаблоны Jinja2
-├── migrations/ # Файлы миграций Flask-Migrate
-├── requirements.txt
-└── run.py
+
+Подробности:
+
+- [docs/architecture.md](docs/architecture.md) — структура, формат расписания, трекеры, права доступа
+- [docs/deploy.md](docs/deploy.md) — Docker и устройство боевого сервера
+- [docs/explanatory_note.pdf](docs/explanatory_note.pdf) — пояснительная записка к курсовой
+
+## Развёртывание
+
+[tablo.deev.su](https://tablo.deev.su) работает на VPS: gunicorn под systemd за nginx с сертификатом
+Let's Encrypt, PostgreSQL — на отдельном сервере, ИИ — Timeweb Cloud AI. Docker-образ собирает GitHub
+Actions на каждый тег `v*` и публикует в GitHub Packages и в реестр `dcr.deev.su`.
+
+## Разработка
+
+```bash
+pip install -r requirements-dev.txt
+export TEST_DATABASE_URL=postgresql://tablo:tablo@localhost:5432/tablo_test
+ruff check . && pytest
```
+Тесты идут на настоящем PostgreSQL: права доступа и экспорт, ссылки, вход и защита от открытого
+редиректа, разбор периодов и времени, слияние расписаний. CI поднимает базу в сервис-контейнере и
+выполняет то же самое на каждый push.
+
## Лицензия
-Этот проект является некоммерческим и распространяется под лицензией MIT.
+Учебный проект (курсовая работа, Московский Политех, 2025/26). Код открыт для изучения, отдельной
+лицензии нет.
## Автор
-**Деев Егор Викторович** - Backend Developer
-- GitHub: [@EDeev](https://github.com/EDeev)
-- Email: egor@deev.space
-- Telegram: [@Egor_Deev](https://t.me/Egor_Deev)
+**Деев Егор Викторович** — [GitHub](https://github.com/EDeev) · [Telegram](https://t.me/DeevEgor) · [egor@deev.space](mailto:egor@deev.space)
---
-
⭐ Если проект оказался полезным, поставьте звездочку на GitHub!
-
Создано с ❤️ от вашего дорогого - deev.space ©
+
⭐ Если проект оказался полезным, поставьте звёздочку на GitHub!
+
Сделано с ❤️ — deev.space
diff --git a/docs/architecture.md b/docs/architecture.md
new file mode 100644
index 0000000..402eaac
--- /dev/null
+++ b/docs/architecture.md
@@ -0,0 +1,63 @@
+# Как устроен Tablo
+
+Flask-приложение с фабрикой `create_app`, блюпринтами и сервисным слоем. База — PostgreSQL
+(структура расписания хранится в JSON-поле), миграции — Flask-Migrate (Alembic).
+
+```
+app/
+ __init__.py фабрика приложения, расширения (SQLAlchemy, Migrate, Login, CSRF)
+ config.py настройки из окружения
+ access.py права: владелец или редактор по ссылке
+ models/ User, Schedule, SubjectConfig, Metric, Share, ShareEditor
+ routes/ auth, schedules, subjects, shares, export
+ services/
+ ai_scan.py распознавание расписания по фото (vision-модель)
+ ai_metrics.py генерация трекера по текстовому запросу
+ merge.py слияние нескольких расписаний
+ schedule_helpers.py разбор периодов, сборка дня и недели
+ export.py PNG и версия для печати через Playwright/Chromium
+ templates/, static/
+migrations/ ревизии Alembic
+tests/ pytest на PostgreSQL
+```
+
+## Формат расписания
+
+`Schedule.data` — список предметов. У предмета — типы занятий (лекция, практика…), у типа — цвет и
+периоды, в периоде — слоты `[день, время, аудитория, преподаватель]`:
+
+```json
+[
+ {
+ "subject": "Базы данных",
+ "types": {
+ "Лекция": {"color": "blue", "dates": {"01.09-31.12": [["понедельник", "09:00-10:30", "АВ-301", "Смирнова Е.А."]]}}
+ }
+ }
+]
+```
+
+Период `ДД.ММ-ДД.ММ` может переходить через Новый год (`01.09-03.01`), «Весь период» — без
+ограничений. Время сортируется как число, поэтому `9:00` и `09:00` равнозначны.
+
+## Распознавание и трекеры
+
+`ai_scan.py` отправляет фото и подробный системный промпт в OpenAI-совместимый API и разбирает
+ответ в JSON указанного формата. `ai_metrics.py` по запросу вида «8 лабораторных и экзамен» подбирает
+тип трекера и его настройки. Ошибки провайдера пишутся в лог, пользователь видит общее сообщение.
+
+Типы трекеров: контрольные точки, накопление баллов, счётчик, этапы, чеклист, посещаемость, оценки
+с весами, дедлайны, серия дней, трудозатраты, история оценок. Трекеры лежат на сетке из 12 колонок,
+положение и размер сохраняются.
+
+## Доступ
+
+| Кто | Что может |
+|---|---|
+| владелец | всё, включая экспорт и удаление |
+| редактор (добавлен в ссылку на редактирование) | просматривать и править по id, экспортировать |
+| любой со ссылкой на просмотр `/shared/` | только смотреть, без входа |
+| вошедший пользователь со ссылкой-шаблоном | получить копию расписания себе |
+
+Проверка прав — одна функция `app/access.py`. Формы защищены CSRF (Flask-WTF), пароли хранятся
+в виде хешей Werkzeug, переход после входа (`?next=`) — только внутри сайта.
diff --git a/docs/deploy.md b/docs/deploy.md
new file mode 100644
index 0000000..26f8741
--- /dev/null
+++ b/docs/deploy.md
@@ -0,0 +1,25 @@
+# Развёртывание
+
+## Docker
+
+```bash
+cp .env.example .env # SECRET_KEY и ключ ИИ-провайдера
+docker compose up -d
+```
+
+Поднимаются приложение и PostgreSQL 16 (данные — в томе `pgdata`), миграции применяются при старте.
+Готовый образ собирается GitHub Actions на каждый тег `v*`:
+
+```bash
+docker pull ghcr.io/edeev/tablo:latest
+docker pull dcr.deev.su/edeev/tablo:latest
+```
+
+Образ большой (около 1,3 ГБ): в нём Chromium для экспорта расписания в PNG.
+
+## Как работает tablo.deev.su
+
+- gunicorn (2 воркера) под systemd за nginx с сертификатом Let's Encrypt;
+- PostgreSQL — на отдельном сервере, подключение через `DB_*`;
+- ИИ — Timeweb Cloud AI (OpenAI-совместимый endpoint), модель задаётся `OPENAI_MODEL`;
+- обновление: выложить код, `pip install -r requirements.txt`, `flask db upgrade`, перезапуск юнита.
diff --git a/explanatory_note.pdf b/docs/explanatory_note.pdf
similarity index 100%
rename from explanatory_note.pdf
rename to docs/explanatory_note.pdf
diff --git a/docs/screenshots/mobile.png b/docs/screenshots/mobile.png
new file mode 100644
index 0000000..e1bc442
Binary files /dev/null and b/docs/screenshots/mobile.png differ
diff --git a/docs/screenshots/profile.png b/docs/screenshots/profile.png
new file mode 100644
index 0000000..34f9b79
Binary files /dev/null and b/docs/screenshots/profile.png differ
diff --git a/docs/screenshots/schedule.png b/docs/screenshots/schedule.png
new file mode 100644
index 0000000..c92a979
Binary files /dev/null and b/docs/screenshots/schedule.png differ
diff --git a/docs/screenshots/subjects.png b/docs/screenshots/subjects.png
new file mode 100644
index 0000000..0abd305
Binary files /dev/null and b/docs/screenshots/subjects.png differ