Калькуляторы + 3D
калькуляторы в проде3D — прототипОдна система расчёта для более чем сотни моделей изделий; прототип на three.js перестраивает 3D-модель при смене параметров.
B2B-каталог мебели под заказ: покупатель настраивает изделие в калькуляторе, сразу видит цену, собирает корзину и оформляет заказ без регистрации.


Старый сайт на MODX не давал менять ассортимент, цены и параметры калькуляторов без программиста, а для заказа покупателю приходилось писать менеджеру. Нужен был каталог, где цена считается на лету, заказ оформляется без регистрации, а контент, фото и параметры меняются в админке — и всё это должен был сделать один человек.
Сделал за ~1,5 года: монорепозиторий из 9 сервисов — фронт на Next.js и 8 сервисов на Python, включая CMS на Wagtail. Весь стек работает в docker compose на одном сервере, мониторинг — на отдельном. Публикация страницы в админке сама сбрасывает кеш сайта; товары уходят фидами в Яндекс Товары и Яндекс Бизнес; на сайте работает чат с ИИ-консультантом, а контент-бот правит карточки через MCP.
Ещё: 93 деплоя в прод с медианой 39 с · 536 правил 301 при переезде · 1 381 коммит · 127 HTTP-эндпоинтов · 19 MCP-инструментов.
Изделие — класс, параметры объявлены аннотациями типов. Декоратор кладёт класс в реестр, при старте каждый получает две ручки — расчёт и превью, — а модель запроса и OpenAPI генерируются из аннотаций. Настройки живут в CMS и проецируются в Redis; URL класса совпадает с URL страницы товара, поэтому калькулятор находится без таблицы соответствий. Ответ у всех калькуляторов один, и корзина собирает позицию одинаково для любого изделия. Цену с фронта корзина не принимает.
Ответы кешируются дважды — в Redis у gateway и в ISR Next.js. CMS после коммита транзакции публикует событие в RabbitMQ; воркер gateway переводит событие в ключи и идёт строго по порядку: Redis, затем сброс ISR, затем прогрев страницы. Гонку закрывает счётчик поколения: пересборка, увидевшая после записи другое значение, удаляет свой результат. События идемпотентны, страховка — TTL и кнопка «Очистить кеш» в админке.
MCP-сервер работает без серверных сессий, с OAuth 2.1, поэтому запрос может обработать любой воркер. Запись в CMS повторяется, только если запрос точно не ушёл; «прочитать → изменить → опубликовать» идёт в одной транзакции под блокировкой строки с повторной проверкой. В страницу с черновиком редактора запись не идёт — бот получает 409. Правка применяется целиком или никак, HTML проходит белый список тегов.
19 MCP-инструментов: 9 на чтение, 10 на запись

У старого сайта были сотни адресов в выдаче с другой структурой URL. Карта 301 в nginx — 536 точных правил, разделы без замены отвечают 410. На фронте 404 приходит с настоящим статусом: notFound() вызывается до первой границы стриминга. Сам переезд — перевод staging-сервера в production с сохранением данных.