Nestar
A full-stack real-estate marketplace where users browse and like listings, agents publish properties, and admins moderate — a NestJS GraphQL API with MongoDB aggregation, scheduled ranking jobs, and real-time chat behind a multilingual Next.js front end.
The problem
Real-estate marketplaces serve three very different user types from one system — buyers who browse and save, agents who publish, and admins who moderate — while keeping discovery fast over large, frequently-updated datasets. Done naively this means slow listing pages (N+1 joins, separate count queries), stale or gameable rankings, and brittle authorization where one endpoint must behave differently for anonymous, member, agent and admin callers.
The solution
A clean NestJS monorepo that separates the request-serving GraphQL API from a scheduled batch worker. Heavy reads are aggregation pipelines using a single facet (page + total in one round-trip), lookup joins, and viewer-aware sub-pipelines that compute per-user flags inside the database. Engagement counters are denormalized and updated atomically. A nightly worker recomputes weighted ranking scores offline. Authorization is layered through custom guards and a role enum, with an optional-auth guard for guest/member parity, and a JWT WebSocket gateway adds live chat — tied together by an SSR Apollo Next.js front end with faceted search and full i18n.
Overview
Nestar is a production-grade, two-tier real-estate marketplace. The backend is a NestJS monorepo split into two deployable apps: a code-first GraphQL (Apollo) API and a standalone scheduled-jobs worker. The API is organized into eight cohesive domain components — member, property, board-article, comment, like, follow, view and auth — each with its own resolver, service, DTOs and Mongoose schema. Authentication is JWT-based with bcrypt hashing, governed by a three-tier role model (USER / AGENT / ADMIN) enforced through custom guards, plus an optional-auth guard so the same listing queries serve both anonymous and logged-in users.
The data layer leans on MongoDB aggregation pipelines rather than naive queries. List endpoints use a single facet stage to return a paginated page plus its total count in one round-trip, lookup joins to hydrate author data, and viewer-aware sub-pipelines that compute per-user liked/followed flags inline. Engagement uses toggle semantics: a single like mutation creates or deletes the like document and atomically increments/decrements denormalized counters, keeping read paths fast, while a dedicated View collection deduplicates view tracking.
The batch worker runs nightly cron jobs that recompute weighted ranking scores so Top Properties and Top Agents stay fresh without burdening live traffic. A NestJS WebSocket gateway powers a live chat room with JWT-authenticated connections, presence broadcasting and a rolling message buffer. The front end is a Next.js application using Material UI and SCSS, fully internationalized in English, Korean and Russian, with SSR Apollo, an isomorphic link that splits HTTP/upload from WebSocket subscriptions, faceted property search, agent and community sections, a personal my-page, and an admin moderation dashboard. Both tiers ship with Docker Compose and ran in production at nestar.uz.
Key features
- Code-first GraphQL API (NestJS + Apollo) with auto-generated schema, validation pipes and a global error formatter
- Three-tier RBAC (USER / AGENT / ADMIN) via custom guards, plus an optional-auth guard so the same queries serve guests and members
- Advanced MongoDB aggregation: facet pagination-with-count in one query, lookup relation hydration, and viewer-aware sub-pipelines for per-user liked/followed state
- Toggle-based likes/follows with atomically maintained denormalized counters and deduplicated view tracking
- Standalone batch worker running nightly cron jobs that recompute weighted ranking scores for top properties and top agents
- Real-time chat over a NestJS WebSocket gateway with JWT-authenticated connections, presence and a rolling message buffer
- Faceted property search: location, type, price/area/date ranges, rooms, beds, barter/rent flags and full-text title matching
- Secure image uploads via graphql-upload with size/count limits, MIME validation and UUID filenames
- Next.js front end with Apollo SSR, HTTP/WebSocket split link, token refresh, an admin moderation dashboard and i18n in English, Korean and Russian