Skip to main content
Skip to main content
Anteyko

Case Study

LocalFood: Peer‑to‑Peer Home‑Cooked Food Delivery Platform (iOS + Backend)

Full-cycle mobile platform connecting home chefs with local food lovers: native iOS app (Swift/SwiftUI) with dual-role architecture (Chef & Customer), real-time order tracking with map integration, multi-step registration with OTP verification, geo-filtered food feed with recommendations, cart & checkout with pickup/delivery options, MIR card payment processing, kitchen quality verification via photo/video, push notifications, and a Node.js/PostgreSQL backend with geospatial queries, WebSocket order updates, and S3 media pipeline.

40+UI screens designed
2 (Chef + Customer)User roles
4Registration steps
6Order statuses tracked
Year: 2021Industry: FoodTech / Marketplace / DeliveryTimeline: 14 weeks

Problem

A Moscow-based client wanted to launch a peer-to-peer food marketplace — a platform where home chefs could sell their dishes to neighbors, with real-time delivery tracking, quality verification, and payment processing. Existing food delivery apps (Yandex.Eda, Delivery Club) cater to restaurants, not individuals. The client needed a two-sided marketplace with distinct experiences for chefs (menu management, order processing, kitchen verification) and customers (geo-based discovery, cart, checkout with pickup/delivery, order tracking on map). The platform had to handle geospatial search (find chefs within 50–1000m radius), OTP-based dual verification (phone + email), MIR payment card processing, real-time order status updates via WebSocket, photo/video kitchen verification for food safety compliance, and map-based delivery routing with ETA calculation. Per client agreement, the app name and logo shown are changed from the original.

Constraints

  • Native iOS (Swift 5 + SwiftUI) — no cross-platform compromises for a premium feel
  • Dual-role architecture: same app, different experience for Chef and Customer
  • 4-step registration with dual OTP verification (SMS + email)
  • Geospatial food feed: PostGIS radius queries (50m–1000m) with distance chips
  • Real-time order tracking: WebSocket status updates + MapKit route rendering with ETA
  • MIR card payment processing (Russian payment system integration)
  • Kitchen verification: photo + live video stream for food safety compliance
  • Push notifications for order lifecycle (ready, in transit, payment failed)
  • App name and logo changed per client NDA agreement

Solution

Designed and built a full-stack two-sided food marketplace across iOS and backend.

iOS APP (Swift 5 + SwiftUI)

dual-role onboarding — at registration Step 1, user chooses Chef or Customer, defining their entire navigation tree; 4-step registration flow (role selection → personal data with bio/DOB/gender → contact info with phone/email/address with geolocation → dual OTP verification for both phone and email); personalized geo-filtered food feed with recommendation carousel (featured dish with chef avatar, rating, price, one-tap add to cart), search with advanced filters (distance radius chips 50–1000m, price range slider, sort order, food type tags — Meat, Salad, Appetizer, Pastry, Side, Soup, Drinks, Grill); dish detail screen with full-bleed hero photo, chef badge, rating with review count, description, ingredients, category tags, and 'More from this chef' section; cart with item management (quantity +/−, favorites, delete), line-item breakdown and total; checkout with segmented control for Pickup vs Delivery (pickup shows chef address + map link, delivery shows user address + delivery fee calculation), saved MIR payment cards with add/remove, order summary with service fee breakdown; 6-stage order tracking on live map (Pending → Accepted → Cooking → In Transit → Delivered → Completed) with real-time driver position via WebSocket, route rendering with ETA (e.g. '32 min, 27.6 km'), and order detail overlay; payment error screen with retry flow and support contact; push notification center with order status updates and payment failure alerts.

CHEF EXPERIENCE

profile with rating, bio, menu management, 'Add dish' form (photo upload, name, description, ingredients, tags, price), order management (incoming orders with Accept/Reject, order detail with item list and 'Start cooking' action), kitchen quality verification (photo of kitchen/products for sanitary inspection + live camera stream), media gallery (uploaded photos + video for transparency).

BACKEND (Node.js + Express + PostgreSQL + PostGIS)

geospatial queries via PostGIS (ST_DWithin for radius search, ST_Distance for distance calculation, spatial index on chef locations for sub-50ms query time at 100K+ records), WebSocket server (Socket.IO) for real-time order status push and delivery driver location updates, S3 media pipeline (dish photos, chef avatars, kitchen verification photos/videos — upload via pre-signed URLs, Sharp-based image resizing to 3 breakpoints, CloudFront CDN for delivery), MIR payment gateway integration (tokenized card storage, 3-D Secure, idempotent charge requests), OTP service (SMS via SMS.RU provider + email via Nodemailer/SES, 6-digit codes with 90-second TTL and rate limiting), order state machine (Pending → Accepted → Cooking → Ready → InTransit → Delivered, with compensating transitions for cancellation/refund), recommendation engine (collaborative filtering based on order history + geo-proximity scoring), and structured logging via Pino with request tracing.

