← All projects
SoftwareReactNode.jsPostgreSQLSaaSIn Progress

Building Maintenance App — Multi-Tenant SaaS

A full-stack SaaS platform for HOA and property management. Tenants submit repair requests, managers assign work orders, and staff closes them out — all with role-based access and per-tenant data isolation.

February 28, 2026


Overview

Managing maintenance across multiple buildings is messy — requests get lost in emails, work orders have no paper trail, and when a management company changes, the building's history walks out the door with them. I built this platform to fix that.

The core idea is that records belong to the building, not the management company. Operators come and go; the maintenance history stays.

How It Works

The flow is straightforward:

  1. A tenant submits an issue with a description and optional photos (up to 4, stored on S3)
  2. A manager reviews it and creates a work order, assigning it to a maintenance staff member
  3. Maintenance staff works the job and marks it complete
  4. The manager closes the issue, optionally leaving a closure note

Every action is scoped to a tenant context embedded in the JWT — a manager from one building cannot see another building's data at the database level.

Roles

RoleAccess
TENANTSubmit and track their own issues
MAINTENANCEView assigned work orders, update status
MANAGERFull issue + work order management for their buildings
ADMINUser management, building configuration
SUPER_ADMINCross-operator visibility

Key Features

  • Issue lifecycle — create, assign, update status, link/unlink work orders, close with notes (warns if open WOs exist), hard delete with automatic WO nullification
  • Work orders — standalone or linked to an issue; role-gated actions throughout
  • Photo attachments — S3 presigned PUT/GET, up to 4 photos per issue, 1-hour expiry
  • Operator Continuity view — portfolio-level view across all buildings with a per-building management timeline
  • Server-side search — paginated results with 400ms debounce on issues and work orders
  • Vite code splitting — per-page lazy chunks keep initial load lean

Stack

LayerTechnology
FrontendReact 18, TypeScript, MUI v5, Redux Toolkit, React Query, Vite
BackendNode.js, Express, TypeScript, Prisma v5
DatabasePostgreSQL 16
AuthJWT with tenant context
StorageAWS S3 (presigned URLs)
ValidationZod (shared schemas across frontend and backend)
DevOpsDocker Compose, GitHub Actions CI, PM2, Nginx

Architecture

The project is a monorepo with four packages:

  • packages/backend — Express API on port 3002 (11 Prisma models, 9 enums)
  • packages/web — React dashboard on port 3000
  • packages/shared — TypeScript types and Zod schemas shared across both
  • packages/mobile — React Native scaffold (future)

Status

The platform is live in production. All core flows are working — auth, issues, work orders, photo uploads, operator continuity, user management, and pagination. Currently working on full visual polish and production hardening (HTTPS, domain, monitoring).