The hardest project. Multiple properties, multiple units per property, tenants with lease terms, recurring rent generation, payment tracking, maintenance workflows, and financial analytics per property and per unit. TypeScript is essential — the relationships between properties, units, leases, tenants, payments, and maintenance requests are deep enough that untyped code will break constantly. This is your portfolio centerpiece.
What to Build
- Roles: Landlord/Admin (full access), Property Manager (assigned properties only), Tenant (their unit only)
- Properties: name, address, type (apartment/condo/house), number of units, photos, documents
- Units within properties: unit number, floor, bedrooms, bathrooms, area (sqm), monthly rate, status (Vacant/Occupied/Under Maintenance)
- Tenant management: personal info, emergency contact, move-in date, lease terms, documents
- Lease management: unit, tenant, start date, end date, monthly rate, security deposit, terms. Status: Active, Expiring Soon, Expired, Terminated. Auto-flag leases expiring within 30 days.
- Rent generation: auto-generate monthly rent invoices for all active leases. Track status: Pending, Paid, Partial, Overdue. Support partial payments.
- Payment recording: amount, date, method (cash/bank transfer/GCash), reference number, receipt generation
- Maintenance requests: tenant submits request (description, category, urgency, photos). Landlord assigns priority and status: Open → In Progress → Completed. Cost tracking per request.
- Tenant portal: see lease details, payment history, submit maintenance requests, view announcements
- Dashboard: total revenue vs. expenses per property, occupancy rate, overdue payments, upcoming lease expirations, pending maintenance, net income per unit
- Financial reports: income statement per property, per unit. Filter by date range. Export-ready views.
Phases
1Data model with TypeScript interfaces: User (with roles), Property, Unit, Tenant, Lease, RentInvoice, Payment, MaintenanceRequest. Define types first. The relationship chain is deep: Property → Unit → Lease → Tenant, and Property → Unit → MaintenanceRequest. Think about how rent invoices are generated and linked.
2Backend: Property/Unit CRUD, tenant onboarding, lease creation with validation (can't lease an occupied unit), rent invoice auto-generation, payment processing with partial payment support, maintenance request workflow, financial aggregation endpoints. Fully typed.
3Landlord frontend: property overview, unit grid per property, lease management, rent collection tracker, maintenance queue, financial dashboard with charts.
4Tenant portal: lease info, payment history, submit/track maintenance requests.
5Tests: rent calculation edge cases (partial payments, mid-month move-ins), lease validation (overlapping leases on same unit), financial report accuracy. Deploy.
Decisions You'll Make
How to model the Property → Unit → Lease → Tenant chain (all separate collections with references? how deep do you populate?). How to handle rent generation (cron-like job on server start? generate on dashboard load? pre-generate for the month?). How to prevent leasing an already-occupied unit (validation + atomic check). How to calculate net income per unit (rent payments minus maintenance costs — aggregation pipeline). How to handle partial payments (a tenant pays 8,000 of 12,000 — how is that modeled?). How to type the financial calculations so rounding errors are impossible. How to share types between the landlord frontend and tenant portal.
Stack
TypeScript
React
Express or Apollo
MongoDB
Mongoose
JWT
bcrypt
React Router
React Query
Redux Toolkit
useReducer
useContext
Custom Hooks
Vitest
SuperTest
Playwright
React Testing Library
Material UI
ESLint