Independent Build / 05 · Full-Stack Marketplace & Geospatial Systems

Helpful: 3-Sided On-Demand Home Services Marketplace

Architecting an on-demand domestic cleaning platform for Singapore: multi-app Flutter monorepo with shared immutable data models, PostGIS 15km radial geospatial dispatch, OneMap Singapore postal code resolution, and atomic serverless edge state machines.

3
Apps in 1 Monorepo
15km
PostGIS Dispatch Radius
100%
Singapore Postal Resolution
0
Client-Side Race Conditions
Project Status · Client Commission

This platform was commissioned by a Singapore corporate client. Development is currently on temporary hold while the client resolves Singapore regulatory and legal licensing requirements. System architecture, product UX, and live Flutter interfaces are showcased here with full client permission.

01 / Product Philosophy

The High-Trust Hurdle in Domestic Services

In ride-hailing (e.g. Grab or Uber), passengers treat the driver as a fungible commodity: you request a ride, any nearby 4-star driver arrives, and you complete your journey. Home cleaning operates on a completely different psychological plane: a homeowner is granting an unfamiliar person access to their private sanctuary, family, and possessions.

In Singapore, homeowners are routinely trapped between two substandard models: exploitative domestic employment agencies requiring rigid multi-month contracts and high upfront agency fees, or unregulated WhatsApp message boards where availability is chaotic, cleaners cancel without notice, and quality is unpredictable.

I engineered Helpful (initially code-named InstantMaid) as a 3-sided marketplace that merges the velocity of on-demand ride dispatch with the rigor of verified domestic trust:

  • Transparent Tiered Pricing: Standardized, upfront hourly rates ($15/hr for standard maintenance cleaning, $20/hr for deep cleaning) without hidden agency commission markups.
  • Instant Postal Code Matching: Customers enter their 6-digit Singapore postal code to view live provider density, nearby helpers, and realistic arrival windows.
  • Two Distinct Operational Apps: Rather than forcing cleaners and homeowners into an awkward single app with role toggles, each audience has a bespoke native Flutter client designed around their specific daily workflow.
Helpful Customer App Discovery Home Screen
Exhibit 1.0 · Helpful customer discovery dashboard: service category tabs (Home Cleaning, Cooking, Eldercare, Babysitting), Singapore postal code resolution, and live available helper preview cards.
02 / Provider Trust Systems

De-Risking the Living Room: Verified Helper Credentials

Marketplace conversion hinges entirely on defusing customer anxiety before the first booking. If a customer cannot immediately verify a helper's background and experience, they abandon the funnel.

I architected a multidimensional provider trust system:

  • Identity & Background Verification: Cleaners must complete identity screening (NRIC/Work Permit verification) and background checks before they can go online. This earns a prominent verified badge on their public profile.
  • Operational Track Record: Profiles display verifiable platform metrics: completed job count (e.g. 312 Jobs done), years of experience, aggregate customer star rating, and real-time response rate (e.g. 98% response).
  • Language & Specialty Badging: In Singapore's multilingual society, communication barriers cause job friction. Provider cards explicitly display verified spoken languages (English, Tamil, Bahasa Malaysia, Mandarin) and specialized care competencies (medical assistance, companionship, deep sanitization).
Helpful Verified Provider Profile and Trust Metrics
Exhibit 2.0 · Verified helper profile: verified background-check badge, 4-metric reliability scorecard, specialized service tags, and trust indicators.
03 / Systems Architecture

The Flutter Monorepo with Shared Freezed Packages

The platform requires three distinct user interfaces:

  • Customer App (apps/user_app): Flutter iOS/Android client styled in clean Material 3 Indigo, optimized for browsing, scheduling, and live tracking.
  • Cleaner App (apps/provider_app): Flutter iOS/Android client styled in high-contrast Dark/Emerald Green, optimized for outdoor daylight legibility, one-tap online/offline toggling, and urgent dispatch acceptance.
  • Operations Portal (helpful-admin): Next.js web application for booking monitoring, provider onboarding, and geofenced dispatch oversight.

To eliminate model duplication across these apps, I structured the repository as a shared Dart workspace:

  • Shared Immutable Models (packages/maid_models): Built with Freezed and json_serializable. Models for Booking, Profile, Review, and ProviderJobCard are strictly immutable, generating type-safe copyWith methods and serialization logic. A single update immediately cascades across both mobile clients.
  • Shared API Layer (packages/maid_api): Pure Dart package encapsulating SupabaseService and Riverpod providers. Manages asynchronous data pipelines with AsyncValue and handles background connectivity recovery.
  • Database-Level Row Level Security (RLS): Because three apps and serverless edge functions share a single PostgreSQL database, access control cannot rely on client-side rules. Strict RLS policies at the PostgreSQL level ensure customers can only read their own bookings, cleaners can only access dispatched jobs, and sensitive contact information remains masked until booking confirmation.
