👔

Интернет-магазин рубашек на Nuxt 4 с админкой для владельца

магазин рубашек в Чебоксарах: владелец сам ведёт товары, цены и заказы

Интернет-магазин школьных и повседневных рубашек в Чебоксарах на Nuxt 4 и FastAPI: каталог с цветами и остатками по размерам, корзина, оптовые цены, панель управления и заказы в Telegram.

В продакшенеNDA
2 раздела
детские и подростковые рубашки, у каждого своя таблица размеров
webp
фото с телефона сервер сам поворачивает, уменьшает и конвертирует
15 минут
блокировка входа в панель после 5 неверных паролей подряд
Интернет-магазин школьных рубашек на Nuxt от DevUnit Lab: главная страница на телефоне
Интернет-магазин школьных рубашек на Nuxt от DevUnit Lab: главная страница на телефоне

Задача

Магазин школьных и повседневных рубашек в Чебоксарах продавал «по звонку и переписке» и доставлял по городу и районам Чувашии. Заказчику нужен был полноценный интернет-магазин, который владелец ведёт сам: добавляет товары и фотографии, меняет цены, видит заказы, не обращаясь к разработчику и не разбираясь в технической части.

Условия:

  • сайт находится в поиске по запросам вида «купить школьные рубашки Чебоксары»;
  • покупатель выбирает размер и цвет, а не гадает по переписке;
  • оптовые покупки считаются автоматически;
  • о новом заказе владелец узнаёт сразу, в мессенджере.

Решение

Витрина на Nuxt 4 и API на FastAPI с MySQL 8 плюс панель управления для владельца. Панель управления — закрытый раздел сайта, где владелец правит товары, цены, фотографии, тексты и смотрит заказы.

Что реализовано:

  • Каталог с разделами «детские» и «подростковые», карточка товара с вариантами расцветки, размерной сеткой и несколькими фотографиями.
  • Таблицы размеров для детей и подростков, схема обмера рубашки с подписями и пояснением.
  • Корзина: добавление, изменение количества, удаление, сумма. Состав хранится в браузере и переживает перезагрузку страницы.
  • Оформление заказа на несколько товаров сразу, цены считает сервер.
  • Опт: количество и скидка задаются в панели, участие товара отмечается в его карточке.
  • Панель управления: товары, цены, фотографии, метки «хит» и «новинка», снятие с витрины, список заказов со сменой состояния.
  • Раздел «Содержимое сайта»: контакты и реквизиты, график выездной торговли, рассказ о магазине, условия опта, три довода на главной, частые вопросы, тексты страниц.
  • Светлая и тёмная темы с переключателем, своя страница 404.
  • Бот заявок на доступ к уведомлениям о заказах: новый человек пишет боту, владелец одобряет заявку кнопкой в переписке.

Как это устроено

Серверный рендер Nuxt для поиска «купить школьные рубашки»

Серверный рендер (SSR) — страница собирается на сервере и отдаётся готовым HTML, а не пустой оболочкой, которую наполняет JavaScript. Поэтому поисковый робот видит товары сразу. Для поиска сделано следующее: у каждой страницы свои заголовок и описание, микроразметка Product с ценой, наличием и фотографиями, разметка ClothingStore с координатами точки самовывоза, канонический адрес, robots.txt с закрытой панелью и карта сайта, которая собирается на лету из видимых страниц и товаров.

Остатки по размерам и цветам в карточке товара

У товара есть список цветов, у каждого цвета собственный список размеров с остатком. На странице товара покупатель выбирает цвет кружком-образцом и размер из тех, что есть в наличии. Выбор попадает в корзину, в заказ, в панель управления и в уведомление в Telegram. Размер без остатка на витрине не показывается.

Фото с телефона: поворот по метке камеры и webp

Владелец загружает обычный снимок с телефона. Телефон записывает поворот кадра в метку камеры, а не поворачивает сами пиксели, и без учёта метки фото ложится боком. Сервер читает метку, поворачивает кадр, уменьшает его и переводит в webp — современный формат изображений, который весит заметно меньше JPEG.

Цены считает сервер, а не браузер

Состав корзины хранится в браузере, а браузер покупатель может править как угодно. Поэтому при оформлении заказа сервер пересчитывает цены и итог по данным из базы. Он же применяет оптовую цену.

Оповещения о заказах в Telegram и бот заявок на доступ

Заказ дублируется в чат владельца в Telegram. Доступ к уведомлениям для других людей выдаётся ботом: человек пишет боту, заявка уходит владельцу, тот одобряет или отклоняет её кнопкой в переписке. Одобренные добавляются к получателям без правки настроек на сервере. Оповещения во ВКонтакте написаны, но не включены: не хватает токена сообщества.

