Что рядом
Карта вместо списка: заведения сортируются по расстоянию, у каждой карточки видно «307 м от вас», цену микса и время работы. Никакого бренд-лендинга: пользователь выбирает то, что рядом и открыто.
Контекст
Гость уже сидит в лаунже: приглушённый свет, шумно, телефон в одной руке. Ему не нужно «изучить меню», нужно собрать микс и отправить его. Владельцу нужна обратная сторона: заказ мгновенно, чат для уточнений, склад табака и понимание, кто возвращается.
Food-delivery решения эту пару задач не закрывают: они спроектированы под доставку, а не под гостя, который уже в зале. Поэтому строили с нуля свою модель данных, свой флоу заказа и свою дизайн-систему под тёмный зал.
Клиентский флоу
Карта вместо списка: заведения сортируются по расстоянию, у каждой карточки видно «307 м от вас», цену микса и время работы. Никакого бренд-лендинга: пользователь выбирает то, что рядом и открыто.
Два режима. «Подберите мне»: крепость, холодок и направления вкуса, дальше собирает сервис. «Соберу сам»: каталог табака заведения с точными пропорциями. Направления открывают шит с подкатегориями.
Сводка, напитки к кальяну, время подачи чипами или колесом, и одна кнопка. Заказ уходит владельцу мгновенно, дальше статусы и чат по этому заказу.
26 экранов · операционка
Второе приложение в том же монорепо: заказы в реальном времени, редактор карты зала, склад табака и напитков, смены персонала, отзывы, CRM гостей, аналитика и подключение внешних систем.
← Листайте · клик по экрану — увеличить
1 654 позиции · 24 бренда
Третье приложение отвечает за каталог табака: таблица на 1 654 вкуса, где у каждой позиции есть вектор дескрипторов (сладость, кислинка, свежесть, пряность, травы, конфетность, кулинарность, сливочность, десертность, крепость). На этих числах работает подбор миксов в приложении гостя.
Инфраструктура
Деплой идёт одним bash-скриптом с рабочей машины: сборка, rsync, pm2. Без CI, без контейнеров на прикладном слое.
Инженерия
Продакшн жил на облачном Supabase в Ирландии: 100–200 мс на запрос через границу, требования к хранению персональных данных и санкционный риск. Перевезли весь стек на собственный VPS в Москве: Postgres, авторизация, storage, шлюз. План разложили на восемь ранбуков: провижининг, разворачивание, DNS и SSL, бэкапы, тестовый прогон полного дампа, чеклист дня миграции и процедуры отката. Окно простоя составило 15–25 минут ночью, старое облако держали ещё неделю как страховку. После переезда до базы 3–10 мс.
Диапазоны, где хостилось облако, фильтровались по DPI, и логин у части пользователей не работал без VPN. Поставили перед ними Cloudflare Worker: через anycast-прокси пошли и Telegram Bot API, и SDK-скрипты, и трафик фронтенда к базе. На бэкенде прокси включается переменной окружения, прямые адреса остаются рабочим дефолтом.
Socket.IO-gateway внутри того же бэкенда: комнаты по заказу, статусы прочтения и присутствия, аутентификация соединения по токену и проверка источника по вайтлисту. Тексты сообщений и вложения лежат в базе зашифрованными AES-256-GCM с версионированным префиксом, а уже накопленную переписку зашифровали отдельным скриптом миграции.
Клиентский и админский боты живут в одном процессе: уведомление маршрутизируется по типу получателя: новый заказ и сообщение гостя уходят владельцу, смена статуса и ответ заведения возвращаются гостю. Оба приложения работают и как Telegram Mini App: серверный прокси SDK с прогревом кэша, чтобы фронтенд не ходил на внешние домены.
Микс собирается из реального остатка табака конкретного заведения. Каждый вкус описан вектором из семи дескрипторов, поверх — правила несочетаемости категорий: кулинарный вкус не ставится с десертным, безароматка не дублируется. Состав считается детерминированно, языковая модель подключается только на последнем шаге, для названия и описания. Отдельным контуром шёл python-прототип на оценках «ок / не ок» с обучением RandomForest и GradientBoosting.
Приложение живёт в трёх средах сразу: браузер, установленная PWA и Telegram WebView. Отступы собраны трёхуровневым каскадом: статичный fallback, затем env(safe-area-inset), затем переменные Telegram. Web Push на iOS работает только в установленной PWA начиная с 16.4, а ключи VAPID нельзя менять после первых подписок. Плюс вендорные префиксы для backdrop-filter и clip-path и фоллбек 100vh перед 100dvh.
Язык интерфейса
Ощущение приглушённого лаунжа ночью, а не дашборда в полдень. Тёплый тёмный вместо холодного tech, редакторский разворот вместо формы ввода.
Направление зафиксировано в коде как система токенов: 124 переменных, 65 миксинов, 34 анимации. Огонь остаётся резервируемым ресурсом: один основной CTA на экран, одна пульсация, один градиентный wordmark. Стекло с размытием и тёплый ambient-градиент на фоне; вес шрифта ограничен 600, основной текст мягкий #F5F5F5 вместо чистого белого, чтобы не слепить в темноте.
Анти-референсы прописаны так же строго, как токены: утилитарные серые списки доставки, казино-золото во всю ширину, яркий consumer-tech и кофейные приложения со штампами. Всё mobile-only, 320–430 px: hover-состояний нет вообще, только нажатие, тап-зоны от 44 px, анимации выключаются при системном запросе уменьшить движение.
Технологии
Экраны сняты на локальной сборке проекта с демонстрационными данными.
Нужен такой же продукт?