Розробка мобільного додатку для виклику майстра на дім (сантехнік, електрик)
Завдання «з'єднати клієнта з майстром за 3 хвилини» на поверхні виглядає просто: форма заявки, список виконавців, кнопка «викликати». На практиці — це геолокаційний матчинг у реальному часі, черги завдань з пріоритетами, двосторонні сповіщення та проблема «холодного старту» з нульовим числом майстрів у базі.
Що реально ломається при розробці
Головна біль — жива карта з майстрами. Якщо кожен майстер шле location кожні 3 секунди через REST, при 50 одночасних виконавців сервер отримує 1000 запитів на хвилину лише на оновлення позиції. Рішення: WebSocket-канал (на Flutter — пакет web_socket_channel 2.x) плюс серверний throttle. Клієнт отримує дельта-оновлення, а не повний список. На карті — flutter_map з TileLayer від OpenStreetMap або Google Maps SDK, залежно від бюджету ліцензії.
Друга проблема — статусна машина заявки. Типичний граф: created → assigned → accepted → in_progress → completed | cancelled. Якщо не зафіксувати переходи на рівні бекенду та не синхронізувати їх з локальним станом (Riverpod StateNotifier або BLoC), клієнт бачить «майстер їде» навіть після скасування — тому що push-сповіщення прийшло пізніше, ніж користувач оновив екран. Розв'язуємо через FCM data messages замість notification messages: додаток сам вирішує, що показати, виходячи з поточного стану.
Ще момент: рейтинги та відгуки не можна відкривати до завершення заявки. Якщо не додати серверну перевірку статусу перед записом відгуку, майстра отримують оцінки за незбувшиеся візити — бачив таке у трьох різних проектах.
Стек та архітектура
Flutter + Dart як основний вибір для cross-platform: один кодовой базою закриваємо iOS та Android, при цьому нативні виклики через MethodChannel — для фонової геолокації (background_locator_2) та обробки вхідних дзвінків через VOIP (на iOS — CallKit, на Android — ConnectionService). Вбудований чат — через Firebase Realtime Database або власний WebSocket, медіафайли (фото несправності) — через Firebase Storage або S3 з presigned URLs.
Архітектурно: Clean Architecture зі шарами domain / data / presentation. Репозиторії ізолюють логіку від джерела даних — легко менять Firebase на власний API без переписування UI. GetIt як service locator для DI, Dio з interceptors для REST, hive для кешу заявок офлайн.
Ключові інтеграції:
- Google Maps SDK / Yandex MapKit — маршрут майстра до клієнта
- Firebase Cloud Messaging — сповіщення про зміну статусу
- Stripe / CloudPayments / YooKassa — оплата після виконання
- Twilio або Vonage — маскування номерів при дзвінку
- OneSignal — маркетингові пуші та retention-кампанії
Окремо про онбординг майстрів
Верифікація виконавця — не просто форма з полями. Потрібна завантаження документів (паспорт, ліцензія), ручна модерація або інтеграція з сервісом перевірки (наприклад, російський «Контур.Фокус» для ІП). На Flutter: image_picker + dio multipart upload, статус перевірки через polling або WebSocket. Поки обліковий запис не верифіковано — флаг is_verified: false блокує приймання заявок на рівні API middleware.
Процес роботи
- Аудит вимог — з'ясовуємо: монетизація (комісія з заявки або передплата майстра), географія (один город або федеральна мережа), потрібен ли веб-кабінет диспетчера
- Проектування — ERD, State Machine діаграма заявки, API контракти (OpenAPI 3.0)
- UI/UX — Figma-прототип, окремі потоки для клієнта та майстра
- Розробка — спринти по 2 тижні, CI/CD через Fastlane + GitHub Actions
-
Тестування — інтеграційні тести на
flutter_test, ручна QA на реальних пристроях - Публікація — App Store + Google Play, налаштування ASO, скриншоти та описи
Часова шкала
MVP (клієнт + майстер, базовий матчинг, оплата, пуші): 10–16 тижнів. Повна платформа з кабінетом диспетчера, аналітикою та верифікацією: 20–28 тижнів. Вартість розраховується після аналізу ТЗ — занадто багато залежить від кількості категорій майстрів та географії охоплення.
Типові помилки, які коштують дорого
- Реалізувати геолокацію без
background_locator— майстер «пропадає» з карти, коли сворачує додаток на Android 12+ через Doze Mode - Зберігати токени FCM у локальній БД без TTL — через 3 місяці 30% токенів протухають, пуші перестають доставляються
- Не розділяти FCM-канали для клієнта та майстра в одному додатку — обидва отримують чужі сповіщення при зміні ролі