Helpful Verified Reviews and Availability Matrix
Exhibit 3.0 · Social proof engine: 7-day recurring availability matrix, multi-language proficiencies, and verified customer review timeline.
04 / Geospatial Engine

PostGIS 15km Radial Matching & Singapore Geocoding

Effective dispatch requires spatial precision. Matching a homeowner in Jurong West with a cleaner in Changi wastes transit time and triggers cancellations.

I engineered a localized spatial dispatch pipeline tailored to Singapore:

  • OneMap Singapore Postal Resolution: Built direct integration with the Singapore Land Authority's official OneMap API. Entering a 6-digit postal code (e.g. 238823 for Orchard Road) immediately resolves building coordinates, block numbers, and street names without requiring messy freeform address typing.
  • PostGIS Radial Matching: Provider locations are stored as PostgreSQL geography(Point, 4326) coordinates. The custom RPC find_nearest_cleaners() uses spatial index queries (ST_DWithin) to calculate exact linear distance, identifying all vetted, online providers within a 15-kilometer radius.
  • OpenRouteService Real-Time Driving ETAs: While PostGIS handles radial filtering, actual driving times on Singapore expressways (PIE, AYE, CTE) dictate real arrival estimates. OpenRouteService computes live driving durations so homeowners see realistic arrival windows (e.g. "Arrives in ~15 min").
Helpful Postal Code Resolution and Duration Selector
Exhibit 4.0 · Location resolution interface: OneMap Singapore postal code geocoding pin on Orchard Road, unit/block address fields, and interactive duration selector.
05 / State Machine & Ergonomics

Atomic Serverless Dispatch & Slide-to-Confirm Ergonomics

The booking lifecycle is governed by an explicit 9-state finite state machine:

draft → pending_dispatch → searching → confirmed → in_progress → completed [or: cancelled / rejected]

In two-sided dispatch platforms, client-side race conditions are lethal: if two cleaners tap "Accept" simultaneously, both arrive at the customer's doorstep.

  • Server-Side Dispatch Orchestration: When payment authorization succeeds, the client does not query cleaners. Instead, a Supabase Deno Edge Function (dispatch-booking) triggers. It queries find_nearest_cleaners(), inserts atomic records into dispatch_requests, and broadcasts an alert overlay to cleaners via Supabase Realtime channels.
  • Atomic First-to-Accept Locking: When a cleaner accepts, an atomic PostgreSQL transaction binds the cleaner to the booking and immediately cancels all other outstanding dispatch requests, preventing duplicate assignments.
  • Slide-to-Confirm Ergonomics: Accidental taps on a "Book Now" button trigger unwanted dispatch fees and driver frustration. Borrowing from mission-critical transport UX, I designed a swipeable "Slide to confirm" slider widget that requires deliberate physical intent to lock in the reservation.
  • Stripe Payment Authorization: Customers are never charged upfront for unfulfilled jobs. A Deno Edge Function creates a Stripe PaymentIntent with manual capture; the card is only captured when the cleaner taps "Job Complete" on-site.
Helpful Booking Details and Slide to Confirm Interaction
Exhibit 5.0 · Booking checkout sheet: live helper arrival countdown, transparent $45 pricing total (3 hrs × $15/hr), and the swipeable "Slide to confirm" checkout slider.
06 / Outcomes & Takeaways

Key Learnings from Marketplace Systems Engineering

  • Domain nuances dictate interaction patterns: Ride-hailing prioritizes instant 3-minute pickups with random drivers; domestic services prioritize scheduling flexibility, background verification, and language compatibility. Tailoring the UI around trust metrics eliminated the primary point of customer friction.
  • Enforce security at the database boundary: Relying on mobile app code to guard customer addresses and cleaner phone numbers invites data breaches. Enforcing Row Level Security (RLS) directly in PostgreSQL ensures that even if client code is reverse-engineered, user data remains untouchable.
  • Monorepos eliminate sync drift: Maintaining separate repos for customer and provider apps inevitably leads to broken schemas and out-of-sync API contracts. A single Flutter monorepo with Freezed code generation ensures compile-time safety across all clients.