What we solved
Property finders usually force users into fixed city or postcode searches, and most contact flows dead-end at a form the agent never sees. RHEEL - “your all-in-one real estate solution” - needed radius-based search in miles around any Google Places location, rich listings with photos, floor plans, and virtual tours, and a contact path that reaches the agent directly on WhatsApp or email. The operator also needed an admin web panel - users, agents, banners, inquiries - without a separate CMS.
The system at a glance
A Flutter 3.13.0 codebase shipping the consumer mobile app (iOS + Android) and the admin web panel from the same repository. Supabase runs the backend (Auth + Postgres + Storage + Edge Functions). Google Places provides the location search. Radius queries run in plain SQL against lat/lon columns - no PostGIS, no custom geo backend. Currently at v2.11 on the App Store, with v2.0 having shipped a major database migration and complete interface redesign.
What the user experiences
Buyer / renter
- Open the app. Browse or log in.
- Search by location (Google Places autocomplete), then set a radius - 5, 10, 25 miles.
- Filter by price range, bedrooms, property type, date added, furnished type, let type, must-haves.
- Open a listing: photos, floor plans, videos, virtual tours, aerial maps.
- Save listings. Contact the agent via WhatsApp or email directly - no web form bounce.
- Track your sent inquiries with status.
- Take advantage of discounted agency fees through the app.
Operator (admin web)
- Sign in on a desktop. Same Flutter codebase, web build.
- Manage users, properties, agent companies, homepage banners.
- Triage inquiries - mark resolved, search history.
How we built the pieces
Radius-in-miles - plain Postgres, no PostGIS
Each property row carries lat and lon columns. The radius query runs the Haversine formula in SQL against those columns with a bounding-box pre-filter (so Postgres uses the index before the expensive math). Works at our scale; we swap for PostGIS if we ever outgrow it, not before.
Consumer + admin - one Flutter codebase, two builds
The consumer app ships as iOS + Android. The admin web panel ships as flutter build web. Same models, same API client, same auth. A change to the property schema rolls out to both surfaces in one PR.
WhatsApp + email contact - direct, not brokered
The “contact agent” buttons open WhatsApp with a pre-filled message or the email client with subject and body. The inquiry also logs server-side for the admin to track. The buyer reaches the agent immediately; the operator still has the audit trail.
Google Places - Edge Function proxy for web
Flutter web hit CORS issues talking to Google Places directly. We proxy through a Supabase Edge Function for the web build; the mobile app calls Google Places directly with its own API key. Same UX, different path under the hood.
Featured properties - admin-managed
Banners and featured listings are managed from the admin web, with upload to Supabase Storage. Homepage carousel reads from a featured table flag; no code deploy to promote a listing.
The radius math plus the admin panel shipping together
Two things make RHEEL ship-worthy: the radius math is honest (bounding-box plus Haversine, not fake), and the admin panel shipped in the same release as the consumer app. Most property apps skip the admin and tell the client “we’ll do it later.” That is how they die.
Results
- iOS + Android + admin web all live from one codebase.
- App Store v2.11 (May 2025 update) with continuous iteration since launch.
- Radius-in-miles search working across any Google Places location.
- WhatsApp + email direct-contact flow with server-side logging.
- Supabase handling auth, data, and storage with no custom backend infrastructure.
What an engineering team should take from this
If you are building any geo-search app at early scale:
- Start with Haversine + bounding box in plain Postgres. Don’t over-engineer with PostGIS until the volume demands it.
- Supabase covers the backend for small and mid teams. Auth, Postgres, Storage, Edge Functions - skip the “build a REST API” phase.
- Ship the admin panel in the same codebase as the consumer app. Flutter web + Flutter mobile share models, API clients, and validation - two teams collapses to one.
Tech stack
- Mobile + web admin: Flutter 3.13.0 (single codebase)
- Backend: Supabase (managed Postgres + Auth + Storage + Edge Functions)
- Location: Google Places API, lat/long radius algorithm
- Contact: deep links to WhatsApp + email
Screens
