R
0

Property Marketplace Platform

In Development

GharBazaar

RoleIndependent Project — Full Stack Product EngineerPeriod2025 — PresentLive Site Source

Deployed and running — pre-launch, so the catalogue is still small

Status Note: The platform is deployed and running at gharbazaar-mu.vercel.app, with the database connected and every marketplace route live. It is pre-launch rather than finished: seller onboarding is still in progress, so the catalogue holds only a few listings and no student listings yet. The build-status table below marks exactly what is complete.

Next.js 16React 19TypeScriptTailwind CSS v4shadcn/uiBase UISupabasePostgreSQLPostGISGoogle MapsVitestPlaywrightGitHub ActionsVercel
01

Overview

Project Overview

GharBazaar is a property marketplace built around a single idea: students looking for housing care about distance to their campus, not postal boundaries. Properties are linked to nearby universities with distances computed in the database using PostGIS, so a student picks their university and sees genuinely nearby flats, PGs and hostels ranked by real distance. Around that sits a full marketplace — tiered identity verification, listing moderation, lead capture with contact gating, in-app messaging, subscriptions and billing.


02

Screenshots

What it looks like

Captured from the running product — not mockups. You can check any of it against the live site — deployed and running — pre-launch, so the catalogue is still small.

GharBazaar homepage with a property search bar offering buy, rent, commercial and plot modes, plus filters for property type, budget and BHK
The live marketplace. Search is faceted across purpose, property type, budget and configuration before a single result is rendered.
Student housing page listing fifteen universities and coaching hubs to browse by, with gender filters and a note that campus distance is auto-computed
The student-housing entry point, with fifteen institutions to browse. The page states the architecture in its own words — campus distance is auto-computed, never manually entered — which is the PostGIS trigger doing the work. The empty state is real: seller onboarding is still in progress.
Property listings page for Mathura showing a verified 3 BHK apartment with price, area and configuration, alongside BHK filters and locality navigation
City listings with configuration filters and locality navigation. Every listing shown has passed admin approval before going live.

On a phone

GharBazaar homepage rendered on a phone viewport
Mobile home — students search for housing on phones, so this is the primary surface.
Not shown here (8)
  • University selection to distance-ranked resultsNo property is linked to a university yet — the listings are in Mathura, the universities in NCR, so there is no real distance ranking to show
  • Map view with pins near a campusNeeds listings with campus links to be meaningful
  • Owner listing creation and university taggingRequires a seller account; not captured to avoid creating listings on the live site
  • Three-tier KYC submission and reviewWould mean submitting real identity documents
  • Leads dashboard showing contact-reveal stateRequires a seller account with real leads
  • In-app messaging threadWould mean sending real messages between real accounts
  • Admin moderation queueRequires an admin account
  • CI run showing the pipeline greenThe lint fix is committed locally but not yet pushed, so the remote pipeline is still red

03

Problem

The Problem

A student moving to a new city has a housing search that no general property portal serves. The big portals index by locality and price, but a student's real constraint is how far a place is from their campus — and locality names carry no distance information. The informal alternatives, campus WhatsApp groups and noticeboards, have no verification at all, which is exactly where students get scammed. Property owners near universities have the opposite problem: no targeted way to reach student tenants. GharBazaar makes campus proximity a first-class, computed property of every listing, and puts a verification system behind the people posting them.


04

Role

What I Built

  • ↗Designed the complete product architecture and the 58-table PostgreSQL schema
  • ↗Modelled property-to-university proximity with PostGIS, computed by database triggers
  • ↗Wrote 128 Row-Level Security policies covering every table in the schema
  • ↗Built the three-tier KYC verification flow with private document storage
  • ↗Built the property lifecycle: submission, admin approval, publication and automated expiry
  • ↗Built the lead system with contact-reveal gating to protect student privacy
  • ↗Implemented a transactional outbox for notifications, drained by a scheduled job
  • ↗Built saved searches with a nightly alert-matching job
  • ↗Built the multi-role architecture spanning students, sellers, property dealers and admins
  • ↗Built the admin surface: moderation queue, KYC review, reports, strikes and support tickets
  • ↗Wrote 196 Vitest unit tests and 23 Playwright end-to-end specs, wired into a GitHub Actions pipeline

05

Architecture

System Architecture

GharBazaar is a Next.js 16 App Router application over Supabase PostgreSQL. Business logic lives in feature modules with server-only data access, exposed through 59 route handlers under /api/v1. Authorization is enforced primarily in the database: 128 Row-Level Security policies cover all 58 tables, so a compromised or buggy route cannot read data its caller shouldn't see. Geospatial relationships are computed by PostGIS inside database triggers rather than in application code, which keeps distances correct no matter which code path writes a property.

