Сайт культурного центра с магазином и пожертвованиями: каталог, корзина, оплата картой через Ameriabank vPOS и админка, в которой команда сама меняет тексты, товары и порядок блоков.
Клиенты
Сервер
Данные и внешние сервисы
Наведите на блок или нажмите на него: что он делает и с чем связан.
Культурному центру, который занимается музыкой с детьми с особыми потребностями, нужен был сайт, где можно купить его товары и поддержать программы пожертвованием. Два условия: оплата через армянский банк и команда без разработчика, которая сама ведёт весь контент на армянском и английском.
Проект состоит из трёх приложений: витрины на Next.js, API на NestJS с PostgreSQL и админки на React. Архитектуру фронтенда и бэкенда, REST API, бизнес-логику и выкладку на сервер я делал сам.
Покупатель выбирает товары в каталоге, складывает их в корзину и оформляет заказ без регистрации; у товара может быть вариант «в подарок» со своей ценой. Пожертвования оформляются на отдельной странице. Оплата проходит картой на защищённой странице Ameriabank, а подтверждение заказа, квитанция о пожертвовании и уведомление о возврате приходят на почту через Resend. Возвраты и отмены команда делает из админки, там же меняет товары, истории, FAQ, тексты страниц, порядок блоков, SEO-поля и медиатеку; длинные тексты редактируются в визуальном редакторе на Tiptap. На странице контактов — карта на Leaflet. Сайт ставится на телефон как PWA и показывает отдельную страницу, когда нет сети.
Платёжные данные не проходят через сайт: страница банка открывается в отдельном окне и после оплаты сообщает результат вкладке магазина через `postMessage` с проверкой источника. Возврат покупателя сам по себе ничего не доказывает — API запрашивает детали платежа у банка и только тогда помечает заказ оплаченным. Если покупатель закрыл окно раньше времени, фоновая задача каждые пять минут сверяет незавершённые платежи с банком и заодно замечает возвраты, сделанные прямо в банке. Сумму тоже считает сервер: цены, вариант «в подарок» и валюта берутся из базы, остаток проверяется при создании заказа и списывается один раз, когда заказ оплачен. Каждый шаг обмена с банком пишется в журнал, который виден в админке.
Правки из админки появляются на сайте сразу, без пересборки: витрина кеширует ответы API по тегам, а после сохранения API сбрасывает нужные теги через закрытый адрес. Армянский живёт на адресах без префикса, английский — под `/en`; если редактор заполнил только один язык, текст копируется во второй, а canonical, hreflang и sitemap строятся для обоих. Service worker написан вручную, без Workbox.
Всё работает на одном Linux-сервере без контейнеров: PostgreSQL, Nginx и PM2 для API и Next.js, админка — статическая сборка. Обновление — по описанной инструкции: сборка на сервере и перезапуск через PM2, а изменения схемы базы идут только через миграции, которые API применяет при старте. Секреты хранятся только на сервере.
Проект завершён: витрина, API и админка работают вместе, команда центра сама ведёт контент на двух языках, а оплата, возвраты и пожертвования проходят через Ameriabank vPOS.
