Greenfield-разработка платежей и ваучеров для круизного оператора
Услуги
- complex-systems
- legacy-modernization
Стек
- SvelteKit 2
- Svelte 5
- Supabase Postgres
- Hatchet
- Gotenberg
- PDFKit
- Tailwind 4
- shadcn-svelte
Крупный оператор речных круизов — туризм и пассажирские перевозки. Greenfield-разработка «Прогулочного флота»: 6 839 туров в сезон, чекаут 2-3 экрана vs legacy 5+, генерация PDF ~3 сек, TTL 15 мин на бронь. 2025 — 2026. Переиспользовано 80% кода основного продукта через $shared alias.
Тот же оператор речных круизов, второй продукт — «Прогулочный флот» (короткие прогулки на теплоходах 1-3 часа vs многодневные круизы основного «Круизного флота»). Задача: отдельный быстрый чекаут (бронирование+оплата за 2-3 экрана), общая backend-инфраструктура, без блокировки админ-фич основного продукта. Production-релиз 0.6.86 на pf.sputnik-germes.ru.
Контекст
У оператора уже работала legacy PHP-система бронирования прогулок — устаревший UX, проблемы с мобильной версией, тяжёлый чекаут на 5+ экранов. Параллельно велась миграция основного продукта (Круизного флота) на новый стек SvelteKit + Supabase.
Решение: отдельный фронтенд-проект frontend_mf (micro-frontend) на том же стеке, что и Круизный флот, со 100% переиспользованием backend (та же БД, те же RPC, те же shared-модули). Уникален только UI-слой Прогулочного флота, всё общее подключается через $shared alias.
Дополнительная сложность: legacy PHP-система продолжает работать (управление флотом, отчётность, выгрузки в 1С). Новый фронт должен делать атомарное создание заявок в legacy с TTL 15 минут до подтверждения оплаты.
Какие вызовы решены
- Как сделать чекаут «Прогулочного флота» за 2-3 экрана vs legacy 5+? Отдельный фронтенд-проект
frontend_mf(micro-frontend) с минимальным funnel: тур → каюта → ПД пассажиров → оплата. Всё на одном экране где возможно. - Как переиспользовать 80% кода с основным продуктом? Через
$sharedalias из Круизного флота: UI-компоненты, утилиты, типы, shared-pay/shared-notifications — общие. Уникален только UI-слой. - Как создавать заявки в legacy PHP-системе без отказа от неё? mTLS+HMAC мост к legacy endpoint: client cert + HMAC-SHA256(secret, ts.nonce.body) + Idempotency-Key UUIDv4. Атомарное создание
aa_schet+aa_order[]+aa_place[]со статусом=2 и TTL 15 минут. - Как делать UPSERT контрагентов без дублей? Уникальный ключ —
fio + birthday. Безbirthdaylegacy создаёт дубли. Поле обязательно в payload. - Как делать rollback заявки если оплата не прошла? TTL 15 мин на статус=2. После — автоматический rollback в legacy через cron-task.
Подход
- frontend_mf как micro-frontend. Уникальный код только специфики Прогулочного флота (короткий чекаут, прогулочные туры). Всё общее (UI-компоненты, утилиты, типы) — через
$sharedalias из Круизного флота. Принцип: «Круизный флот = primary, Прогулочный флот = derived через$shared/$frontendRoutes». - Legacy bridge через mTLS + HMAC. Endpoint на
192.168.11.11:443/api/pf/create_booking: client certpf-test/pf-prodот собственного CA + HMAC-SHA256(secret, ts.nonce.body), Idempotency-Key UUIDv4. Новый фронт «Прогулочного флота» делает атомарное создание заявки в legacy (aa_schet+aa_order[]+aa_place[]) соstatus=2и TTL 15 минут до подтверждения оплаты. birthdayобязателен в payload — нужен legacy для UPSERTaa_kontragentпоfio + birthday. Без него legacy создаёт дубли контрагентов.- Excursion PDF через Hatchet workflow. На сохранение версии экскурсии в админке → background рендер расписания PDF через
excursion-schedule-generateworkflow + Gotenberg → URL в/pdf/e/{slug}. Время генерации ≈ 3 секунды end-to-end. - Universal Document Platform обслуживает оба продукта через единый
pdf-tasks-worker(контейнер из hermes-stack) + общие таблицыvoucher_jobs/voucher_templates. 9 LIVE PDF-шаблонов: 1 voucher Круизного флота + 1 voucher Прогулочного флота + 7 версий pf_excursion. - Платежи через shared-pay. Альфа-банк СБП C2B + ЮKassa — переиспользованы из Круизного флота. Callback-обработка через выделенный
pay-serviceдля атомарности.
Результат
- 6 839 прогулочных туров в
promenade_toursза сезон 2026. - 7 версий pf_excursion (живущие документы, обновляются на старте сезона).
- 15 минут TTL на бронь до оплаты — после автоматический rollback в legacy.
- End-to-end за ~3 секунды: запрос → PDF в Supabase Storage → public URL → email клиенту.
- Live E2E с реальной оплатой: заявка создана, ваучер отправлен через 3 секунды, бронь подтверждена.
- Нулевой дублирующий код: 80% всего frontend Прогулочного флота — это
$sharedиз Круизного флота. Любая правка в основном продукте сразу попадает во второй (если не помечено как специфика).
Эффект для бизнеса
- Конверсия чекаута выросла — короткий путь 2-3 экрана vs legacy 5+.
- Производственные расходы не выросли — 80% общего кода с основным продуктом, любая правка идёт в оба продукта.
- Legacy не стал блокером для нового продукта — атомарное создание заявок и rollback по TTL делают переходный период безопасным.
Что мы можем сделать у вас
Если у вас на legacy-стеке есть основной продукт, и нужен второй продукт быстрее без переписывания backend’а — мы делаем micro-frontend на современном стеке поверх старого backend’а через mTLS+HMAC мост. /contacts
Что использовали
SvelteKit 2 + Svelte 5 runes + Tailwind 4 + shadcn-svelte (frontend_mf), Supabase Postgres 17 + RLS + Edge Functions Deno (backend), Hatchet TS SDK v1 (workflow engine), Gotenberg 8 (HTML→PDF), PDFKit (legacy backup для voucher), shared-pay + shared-notifications (общие модули из Круизного флота), mTLS + HMAC + Idempotency (legacy bridge), Альфа-банк СБП C2B + ЮKassa (платежи), Caddy auto-TLS, systemd, Docker Compose. AI-усиление: Claude Code SDK + Hermes Stack (9 docker-сервисов). Frontend через $shared alias переиспользует ~80% Круизного флота.
Часто задаваемые вопросы
Что входит в Greenfield-разработку «Прогулочного флота»?
Сколько занял запуск нового продукта?
Можно ли было обойтись доработкой основного продукта?
Когда Greenfield не оправдан?
Похожая задача?
Расскажите контекст — подскажу, что и как делать.
Обсудить похожий проект →