Deliverables

  • Native iOS app (Swift 5 + SwiftUI, dual-role: Chef & Customer)
  • 4-step registration with dual OTP (phone SMS + email verification)
  • Geo-filtered food feed with recommendation carousel and advanced filters
  • Dish detail, chef profile, and 'More from chef' discovery
  • Cart with quantity management, favorites, and line-item totals
  • Checkout with Pickup/Delivery toggle, MIR card management, service fee breakdown
  • 6-stage real-time order tracking on live map (WebSocket + MapKit + ETA)
  • Payment error handling with retry flow
  • Push notification center (order ready, in transit, payment failed)
  • Chef: menu CRUD (photo, description, ingredients, tags, price)
  • Chef: order management (accept/reject, detail, 'start cooking')
  • Chef: kitchen verification (photo + live video stream for sanitary compliance)
  • Node.js + Express REST API with PostGIS geospatial queries
  • WebSocket server (Socket.IO) for real-time order/driver updates
  • S3 media pipeline (pre-signed upload, Sharp resizing, CloudFront CDN)
  • MIR payment gateway (tokenized cards, 3-D Secure, idempotent charges)
  • OTP service (SMS.RU + SES, rate limiting, 90s TTL)

Screenshots / UX Flow

Step-by-step walkthrough of the product interface

01

Onboarding — 'Order delicious food from neighbors' welcome screen with LocalFood branding

02

Login — email/phone + password authentication with 'Sign up' link

03

OTP — phone number verification with 6-digit code entry and 1:27 resend timer

04

OTP — email verification with 6-digit code sent to example@mail.ru

05

Registration Step 1 — role selection: Chef (with chef hat icon) or Customer (with utensils icon)

06

Registration Step 2 — personal data: first name, last name, about me bio, date of birth, gender

07

Registration Step 3 — contact info: phone or email, address with geolocation pin, password

08

Registration Step 4 — email OTP verification during registration flow

09

Registration Step 4 — phone OTP verification during registration flow

10

Main feed — delivery address, recommendation carousel (Caesar Salad 249₽), search, chef cards with ratings

11

Feed with cart badge — floating cart button showing 2184₽ / 2 items

12

Feed with active order banner — Order #160924 'Awaiting pickup' with 'On map' button

13

Filters — distance chips (50–1000m), price range slider (120–1100₽), sort by price, food type tags

14

Dish detail — full photo, chef badge (4.8★), 141 reviews, description, ingredients, tags, 'More from chef'

15

Dish detail (alternate) — same layout with different dish, showing add-to-cart 249₽ button

16

Chef profile — avatar, username, 4.8★ rating, 'About me' bio, menu list with prices and add buttons

17

Cart — items with photos, prices, quantity controls (−/+), favorites, delete, 2 items total 596₽

18

Checkout (Pickup) — pickup/delivery toggle, chef address on map, MIR cards, 2 items 596₽ + 49₽ service = 645₽

19

Checkout (Delivery) — delivery selected, user address, MIR cards, 596₽ + 49₽ service + 120₽ delivery = 765₽

20

Payment error — red screen 'Order #52120120 payment failed' with Retry button and support contact

21

Order tracking — map with route, 'Awaiting pickup' status, 32 min ETA, 27.6 km, order details overlay

22

Order tracking — 'In transit' status with live driver position on map route

23

Order tracking — chef view: 'Deliver the dish to the customer' instruction with map

24

Order delivered — status 'Delivered', items list with 'Repeat order' button

25

Account menu — Profile, Addresses, Notifications, Settings + 'Become a chef' CTA, Logout/Support

26

Payment data — saved MIR cards (····7289, ····3212) with delete/confirm actions, 'Add card' button

27

Add payment method — card number, name, MM/YY, CVV fields with 'Add' button

28

Notifications — 'Your order is ready' (×2), 'Payment failed' alerts with order numbers and timestamps

29

Address list — saved delivery address (Moscow, pl. Lenina 11) with edit icon, 'New address' button

30

Address map — full map view with route (32 min / 27.6 km), delivery address input, apartment/floor fields, 'Detect location'

31

Profile edit — avatar upload, name, surname, username, bio, DOB, gender, email/phone, password

32

Chef profile (own view) — avatar, name, rating 4.8★, 'Edit' button, 'My orders' badge, bio, menu with 'Add dish'

