NEVERMORE

От схемы базы до пикселя

Full-stack разработчик. Бэкенд на Python и FastAPI, фронтенд без лишних слоёв.

AniWorld
Голубика Давидика
Breaking Bad
DotaCounters
AniWorld
Голубика Давидика
Breaking Bad
DotaCounters

Что я построил

AniWorld
Продукт в проде2026

AniWorld

Библиотека аниме и манги с личными коллекциями, оценками и профилями.

Метаданные из Shikimori, видео из Kodik, манга сразу из трёх читалок за общим контрактом провайдера. Серверный рендеринг вместо SPA, потому что трафик такому сайту даёт поиск. 900 тестов, 43 миграции, прод на VPS в ЕС.

  • FastAPI
  • SQLAlchemy 2.0
  • MySQL
  • Alembic
  • Jinja2
  • nginx
Голубика Давидика
Коммерческий заказ2026

Голубика Давидика

Лендинг фермерского хозяйства: заявка уходит владельцу в Telegram за секунду.

Ноль фреймворков на фронте, минифицированные css и js, разметка под поиск: sitemap, robots, манифест. Форма заказа бьёт в Express, тот отдаёт заявку боту. Развёрнуто на Vercel.

  • Express
  • Vanilla JS
  • Telegram Bot API
  • Vercel
Breaking Bad
Работа с формой2026

Breaking Bad

Лонгрид по сериалу: персонажи, сезоны, галерея, локации, две языковые версии.

Здесь меня интересовала только подача. Палитра собрана из кадров, заголовки на Bebas Neue, вёрстка держит длинный текст и не разваливается на середине. Переключатель EN и RU работает без перезагрузки.

DotaCounters
Десктоп2026

DotaCounters

Портативная утилита для Dota 2: против кого герой играет слабо, а против кого сильно.

Тянет свежую статистику матчапов с Dotabuff и рисует её в одном окне с иконками героев. Патч определяется сам при запуске. Один exe, без установки и без браузера.

  • Python
  • Tkinter
  • PyInstaller

Как я это делаю

Сначала контракт

Источники прячутся за интерфейсом

У манги в AniWorld три поставщика с разными API и разной пагинацией. Слой синхронизации не знает ни одного из них: он видит только нормализованный ответ. Добавить четвёртый значит написать один класс, а не править половину проекта.

services/manga/base.py
class MangaProvider(ABC):    name: str                      # ключ в конфиге: "mangadex"    can_read: bool = True          # можем ли забрать страницы глав    page_hosts: tuple[str, ...] = ()     @abstractmethod    async def fetch_catalog(self, client, *, limit, offset,                            language) -> list[MangaRaw]: ...

Рендер по задаче

SPA не всегда правильный ответ

AniWorld живёт поиском, поэтому страницы тайтлов отдаёт сервер на Jinja2, а динамика идёт отдельными запросами к тому же FastAPI. Индексируемо из коробки, быстрый первый экран, никакого сборщика.

api/pages.py
@router.get("/", response_class=HTMLResponse)async def home_page(request: Request,                    db: AsyncSession = Depends(get_db)):    featured = await pick_featured(db)    return templates.TemplateResponse(        "home.html", {"request": request, "featured": featured},    )

Версии под контролем

Зависимости закреплены по разбору CVE

В requirements рядом с версиями лежат причины: какой разбор формы читается до проверки входа, какая дыра закрыта в каком релизе. Обновление пакета это решение, а не автоматика.

requirements.txt
# Разбор формы идёт до проверки входа: так устроен FastAPI,# тело читается раньше зависимостей маршрута.python-multipart==0.0.32Pillow==12.3.0 argon2-cffi==25.1.0PyJWT==2.13.0

Коротко о себе

Залеский Кирилл

Началось со школы: мне было интересно всё, что связано с компьютерами, и со временем это сузилось до серверной логики. Люблю продумать, как ходят данные, а потом открыть сайт и сразу увидеть результат. Python выбрал за простой синтаксис и за то, что почти под любую задачу уже есть библиотека.

AniWorld делаю для себя. Самым тяжёлым оказалась не архитектура, а отладка: найти, почему источник отдаёт не то, починить и не бросить проект на этом месте. По-моему, это и есть главный навык, который у меня появился.

Сейчас учусь и хочу практики: одинаково рад заказу, стажировке и работе в команде.

NEVERMORE это старое имя Shadow Fiend из Dota 2, одного из моих любимых персонажей.

900
тестов в AniWorld
43
миграции базы
4
проекта в проде
3
источника за одним контрактом

Чем работаю

Напишите мне

Открыт к работе и к заказам. Отвечаю в течение дня.