Students

Select a university → browse nearby verified listings ranked by real distance

Sellers & dealers

List properties → complete KYC → manage leads and appointments

Admins

Moderate listings, review KYC, resolve reports, issue strikes, handle support

Frontend

Next.js 16 App Router · React 19 · Tailwind v4 · shadcn · Base UI

API

59 route handlers under /api/v1 over server-only feature modules

Database

Supabase PostgreSQL — 58 tables, 67 indexes, 16 functions, 21 triggers

Authorization

128 Row-Level Security policies — the database is the final authority

Geospatial

PostGIS geography(point) with st_distance computed in triggers

Scheduled jobs

Listing expiry · saved-search alert matching · notification outbox drain

Key Architectural Decisions

  • ·University proximity as computed data, not user input — distance is written by a trigger and cannot be inflated by a seller
  • ·Row-Level Security as the primary authorization boundary rather than route-level checks alone
  • ·Tiered verification (identity → property → trusted) instead of a single binary verified flag
  • ·Transactional outbox for notifications so a delivery failure never rolls back the business action
  • ·Contact details revealed only after an explicit lead, keeping student contact data out of listing pages
  • ·Soft delete enforced at the database — a property cannot be hard-deleted out from under its audit trail

06

Build Status

What's Built vs In Progress

This project is in active development. The table below shows the current implementation status of each system area.

Database schema (58 tables, 67 indexes)
Completed
Row-Level Security (128 policies)
Completed
PostGIS proximity model
Completed
University ↔ property association
Completed
Multi-role architecture
Completed
Property listing lifecycle
Completed
Three-tier KYC verification
Completed
Lead capture & contact gating
Completed
In-app messaging
Completed
Notification outbox & cron drain
Completed
Saved searches & alert matcher
Completed
Search & filtering
Completed
Subscriptions, payments & invoices
Completed
Moderation, strikes & audit logs
Completed
Admin surface (19 endpoints)
Completed
Unit tests (196, passing)
Completed
CI pipeline
In Development
SEO (sitemaps, structured data)
Completed
Landing site deployment
Completed
Marketplace production deployment
Completed

07

Technical Breakdown

System-by-System Engineering

A detailed look at each layer and subsystem — decisions made, how it was built, and why it was built that way.

Geospatial proximity model

Completed

The feature the whole product rests on. Properties and universities both carry a PostGIS geography point, and the distance between a linked pair is computed by a database trigger — never supplied by a user.

  • ·PostGIS extension enabled; properties and universities both store geography(point) locations
  • ·property_universities join table with a composite primary key and a computed_distance_m column
  • ·A trigger computes st_distance on link creation; a second trigger recomputes every linked distance when a property's pin moves
  • ·Distance is explicitly never user input — a seller cannot claim to be closer to a campus than they are
  • ·Composite index on (university_id, computed_distance_m) so 'nearest first' is an index scan
  • ·Google Maps integration for pin placement and map-based browsing

Database & authorization

Completed

A 58-table schema where authorization is a database concern. Row-Level Security covers every table, and the migration history shows security being tightened deliberately over time.

  • ·58 tables, 67 indexes, 16 functions and 21 triggers across 8 migrations
  • ·128 Row-Level Security policies, with RLS enabled on all 58 tables
  • ·Dedicated hardening migrations for RLS gaps, financial record protection and view-counter abuse
  • ·Hard deletion of properties blocked at the database, preserving audit history
  • ·Separate audit_logs and activity_logs tables for administrative and user actions
  • ·Security-definer functions used deliberately and scoped with an explicit search_path

Identity & verification

Completed

Trust is the core problem in a housing marketplace. Verification is tiered rather than binary, so the platform can distinguish a verified identity from a verified property.

  • ·Three verification levels: identity, property, and trusted
  • ·Verification request states: pending, approved, rejected, expired
  • ·KYC documents stored in a private bucket with MIME-type and file-size restrictions
  • ·Admin endpoints to verify or reject a submission
  • ·Property images kept in a separate public bucket — private documents never share a bucket with public assets

Listing lifecycle

Completed

Properties move through submission, moderation and publication, and expire automatically so the catalogue does not fill with stale listings.

  • ·Admin approve and reject endpoints backing a moderation queue
  • ·Separate publish action, so approval and going live are distinct steps
  • ·Automated daily expiry job for listings past their active window
  • ·Price history retained per property
  • ·Stable slug management so a renamed listing keeps a working URL
  • ·Amenities, property types, room types and areas maintained as seeded reference data

