Перейти к основному содержимому

Архитектура

Общая картина системы Ghost Kitchen: что это, из чего состоит и почему выбран именно такой стек.

:::info Для кого этот раздел «Обзор», «Роли и панели» и «Запуск нового бренда» написаны простым языком — их можно показывать заказчику и агентству. «Модель данных» и «Интеграции» в разделе Бэкенд — техническая зона напарника. :::

Что мы строим

Ghost Kitchen — это собственная multi-tenantMulti-tenantАрхитектура, где одна копия приложения и одна база данных обслуживают много изолированных клиентов (тенантов). Здесь тенант = бренд. платформа для управления сетью ресторанов-доставок и брендов. Она заменяет связку из агрегаторовАгрегаторПлатформа-посредник, собирающая заказы для ресторанов (например, доставка еды). Передаёт заказы на кухню и берёт комиссию. (Uber Eats, Lieferando, Bolt Food) и аренды Shopify на одну кодовую базу и одну базу данных, которые обслуживают все бренды сразу.

Платформа даёт: витрину заказов, приём и оплату заказов, управление меню, передачу заказов на кухню (POSPOSPoint of Sale — кассовая система ресторана. Здесь — Liefersoft: принимает заказы от платформы, печатает чеки, ведёт фискальный учёт.), аналитику и управление брендами — при меньшей комиссии, чем у агрегаторов.

Почему не Shopify

Подробный разбор — в материалах для заказчика. Если коротко, Shopify лицензирует каждый магазин отдельно: на 10 брендах это 10 подписок, 10 админок, 10 интеграций и изолированные друг от друга данные клиентов. Самую сложную часть — связь с кухонной кассой — всё равно пришлось бы писать руками. Кастомный multi-tenantMulti-tenantАрхитектура, где одна копия приложения и одна база данных обслуживают много изолированных клиентов (тенантов). Здесь тенант = бренд. стек убирает эту линейную стоимость: новый бренд — это строки в базе, а не новая подписка.

Рекомендуемый стек

СлойТехнологияЗачем
Витрина клиентаNuxt 3NuxtМета-фреймворк поверх Vue.js. Поддерживает серверный рендеринг (SSR) и режим SPA. Используется для витрины клиента и админок. (Vue) в режиме SSRSSRServer-Side Rendering — страница собирается на сервере и отдаётся готовым HTML. Нужен для SEO и скорости первой загрузки витрины.SEO и скорость food-сайтов
АдминкиNuxt / Vue в режиме SPASPASingle-Page Application — приложение рендерится в браузере, без перезагрузки страниц. Подходит для админок за логином, где SEO не нужен.За логином, SEO не нужен
Данные + API + админ-ядроDirectusDirectusOpen-source headless-платформа поверх PostgreSQL: даёт модель данных, REST/GraphQL API, аутентификацию, RBAC и готовую админку без написания кода.Модель данных, REST/GraphQL, RBACRBACRole-Based Access Control — управление доступом на основе ролей. Права выдаются роли (Company Admin, Brand Admin, Restaurant Manager), а не каждому пользователю отдельно., готовая админка
Бизнес-логика и интеграцииNode-адаптерЗаказы, вебхуки, связь с POS/оплатой
База данныхPostgreSQLТенантЛогически изолированный клиент в multi-tenant системе. В Ghost Kitchen тенант — это бренд: его данные отделены от других по `brand_id` и правам доступа.Единый источник правды
ПлатежиMollieMollieЕвропейский платёжный провайдер. Принимает оплату (карты, iDEAL, Apple/Google Pay и др.) и присылает статус платежа через вебхуки.Приём оплаты (ЕС)
Касса ресторанаLiefersoftLiefersoftPOS/кассовая система ресторана (Германия) с TSE-фискализацией. Платформа передаёт ей заказы для приготовления и фискального учёта.Приготовление + TSE-фискализацияTSE-фискализацияТехнические требования Германии (Technische Sicherheitseinrichtung) к кассам: каждая продажа защищённо подписывается. Обеспечивается на стороне POS (Liefersoft).
ХостингVercel + Neon + HetznerПлоская стоимость, не растёт с числом брендов

:::note Ответ на вопрос «SPA или нет» Витрина клиента — SSR, не SPA. Поисковая выдача и превью ссылок (Google, мессенджеры) критичны для конверсии в доставке. Админки — SPA: они за логином, индексировать нечего, а интерактивность выше. Nuxt поддерживает оба режима в одном фреймворке. :::

Карта системы (C4 — контекст)

Три слоя бэкенда

Бэкенд намеренно разделён на три части с чёткими границами:

  1. DirectusDirectusOpen-source headless-платформа поверх PostgreSQL: даёт модель данных, REST/GraphQL API, аутентификацию, RBAC и готовую админку без написания кода. — «80% без кода». Описываем модель данных (бренды, кухни, меню, заказы, пользователи) — и сразу получаем REST/GraphQL API, аутентификацию, RBACRBACRole-Based Access Control — управление доступом на основе ролей. Права выдаются роли (Company Admin, Brand Admin, Restaurant Manager), а не каждому пользователю отдельно. и готовую админку для контент-операций.
  2. Node-адаптер — «оставшиеся 20%». То, что Directus не делает: оркестрация оформления заказаCheckoutОформление заказа: ввод контактов и адреса, выбор времени/доставки, оплата и подтверждение. В кастомном стеке полностью под нашим контролем., приём вебхуковWebhookHTTP-уведомление, которое внешний сервис (например, Mollie) шлёт платформе при событии — например, «платёж оплачен». Альтернатива постоянному опросу API. Mollie, передача заказа в LiefersoftLiefersoftPOS/кассовая система ресторана (Германия) с TSE-фискализацией. Платформа передаёт ей заказы для приготовления и фискального учёта., повторные попытки, идемпотентностьИдемпотентностьСвойство операции давать один и тот же результат при повторе. Защищает от дублей заказа/платежа при повторной доставке вебхука или ретрае., dead-letter queueDead-letter queueОчередь для сообщений/задач, которые не удалось обработать после всех повторов. Их разбирают вручную, чтобы не потерять заказ при сбое интеграции..
  3. PostgreSQLТенантЛогически изолированный клиент в multi-tenant системе. В Ghost Kitchen тенант — это бренд: его данные отделены от других по `brand_id` и правам доступа. — единый источник правды. Все бренды в одной базе, изоляция по brand_id и правам доступа.

Multi-tenant: тенант = бренд

Каждый брендБрендТорговая марка внутри платформы (например, «Pizza Burger»). Один бренд может иметь несколько ресторанов/кухонь. В архитектуре бренд = тенант. — это логически изолированный тенантТенантЛогически изолированный клиент в multi-tenant системе. В Ghost Kitchen тенант — это бренд: его данные отделены от других по `brand_id` и правам доступа. в общей базе. Данные одного бренда не видны другому, но платформа (Company AdminCompany AdminВладелец платформы. Видит и управляет всеми брендами, ресторанами, заказами и сквозной аналитикой; создаёт новые бренды.) видит всё сразу — отсюда сквозная аналитика «одним SQL-запросом», недостижимая на изолированных магазинах Shopify.

Масштаб

Сейчас разговор с заказчиком — про 3–10 брендов в горизонте двух лет. Но multi-tenant архитектура с самого начала проектируется так, чтобы расти до десятков и сотен брендов без переписывания: добавление бренда не требует деплоя, нагрузка распределяется на уровне одной базы и одного набора сервисов. Конкретные шаги горизонтального масштабирования (реплики БД, кэш, очереди) описываются в разделе Бэкенд по мере роста.

Что дальше