Skip to main content
Case study · Real estate

Bhatia Builders a system.

A Mumbai developer had a website people read once and forgot. Now buyers walk through the tower before it is built, every enquiry lands where the team can act on it, and the numbers are on one screen every morning.

0.7MB
the whole tower, livemodel + city light, streamed after the page paints
3
apps, one systemthe site · the admin · the engine underneath
0
duplicate leads, by designthe same enquiry can never land twice
8
checks on every enquiryfrom the tap on the phone to the database
Read in sixty seconds
01What they had
A brochure site. Enquiries scattered across inboxes. No way to change a word without a developer.
02What we built
A real-time 3D site buyers explore on their phones, an admin the team edits themselves, and a lead pipeline that never drops or doubles an enquiry.
03What it does now
Sales opens one inbox. Marketing opens one dashboard. Both read the same numbers.
01The problem

Scrolled past, then forgotten

Bhatia Builders sells homes in a tower that does not exist yet. Their site showed flat renders, buyers closed the tab, and the enquiries that did arrive went to three different inboxes. Nobody could say which ad brought which buyer, and changing a price on the site meant calling a developer.

So we did not redesign the site. We replaced what was underneath it.

What changed
  • 01Flat renders on a brochure pageA tower you walk through on your phone
  • 02Every edit went through a developerThe team edits the site itself
  • 03Enquiries lost across inboxesOne inbox, no lead ever dropped
  • 04No idea what was workingThe numbers, every morning
02Real-time 3D

Walk through it before it is built

This is the real Esspee Square tower from the project, drawn live in your browser as you scroll, not a video. It is the moment a buyer stops scrolling, and it runs on the phones they actually carry.

Esspee Square: rendered tower from the Bhatia Builders 3D marketing site
  • Loads while you readThe model and the city light stream in after the page has painted: the tower is never the reason the page is slow.
  • Steady on a mid-range phoneRendering is capped at 1.25× pixel density and the GPU rests whenever nothing moves.
  • Smaller than one photoAbout 0.7 MB for the tower and its environment: less than a single hero image on most sites.
  • Always something to seeOn reduced-motion settings or a weak connection, a still render takes its place. No blank box, ever.
03The team's view

What the team opens every morning

Two screens, one truth. Sales reads the CRM: every enquiry that exists right now. Marketing reads the analytics: how visitors behaved. Both are counted from the same rows, so the numbers never disagree.

Bhatia Builders sales dashboard: lead inbox with the new / contacted / scheduled / closed pipeline
Sales · 9 a.m.

Every enquiry, one inbox

Leads, site enquiries and subscribers in a single list, sorted hot, warm and cold. The team knows who to call first before the first coffee.

  • Unified inbox
  • Hot / warm / cold pipeline
  • Stats from one aggregation query
Bhatia Builders marketing dashboard: headline GA4 metrics and conversion goals
Marketing · 9 a.m.

Where the buyers came from

Traffic, sources, devices and the full visitor-to-closed funnel, reconciled against the real enquiries in the CRM, so a click that never became a lead cannot flatter the report.

  • GA4 Data API
  • ~13 reports, fetched in parallel
  • Reconciled against the CRM
Bhatia Builders marketing dashboard: traffic over time, acquisition channels, and the visitor-to-closed funnel
Traffic over time, where it came from, and the whole visitor → closed funnel: one screen.
04Under the hood

For the technical reader

Three apps share one database and one set of conventions. The decision that ties them together: the public site never fetches content at runtime. An edit becomes a build, and the live site ships static data.

How an edit reaches the site
  1. Editor saves
  2. MongoDB
  3. Sync engine
  4. Seed files
  5. Vercel build
  6. Live site

An edit is written to the database, baked into version-controlled seed files, and committed, which triggers a fresh build. Zero network latency on the public site, nothing to break mid-scroll, and every change in git history.

  • React 19
  • React Three Fiber
  • GSAP + Lenis
  • Express 5
  • MongoDB Atlas
  • Cloudflare R2
  • GA4 Data API
  • Vercel
The lead pipeline

Built to never lose a lead

One rule shaped the path from the form to the dashboard: never lose an enquiry, never create a duplicate. Eight stages enforce it, from the browser to the database.

  1. Written to a local queue with an idempotency key before the request leaves the browser: it survives a tab crash or a dropped network.

  2. A GA4 generate_lead event fires: the capture stage of the tracked journey.

  3. POSTed with the idempotency key. Exponential backoff; 4xx is terminal, 5xx and network errors retry.

  4. CORS whitelist, Helmet headers, global plus per-IP rate limits, and a clean 503 if the database is down.

  5. A Zod schema checks name, email, phone, project, date and time. A failure is a terminal 400.

  6. A replayed key returns the existing lead; a duplicate on email or phone for a project returns 409, backed by a partial unique index.

  7. Stored as source mvp-web, status new, auto-promoted to hot when the visitor leaves a real message.

  8. It lands in the CRM inbox and the analytics funnel at the same time.

Spec sheet
0
runtime content fetches on the public site
1.25×
device-pixel-ratio cap on the live scene
Demand
frameloop: the GPU idles when nothing moves
0.7 MB
model + HDR environment, streamed post-paint (approx.)
1
database, three apps, one convention set
Static
render fallback on reduced-motion and slow links
Security posture

The guards behind that pipeline, and the rest of the platform.

Authentication
A signed JWT in an HttpOnly cookie: no token in localStorage, so no XSS theft surface. Failed logins are rate-limited.
Authorization
Role-based access across four roles: mvp, superuser, editor, viewer.
Input safety
Zod on every write; Mongo-operator injection blocked by regex-escaping and scalar coercion; pagination and sort fields clamped to a whitelist.
Resilience
Serverless-aware DB pooling with a 503 gate, partial unique indexes on public forms, an audit log, and revertible sync snapshots.
Privacy
noindex on both apps; the admin adds a strict CSP and frame-busting.
Start a project

Bhatia Builders is the first Merse build.

Tell us what your site is failing to do. If it deserves the same (the craft on top and the system underneath), we would like to build it.

0/10 min characters

No spam. Your details stay between us: privacy policy.