33

Chef orders — incoming order #160924 (1265₽, 'Delivered') with food thumbnails, Accept/Reject buttons

34

Chef order detail — Order #160924 'Accepted', item list (Caesar ×2, beef, crab salad) with 'Start cooking' button

35

Kitchen verification — 'Photograph kitchen and products for quality and sanitary assessment' with photo/upload buttons

36

Camera stream — 'Prepare camera, products and start broadcast' with camera preview window

37

Media gallery — uploaded photos grid + video section with play button, 'Order ready' action

38

Dish (chef view) — same detail screen but with delete icon and 'Edit' button instead of add-to-cart

39

Edit dish — photo upload area, name field, description, ingredients, tags, price, 'Save' button

40

Create dish — empty form with photo placeholder, name, description, ingredients fields, 'Save' button

Artifacts

Documents and deliverables from the project

iOS app + real-time tracking + geo-feed

Artifact

Verification report

Release gate

Verification / Quality gates

8-phase checklist before release

01Build (Xcode + backend)
Pass
02PostGIS query performance (<50ms)
Pass
03WebSocket order tracking E2E
Pass
04MIR payment integration tests
Pass
05OTP delivery verification (SMS + email)
Pass
06Dual-role navigation audit
Pass
07Media pipeline (upload → resize → CDN)
Pass
08UAT with Moscow test group
Pass
All gates passed
8/8

Tech stack

Swift 5SwiftUIMapKitCoreLocationNode.jsExpressPostgreSQLPostGISSocket.IORedisAWS S3CloudFrontSharpMIR Payment GatewaySMS.RUPinoDockerNginx

Outcome

Delivered a production-ready two-sided food marketplace: 40+ iOS screens covering the complete user journey from onboarding to order delivery, dual-role architecture (Chef manages menu/orders/verification, Customer discovers/orders/tracks), real-time map tracking with WebSocket-driven status updates and ETA, PostGIS-powered geospatial discovery (sub-50ms on 100K+ chef records), MIR payment processing with 3-D Secure, kitchen quality verification via photo and live video stream. The platform handles the full order lifecycle with 6 tracked statuses, push notifications at every transition, and error handling with retry flows. Per client agreement, the app was delivered under a pseudonym (LocalFood) with a neutral logo — the actual product operates under the client's brand in Moscow.

Hard parts we solved

Dual-Role Architecture in a Single App

Chef and Customer share authentication and core infrastructure but have entirely different navigation trees, screens, and data flows. Role is selected at registration Step 1 and defines the app's behavior: Customers see a geo-feed, cart, checkout, and tracking; Chefs see menu management, order queue, kitchen verification, and a chef-specific profile. Implemented via SwiftUI's NavigationView with role-conditional root views, @EnvironmentObject for role state propagation, and a shared data layer (CoreData for offline cache + URLSession API sync). Choosing SwiftUI over UIKit in 2021 was a deliberate forward-thinking decision — the framework was mature enough on iOS 14+ for this scope, while giving us declarative UI composition and significantly faster iteration cycles.

PostGIS Geospatial Search with Sub-50ms Performance

Food discovery is driven by proximity — users see dishes from chefs within a configurable radius (50m to 1000m). Implemented via PostGIS: chef locations stored as geography(POINT, 4326), spatial GIST index, and ST_DWithin for radius filtering. Distance chips in the filter UI map directly to SQL parameters. At 100K+ chef records, queries return in under 50ms. Combined with collaborative filtering (order history + proximity score) for the recommendation carousel.

Real-Time Order Tracking with 6-Stage State Machine

Order lifecycle: Pending → Accepted → Cooking → Ready/InTransit → Delivered → Completed. Each transition triggers a WebSocket event (via Socket.IO) that updates the customer's map view in real-time: driver location pin animates along the route, ETA recalculates, and the status banner changes. MapKit renders the route polyline with distance and time overlay ('32 min, 27.6 km'). Compensating transitions handle cancellation (refund via MIR gateway) and payment failure (retry screen with support contact). Chef receives push notification on new order and can Accept/Reject from the notification or the orders screen.

Kitchen Verification for Food Safety Compliance

Before a chef can start receiving orders, they must pass kitchen verification: upload photos of their kitchen and products (reviewed by the platform's moderation team), and optionally start a live camera stream for real-time inspection. The verification flow uses the device camera (AVFoundation) for photo capture and HLS for live streaming to a moderation dashboard. Media is uploaded to S3 via pre-signed URLs, resized via Sharp, and served via CloudFront. This feature was a regulatory requirement from the client to demonstrate food safety diligence.

Have a similar project? Get an estimate or book a call.