Защита панели управления

Пароли хранятся хэшами, вход даёт сессию. Блокировка на 15 минут после 5 неверных паролей действует для логина независимо от адреса, с которого подбирают пароль: общий лимит запросов на nginx по IP не спасает от перебора с разных адресов. Панель доступна на отдельном поддомене со своей кукой сессии, которая не пересекается с витриной. Все маршруты записи в API проверяют вход.

Выкладка одним контейнерным стеком

Магазин работает в четырёх контейнерах Docker: база, кэш, API и витрина. Схема базы накатывается миграциями Alembic автоматически при старте API. Наружу сайт публикует общий входной nginx на сервере сайтов студии, сертификат выпускается через Let's Encrypt.

Результат

  • Владелец добавляет товары, меняет цены, остатки и тексты сам, без обращения к разработчику.
  • Покупатель выбирает цвет и размер, а заказ приходит владельцу в Telegram с выбранными позициями.
  • Оптовая цена включается автоматически, цены не зависят от того, что лежит в браузере.
  • Страницы отдаются готовым HTML, у каждой свой заголовок и описание, у товара есть микроразметка.
  • Загрузка фото с телефона не требует обработки на стороне владельца.
  • Замеров скорости и автотестов в репозитории нет, поэтому оценок не приводим.

Технологии: что и зачем

  • Nuxt 4, Vue 3, Tailwind CSS 4 — витрина и панель управления с серверным рендером и светлой и тёмной темами.
  • FastAPI и SQLAlchemy 2 (асинхронный) — REST API каталога, заказов и настроек сайта.
  • Alembic — миграции схемы базы, шесть ревизий на момент документа, применяются при старте.
  • MySQL 8 — товары, варианты, остатки, заказы, настройки сайта.
  • Redis 7 — кэш и сессии.
  • Docker Compose — база, кэш, API и витрина одним стеком; Python 3.13 и Node 24 внутри образов.
  • nginx и Let's Encrypt — публикация витрины и панели через общий входной контейнер сервера сайтов.
  • Telegram-бот — уведомления о заказах и заявки на доступ к ним.

Статус

Версия 1.17.1 от 26 сентября 2026 года, магазин работает на боевом сервере. Индексация поисковиками закрыта на время доработок. Перед продвижением нужно снять запрет, подключить Яндекс.Метрику и подтвердить сайт в вебмастерах, для чего нужны коды подтверждения от заказчика. Оплата пока только при получении, приём платежей на сайте не подключён: обсуждается QR СБП или Яндекс-платежи. Числа в размерной сетке нуждаются в сверке с владельцем. Автотестов и описания резервного копирования в репозитории нет. Другие детали заказчика не раскрываются.

Вопросы по проекту

Как перейти от продаж по звонкам и переписке к интернет-магазину?
Нужен магазин, который владелец ведёт сам. Здесь в панели управления он добавляет товары и фотографии, меняет цены, отмечает «хит» и «новинку», снимает товар с витрины и видит заказы со звонком покупателю в один клик. Разработчик для этого не нужен.
Как загрузить фото товара с телефона, чтобы оно не лежало боком?
Загружается обычный снимок с телефона. Сервер сам поворачивает кадр по метке камеры, уменьшает его и переводит в формат webp, поэтому страницы остаются лёгкими.
Как вести остатки по размерам и цветам?
В карточке товара заводится список цветов, у каждого цвета свои размеры с остатком на складе. Размер без остатка пропадает с витрины, как и цвет без размеров. Покупатель выбирает цвет и размер на странице товара, а выбор попадает в корзину, заказ и уведомление владельцу.
Как работают оптовые цены в интернет-магазине?
В панели управления задаются количество, с которого включается опт, и размер скидки, а у каждого товара отмечается участие в опте. Корзина показывает, сколько штук не хватает до оптовой цены. Итог считает сервер по данным из базы, а не браузер.
Как интернет-магазин попадает в поиск по запросу «купить школьные рубашки в Чебоксарах»?
Витрина рендерится на сервере, поэтому поисковые роботы получают готовый HTML с товарами. У каждой страницы свои заголовок и описание, на товаре стоит разметка Product с ценой и наличием, карта сайта собирается автоматически. Сейчас индексация закрыта на время доработок и включается перед продвижением.
Как защищена панель управления магазином?
Запись в API возможна только после входа. После 5 неверных паролей подряд для одного логина вход блокируется на 15 минут, при любом из двух адресов панели. Панель открывается на отдельном поддомене со своей кукой сессии, а время ответа на вход не выдаёт, существует ли логин.

Ещё по этому направлению

Нужно похожее?

Расскажите о задаче — покажем, как решали такое, и прикинем объём работ.