"case_study": "propset"
Reading a property market like a stock chart
A Dubai real-estate marketplace with an investment dashboard that surfaces technical analysis — moving averages, RSI, price-per-sqft — over property transaction history.
"role"
Full-stack development — Angular client and NestJS REST API, integrating an Apollo GraphQL analytics service
"stack": [7]
- Angular
- NestJS
- Apollo GraphQL
- Prisma
- PostgreSQL
- Chart.js
- Kinde
The problem
Property portals show photos and asking prices. What an investor actually needs is price behavior: what has this building, this area, this unit type really transacted at, and which way is it moving? In Dubai — a market with unusually rich public transaction data — that analysis mostly lives in analysts' spreadsheets.
Propset's bet: treat property transactions as market data and give buyers the kind of chart a trader would recognize.
What was built
- An analytics dashboard where users filter by unit type, area, building, or project and get a transaction table plus an interactive chart.
- The chart surfaces technical indicators over property prices: SMA9 and SMA20 moving averages, an RSI, a bull/bear differential the client derives from them, and price-per-square-foot over selectable ranges from one month to all time.
- A listings marketplace with Dubai regulatory records — permit numbers, DEWA numbers, broker and office registration — across property types from apartments to full floors.
- Role-based access for admins, realtors, and merchants, gated by Kinde authentication.
Architecture decisions
- Angular Material client talking Apollo GraphQL for the data-heavy dashboard views, with Chart.js rendering the indicator overlays.
- A NestJS backend on Prisma/PostgreSQL serving Swagger-documented REST endpoints for the listings domain, while the data-heavy analytics run against a separate Apollo GraphQL service — REST where the contract is fixed, GraphQL where the client composes queries.
- Indicator math runs over transaction series server-side, so the client renders results instead of recomputing them.