Парное веб-приложение — это браузерная сторона продукта, который живёт прежде всего в мобильном приложении: место, где клиент регистрируется до установки, где расшаренная ссылка открывается у того, у кого приложения нет, где работа, начатая на телефоне, продолжается на десктопе. Это тот же продукт, на том же API, оформленный под то, что браузер действительно умеет хорошо, — а не порт приложения и не брошюра о нём.
Большинство агентств делает одну из сторон. Мы выпускаем Flutter-приложения, веб-фронтенды и бэкенд-сервисы, которыми и те и другие пользуются, — и это меняет инженерию, потому что на вопрос «на какой стороне должна жить эта функция» отвечает одна команда, глядящая на одну систему, а не переговоры двух подрядчиков.
Какие продукты мы делаем
- Клиентские веб-приложения рядом с мобильными — полный продукт в браузере там, где это оправдано, или осознанное подмножество там, где нет
- Публичные, расшариваемые страницы — страницы, в которые разворачивается пересланная ссылка, отрендеренные и индексируемые, с передачей в приложение, когда оно установлено
- Веб-клиенты реального времени — живые данные в браузере из той же ленты, которую потребляют приложения
- Бэк-офисы того же продукта — операторская сторона — отдельная дисциплина, разобранная на странице админ-панелей и дашбордов
- Веб-сторона на Nuxt — когда парная веб-часть должна ранжироваться, машинерия для этого — наша практика разработки на Nuxt
Кто будет делать ваше парное веб-приложение
Паттерн видно на двух продуктах в продакшене: у каждого — приложение и веб на одном общем бэкенде.
Formtastic — одна платформа, три клиента
Formtastic работает как веб-приложение на Nuxt плюс Flutter-приложения для iOS, iPad и Android — все против одного бэкенда на Django и Go. Показательнее всего то, насколько по-разному одна и та же функция устроена на каждой стороне: голосовой ввод в вебе записывает аудио в браузере и отправляет его на эндпоинт транскрипции, потому что бэкенд, который можно расширить, уже был, — а мобильные приложения несут Whisper прямо на устройстве, потому что на объектах нет связи. Одна функция, две реализации, и каждая честно считается со своей средой. Именно это суждение, больше чем владение фреймворком, и есть то, чего продукт с двумя клиентами требует на самом деле.
ExtraETF — одна лента реального времени, все клиенты
Для ExtraETF мы построили на Go сервис на базе WebSocket, который транслирует живые рыночные данные и веб-, и мобильным клиентам: тысячи одновременных подключений, обновления сведены к той частоте, которая реально нужна человеку, следящему за ценой. Мы сделали мобильные приложения и слой реального времени; веб-клиент, который его потребляет, принадлежит команде самого клиента — и в этом весь смысл. Хорошо спроектированный сервис кормит и те интерфейсы, которые вы никогда не будете строить сами.
Чего на самом деле требует продукт с двумя клиентами
Четыре дисциплины удерживают приложение и веб от превращения в два разных продукта.
Один API, честно обслуживающий обоих
В момент, когда вебу нужен «всего один особый эндпоинт», у вас уже два бэкенда под одним именем. Мы проектируем API как единый контракт продукта — одна аутентификация, одни модели, одно версионирование для каждого клиента, — а там, где сторонам действительно нужны разные формы данных, это различие прописывается в контракте, а не залатывается в клиенте.
Решить, чем является веб-версия
Дорогая ошибка — «приложение, только в браузере». Парная веб-часть окупает свой бюджет тем, чего приложение не умеет: быть достижимой из поисковой выдачи, мгновенно открываться по пересланной ссылке, давать клавиатуру и большой экран для серьёзного редактирования. Мы просеиваем через этот тест каждую функцию — и вычеркнутая из веб-версии функция для нас решение, которое мы отстаиваем вслух, а не дыра, обнаруженная позже.
Передача между вебом и приложением
Пересланная ссылка должна открывать приложение, когда оно установлено, веб-страницу — когда нет, и никогда — сломанную промежуточную страницу. Universal links на iOS и app links на Android, фолбэк-страницы за ними и сценарий регистрации, который начинается в браузере и продолжается в приложении, — на этом шве продукты с двумя клиентами теряют пользователей заметнее всего, поэтому мы прорабатываем его намеренно, не рассчитывая, что он заработает сам.
Рендеринг под задачу страницы
Публичные, расшариваемые страницы рендерятся на сервере, чтобы краулеры и превью ссылок видели настоящий контент; рабочее пространство за логином рендерится как приложение, которым оно и является. Компромиссы разложены на пилларной странице веб-разработки, и выбор делается для каждого маршрута, а не для проекта целиком.
Как мы работаем
Проект с фиксированным объёмом. Мы ведём веб-сторону от определения набора функций до деплоя — против вашего существующего API или того, который построим рядом с ним.
Staff augmentation. Наши инженеры входят в команду, которая владеет продуктом, — см. расширение команды. Если мобильную сторону тоже нужно строить, это наша практика Flutter.
В обоих случаях смету под задачу мы присылаем в течение двух рабочих дней после того, как разберёмся в требованиях.
Сколько стоит парное веб-приложение
Парная веб-часть оценивается по тем же опубликованным тарифам, что и страница веб-разработки: веб-приложение с авторизацией на вашем существующем API попадает в тариф веб-приложения, 1 350 000–3 600 000 ₽, а полноценная вторая сторона продукта с реальным временем, платежами или мультитенантной структурой оценивается как работа уровня SaaS — от 4 500 000 ₽.
Это те же ключи, из которых рисуется таблица цен пилларной страницы, поэтому разойтись они не могут. Что двигает цифру: какая часть API уже существует и насколько чисто он спроектирован под больше чем одного клиента, какую часть продукта покрывает веб-версия и едут ли функции реального времени по существующей ленте — или её нужно строить.
Частые вопросы
Что чаще всего спрашивают команды, чей продукт живёт в приложении, а пользователи продолжают просить его в браузере.
Посмотрите обе стороны в кейсе Formtastic, почитайте, как лента реального времени ExtraETF раздаётся всем клиентам, или начните с пилларной страницы веб-разработки.
