Клиентская работа · 2025–2026
NIGHTSHIFT
Газета работала на лоскутном стеке: сайты двух языковых редакций на Django, отдельные Flask-сервисы для новостей, авторизации и sitemap, админка на Nuxt 2, и всё это разворачивалось из разных каталогов на сервере. Я собрал систему в единый workspace на Python 3.12: FastAPI-сервисы на общей библиотеке, gRPC-контракт для авторизации, новая редакционная админка на Next.js и один деплой. Затем за одну ночь переключил обе редакции, подготовив образы для отката.
- Статус
- Перенесён в Python-монорепозиторий · сентябрь 2026
- Роль
- Full-stack разработчик
- Год
- 2025–2026
- Полный стек
- 17 инструментов
UI/UX-дизайн был создан моим коллегой-дизайнером. Эти кейсы рассказывают о моей инженерной работе и реализации, а не представляют визуальный дизайн как мою авторскую работу.
Полный стек
- Python 3.12
- uv workspace
- FastAPI
- SQLAlchemy 2.0 (async)
- PostgreSQL
- pg_trgm
- Redis
- gRPC
- Celery
- Jinja2
- Next.js 16
- React 19
- TypeScript
- TinyMCE
- Docker Compose
- nginx
- GitHub Actions
Что умеет сайт
- Серверный рендеринг двух языковых редакций одним сервисом на FastAPI и Jinja2: один образ, развёрнутый как два сайта, с кешированием страниц в Redis.
- Пять backend-сервисов в одном uv workspace: редакционный API, портал авторизации, gRPC API пользователей, воркер sitemap и RSS и публичный API. У них общая библиотека, а новые сервисы создаются из шаблона.
- Новая редакционная админка на Next.js вместо Nuxt 2. Она работает как backend-for-frontend и переключается между серверами двух редакций.
- Архив из десятков тысяч статей с поиском на триграммных индексах.
Что я сделал хорошо
- Доказал совместимость, а не предположил её. Контрактные тесты запускали старые Flask- и новые FastAPI-приложения рядом на копии production-базы и сравнивали каждый код ответа и JSON.
- Обошёлся без рискованной конвертации данных: новые сервисы работают с действующими таблицами, а изменения схемы минимальны. URL сохранены в точности, старые маршруты отдают 301.
- Переключил production за одну ночь. Сначала дампы баз и помеченные образы для отката, затем проверка нового стека на альтернативных портах, и только потом замена сервисов, со старыми контейнерами в резерве.
- За несколько дней исправил то, что выявил production: бюджет подключений к базе, переделанные блокировки статей для одновременной работы редакторов, усиление безопасности авторизации и внутренних сервисов, а поиск ускорил с ~6,5 секунды до 1–2.
Что я бы улучшил
- Заменить ручные SQL-скрипты для каждой базы миграциями Alembic.
- Перевести поиск на полнотекстовые индексы, чтобы ускорить запросы по частым словам, и снова включить кеширование публичного API.
- Расширить строгую проверку типов за пределы общей библиотеки, затем убрать образы отката и устаревшую документацию.
Виды проекта
Предыдущая версия
Кейс в том виде, в каком он был до пересборки, — сохранён как запись о том, с чего начинался проект.
2025 – Sep 2026
Flask → FastAPI, первый этап
Frontend / Full-stack разработчик
- Python
- Flask
- FastAPI
- Custom CMS
- HTML
- SCSS
- JavaScript
- Custom editorial infrastructure
Я перенёс кастомный Python-backend из Flask на FastAPI, чтобы он поддержал новый frontend, а затем интегрировал обновлённый интерфейс с существующей системой публикации, сохранив работоспособность старого production-окружения.
Какой была система
- Обновлённый редакционный frontend, подключённый к существующему кастомному publishing-backend.
- Новости, аналитика, мнения, категории, статьи, архив и подписка для издания с большим потоком материалов.
- Миграция backend с Flask на FastAPI вокруг работающей legacy-системы.
- Практично модернизировал backend, чтобы запустить новый frontend без полной замены publishing-системы.
- Сохранил работоспособность старого production-окружения во время изменения архитектурной границы приложения.
Что я тогда хотел исправить
- Очистить сервер от устаревших файлов и исправить либо заменить старые зависимости legacy-окружения.
- Документировать деплой и стандартизировать архитектуру приложения вокруг FastAPI.
- Продолжить изолировать современную реализацию от хрупкого legacy-кода.