Leads & communication

Completed

Student contact details are never exposed on a listing. A lead is an explicit act, and only then does contact information become visible.

  • ·Inquiry model capturing student interest against a property
  • ·Contact reveals recorded separately, so who saw which details is auditable
  • ·In-app conversations and messages between parties
  • ·Visit appointment scheduling
  • ·Lead export endpoint for sellers working their pipeline outside the platform
  • ·Engagement events captured across eight types: view, gallery open, reveal, WhatsApp click, call click, share, favourite and visit request

Notifications

Completed

Notifications use a transactional outbox. A notification is written in the same transaction as the action that caused it, then delivered asynchronously by a scheduled job.

  • ·notification_outbox table written as part of the originating transaction
  • ·A scheduled job drains the outbox on a daily cadence
  • ·Delivery failure cannot roll back or lose the business action that triggered it
  • ·Per-user notification feed with read-state tracking

Search & discovery

Completed

Search combines university proximity with the ordinary filters a renter needs, and remembers searches so students hear about new matches.

  • ·Dedicated search feature module with a student-housing entry path
  • ·Filtering across property type, room type, amenities and area
  • ·Saved searches persisted per user
  • ·A nightly alert-matching job pairs new listings against saved searches
  • ·Search events recorded for relevance and zero-result analysis
  • ·Favourites, comparison sets and recently-viewed lists per user

Monetization

Completed

Sellers and dealers subscribe to plans; the platform tracks payments, issues invoices and consumes provider webhooks.

  • ·Subscription plans and per-user subscriptions
  • ·Payment records with invoices
  • ·Webhook event table for reconciling provider callbacks
  • ·A dedicated migration protecting financial records from modification

Trust, safety & admin

Completed

A marketplace needs enforcement as much as features. Reports, strikes and blocks are first-class, and admins have a purpose-built surface.

  • ·Property reports with resolve and dismiss actions
  • ·Progressive enforcement via user strikes and account deactivation
  • ·User blocks and blocked identifiers to stop repeat abuse
  • ·Support ticket system with threaded admin replies and status transitions
  • ·Reference-data seeding endpoints for cities, areas, universities, amenities and property types
  • ·19 dedicated admin endpoints out of 59 total route handlers

Quality & delivery

Completed

The project has a unit test suite and a CI pipeline wired to run it. The tests pass locally; the pipeline itself is currently red at the lint step, so the later stages have not yet run green.

  • ·196 Vitest unit tests covering schemas, storage, formatting and API invariants — all passing locally
  • ·23 Playwright end-to-end specs — 10 run against the deployed app; the other 13 self-skip without service-role credentials, so they never write to live data
  • ·Coverage reporting configured
  • ·GitHub Actions pipeline: install, lint, typecheck, unit tests, build, then end-to-end tests
  • ·The lint failures that were blocking CI are fixed; the change is committed but not yet pushed, so the remote pipeline is still red
  • ·SEO infrastructure with robots, dynamic sitemaps and structured data
  • ·Vercel Analytics and Speed Insights instrumented
  • ·Image upload pipeline with client-side compression, cropping and a media job queue

08

Challenges

Engineering Challenges & Solutions

Challenge

Making campus distance a fact rather than a claim

The entire product promise is that a listing really is close to a campus. If a seller types in the distance, or the application computes it on write, the number drifts the moment a property's pin is corrected — and a wrong distance is worse than none, because students plan around it.

Solution

Distance is derived data owned by the database. Both properties and universities store a PostGIS geography point, and a trigger computes st_distance whenever a property-university link is created. A second trigger recomputes every affected link when a property's location changes. The column is annotated in the schema as always trigger-computed and never user input, and it is indexed alongside university id so proximity ordering stays cheap.

Challenge

Authorization across four roles and 58 tables

Students, sellers, dealers and admins have overlapping but distinct access to the same tables. Enforcing that only in route handlers means every new endpoint is a fresh chance to leak a phone number or someone else's KYC document.

Solution

Authorization was pushed into the database. All 58 tables have Row-Level Security enabled, covered by 128 policies, so access rules live next to the data rather than being re-implemented per route. The migration history includes dedicated hardening passes — closing RLS gaps, protecting financial records and restricting an abusable view-counter function — which is how those rules got tightened without guesswork.

Challenge

Notifications that cannot silently disappear

