Мобільний застосунок для дошки об'явлень (Classifieds)
Доска об'явлень — висokokомпетитивна ніша. Avito, OLX, Kufar задали планку UX та швидкості. Користувач піде, якщо публікація об'яви займає більше 2-3 хвилин, а фотографії завантажуються по одній. Технічно ключові речи тут — швидкий пошук, пошук по карті, мессенджер всередину застосунку та надійна завантаження фото.
Публікація об'яви: мінімум тертя
Форма об'яви — категорія → заповнення полів → фото → ціна → публікація. Поля залежать від категорії (для авто — VIN, пробіг, рік; для нерухомості — площа, поверх, тип угоди). Динамічна форма: при зміні категорії поля перерисовуються. JSON Schema від сервера → генерація форми на клієнті (избавляет від hardcode полів в коді).
Завантаження фото — найбільше вузьке місце. Користувач хоче завантажити 10 фото. Послідовне завантаження — забагато часу. Паралельне — перегружає мережу на мобільному. Оптимально: 3 паралельні upload через URLSession background session (iOS) або WorkManager з ListenableFuture (Android). Прогрес-бар для кожного фото індивідуально.
Компресія перед завантаженням: UIImage.jpegData(compressionQuality: 0.8) або Bitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream). Фото з iPhone 15 Pro — 8-15 МБ в RAW. Після компресії — 1-2 МБ. Для об'яви достатньо, трафік економиться.
Визначення геолокації об'яви
Місцезнаходження об'яви — або поточні координати, або вибір на карті, або введення адреси з геокодингом. Для продажу речей зазвичай достатньо райойну/міста без точної адреси — це важливо для безпеки продавця. Точні координати потрібні для нерухомості та авто.
Пошук та фільтрація
Повнотекстовий пошук — Elasticsearch або Typesense на бекенді. Клієнт відправляє запит, debounce 300 мс на полі введення. Пошук з урахуванням морфології (російська мова — «машина» находить «машины», «машиной») — через Elasticsearch з russian analyzer або Typesense з Russian stemmer.
Фільтри ціни — range slider. RangeSlider в Material 3 (Android) / кастомний GeometryReader-based range slider (SwiftUI або бібліотека RangeSeekSlider). Значення debounce перед запитом.
Пошук по карті — користувач рухає карту, об'яви оновлюються по видимій області. onCameraIdle (Google Maps) / onMapIdle (Mapbox) → запит з bbox поточного viewport. Маркери на карті, натиск — карточка об'яви.
Для нерухомості важна кластеризація: в одному будинку 50 об'яв. Кластер показує кількість, при zoom-in розкривається в окремі маркери або список.
Мессенджер
Чат продавця та покупця всередину застосунку — без обміну номерами телефонів. Firebase Realtime Database або Supabase Realtime — швидкий спосіб запустити чат з real-time повідомленнями. Для серйозного масштабу — власний WebSocket-сервер або Stream Chat SDK.
Структура повідомлень: { id, conversation_id, sender_id, text, image_url, timestamp, read_at }. read_at для статусу прочитання. Push при новому повідомленні — FCM/APNs data push з conversation_id в payload для deep link в конкретний чат.
Фото в чаті — користувач відправляє фото. Компресія до 800-1200px, upload в S3/Cloudflare R2, повідомлення містить URL. При відображенні — lazy loading з progressive placeholder.
Антиспам: обмеження швидкості повідомлень (rate limiting на сервері), блокування користувача.
Модерація об'явлень
На стороні клієнта: попередження при введенні телефону/пошти в тексті об'яви (обхід контактів через платформу). Кнопка «Пожалаватися» на кожній об'яві — попап з причиною скарги, відправка на сервер.
Автоматична модерація фото: Google Cloud Vision API SafeSearch — перевірка на explicit контент. Інтегрується в upload pipeline на сервері, клієнт отримує статус об'яви (pending_moderation / approved / rejected).
Монетизація та просування
«Поднять об'яву», «VIP-статус», «виділити» — класичні платні опції. In-app purchase через StoreKit 2 / Google Play Billing або разова оплата через Stripe.
Push-кампанії: сповіщення власнику при додаванні в улюблені, при зниженні ціни на улюблене об'яву іншого користувача.
Стек: Flutter (швидкість розроблення важлива для marketplace), Elasticsearch/Typesense для пошуку, Firebase/Supabase або custom WebSocket для чату, Cloudflare R2 / S3 для медіа, Google Maps SDK / Mapbox для карти.
Етапи: структура категорій та схема даних → публікація → пошук та фільтрація → карта → чат → модерація → монетизація → тестування → публікація.
Термін: від 14 до 24 тижнів. Вартість розраховується індивідуально.