Sending a notification inline with the action that triggers it couples them: if the delivery call fails or times out, either the user's action fails or the notification is lost. Neither is acceptable when the notification is 'your listing was approved'.

Solution

Notifications are written to an outbox table inside the same transaction as the originating action, then delivered asynchronously by a scheduled job that drains the outbox. If the business action commits, the notification is durably queued; if delivery fails, it is retried without ever having risked the action itself.

Challenge

Protecting student contact details from cold outreach

If contact details sit on the listing page, students get called by every owner who scrapes the site, and the platform loses both trust and any ability to measure real intent.

Solution

Listings expose property information only. Contact details become available through an explicit inquiry, and each reveal is recorded in its own table so it is auditable and countable. That keeps student data out of public pages, gives sellers higher-intent leads, and turns 'reveal' into a measurable funnel step alongside views and gallery opens.


09

Decisions

Technical Decisions

Key technology and architecture choices — what was chosen, what was considered, and why.

Decision — Where geospatial distance is computed

Chosen

PostGIS in database triggers

Considered

Application-side distance calculation on read

Reason

Computing on read means every query recalculates, and every code path that writes a location has to remember to update. A trigger makes distance a guaranteed property of the data and lets it be indexed, so nearest-first ordering is an index scan rather than a sort over computed values.

Decision — Primary authorization boundary

Chosen

Row-Level Security in PostgreSQL

Considered

Route-level permission checks only

Reason

With 59 route handlers and four roles, per-route checks scale badly and fail open when one is forgotten. RLS puts the rule next to the data, so a missed check in a handler results in an empty result set rather than someone else's KYC documents.

Decision — Verification model

Chosen

Three tiers — identity, property, trusted

Considered

A single verified boolean

Reason

A binary flag cannot express the difference between 'we know who this person is' and 'we have confirmed they control this property'. Tiering lets the platform surface an honest trust signal to students and gives sellers a reason to complete each step.

Decision — Notification delivery

Chosen

Transactional outbox drained by a scheduled job

Considered

Sending inline with the triggering action

Reason

Inline delivery couples a business transaction to a third-party call. The outbox pattern decouples them — the notification is committed atomically with the action and delivered independently, so a provider outage delays notifications instead of failing approvals.

Decision — Schema management

Chosen

Versioned SQL migrations on Supabase

Considered

An ORM-managed schema

Reason

The schema leans on PostgreSQL features an ORM abstracts away or cannot express — PostGIS geography columns, Row-Level Security policies, security-definer functions and triggers. Writing SQL directly keeps those first-class and keeps every policy reviewable in the migration history.


10

Deployment

Deployment & Infrastructure

The landing site is live at gharbazaar.in. The marketplace application itself is built and CI-verified but has no production deployment yet — that is the current focus.

  • ·Landing site deployed and live at gharbazaar.in
  • ·Deployed on Vercel with the database connected; seller onboarding is the remaining pre-launch work
  • ·Deployment configuration committed, including three scheduled jobs for listing expiry, alert matching and outbox draining
  • ·GitHub Actions runs lint, typecheck, unit tests, a production build and end-to-end tests on every push — the pipeline is currently failing at lint
  • ·Supabase provides managed PostgreSQL, authentication and storage; migrations are versioned in the repository
  • ·Vercel Analytics and Speed Insights instrumented ahead of launch

11

Learnings

What I Learned

Derived data belongs to the database. Making campus distance a trigger-computed, indexed column removed a whole class of bugs that application-side calculation would have kept reintroducing.
Row-Level Security changes the failure mode of an authorization mistake. With 128 policies covering every table, a forgotten filter returns nothing instead of returning someone else's data — that difference matters more as the surface grows.
Trust is a product feature in a marketplace, not a compliance checkbox. Tiered verification, contact gating, strikes and audit logs did more for the product's viability than any additional search filter would have.
The transactional outbox is worth the extra table. Decoupling notification delivery from the transaction that triggers it means a provider outage never costs a user their approval.
Writing tests alongside the features made the schema better. Several Row-Level Security gaps surfaced because a test asserted a user could not read something and it turned out they could.

12

Next Steps

What I Would Build Next

  • →Get the CI pipeline green — it fails at lint, which blocks the test and build stages
  • →Onboard sellers so the catalogue and student listings fill out
  • →Publish seeded demo accounts for each role so the platform can be explored without signing up
  • →Full-text and typo-tolerant search across listings
  • →Native mobile experience — student housing search is overwhelmingly mobile
  • →Expand end-to-end coverage across the seller and admin journeys
  • →Landlord analytics dashboard built on the existing listing-event data