Skip to main content

System Architecture

The MLM CMMS is a modern, full-stack maintenance management system built with a clear separation between frontend and backend concerns. This document provides a comprehensive overview of the system architecture, technology choices, and design patterns.

Overview

MLM CMMS is a Computerized Maintenance Management System designed for managing maintenance operations including:
  • Work requests and work orders (tickets)
  • Inventory and spare parts management
  • Asset tracking and preventive maintenance
  • User management with role-based access control (RBAC)
  • Real-time notifications and push messaging
  • Reporting and analytics
The system follows a single-page application (SPA) architecture with a PostgreSQL-backed API layer provided by Supabase.

Architecture Diagram

┌─────────────────────────────────────────────────────────────┐
│                      Client Layer                           │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  React 19 SPA (TypeScript + Vite + Tailwind v4)    │   │
│  │  • Lazy-loaded route components                     │   │
│  │  • Context providers (Auth, RBAC, Settings, Theme)  │   │
│  │  • Service layer for data access                    │   │
│  │  • Progressive Web App (PWA) capabilities           │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘
                             ↕ HTTPS
┌─────────────────────────────────────────────────────────────┐
│                   Supabase Platform                         │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐     │
│  │ Auth Service │  │   Postgres   │  │   Storage    │     │
│  │  • JWT auth  │  │   • RLS      │  │  • Branding  │     │
│  │  • Sessions  │  │   • Policies │  │  • Uploads   │     │
│  └──────────────┘  └──────────────┘  └──────────────┘     │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐     │
│  │  Realtime    │  │ Edge Funcs   │  │   pg_cron    │     │
│  │  • Subs      │  │ • Push notif │  │  • Scheduled │     │
│  │  • Changes   │  │ • Webhooks   │  │    jobs      │     │
│  └──────────────┘  └──────────────┘  └──────────────┘     │
└─────────────────────────────────────────────────────────────┘

Tech Stack

Frontend

React 19

Modern React with hooks, strict mode, and functional components

TypeScript

Strict type checking with ES2020 target and comprehensive linting

Vite

Fast build tool with HMR, bundler module resolution, and optimized production builds

Tailwind CSS v4

Utility-first CSS framework via @tailwindcss/vite plugin

Key Frontend Libraries

LibraryPurposeVersion
@supabase/supabase-jsSupabase client SDK^2.50.0
react-router-domSPA routing^7.6.1
framer-motionAnimations^12.23.24
chart.js + react-chartjs-2Data visualization^4.5.0 / ^5.3.0
@headlessui/reactAccessible UI primitives^2.2.4
@radix-ui/*Accessible componentsVarious
sweetalert2Modal dialogs^11.22.0
react-toastifyToast notifications^11.0.5

Backend (Supabase)

PostgreSQL

Relational database with advanced features (RLS, triggers, functions)

Supabase Auth

JWT-based authentication with session management

Supabase Realtime

WebSocket-based real-time subscriptions to database changes

Edge Functions

Deno-based serverless functions for push notifications

Project Structure

src/
├── components/       # Reusable UI components
│   ├── ui/          # Base UI primitives
│   └── app/         # App-level components
├── context/         # React Context providers
│   ├── AuthContext.tsx
│   ├── UserContext.tsx
│   ├── PermissionsContext.tsx
│   ├── SettingsContext.tsx
│   ├── BrandingContext.tsx
│   └── ThemeContext.tsx
├── services/        # Data access layer
│   ├── ticketService.ts
│   ├── userService.ts
│   ├── assigneeService.ts
│   └── ...
├── pages/           # Route components (lazy-loaded)
│   ├── admin/
│   └── inventory/
├── Routes/          # Route configuration
│   └── appRoutes.tsx
├── rbac/            # Permission system
│   ├── permissionRegistry.ts
│   └── PermissionsContext.tsx
├── lib/             # Utilities and clients
│   ├── supabaseClient.ts
│   └── dataInvalidation.ts
└── main.tsx         # Application entry point

Key Design Patterns

1. Service Layer Pattern

All data access is abstracted through service modules in src/services/. Services handle:
  • Supabase client interactions
  • Error mapping and handling
  • Data transformation
  • RPC/function calls
// Example: src/services/ticketService.ts
export async function fetchTickets(filters: TicketFilters) {
  const { data, error } = await supabase
    .from('tickets')
    .select('*')
    .match(filters);
  
  if (error) throw error;
  return data;
}
Services provide a clean separation between UI components and data access, enabling easier testing and maintenance.

2. Context Provider Pattern

Global state is managed through React Context providers in src/context/:
  • AuthContext: Authentication state and session management
  • UserContext: Current user profile data
  • PermissionsContext: RBAC permissions and roles
  • SettingsContext: Application settings
  • BrandingContext: Multi-tenant branding (logos, colors)
  • ThemeContext: Dark/light theme preferences
// Provider hierarchy in main.tsx
<ThemeProvider>
  <AuthProvider>
    <UserProvider>
      <BrowserRouter>
        <PermissionsProvider>
          <SettingsProvider>
            <BrandingProvider>
              <ThemedAppRoot />
            </BrandingProvider>
          </SettingsProvider>
        </PermissionsProvider>
      </BrowserRouter>
    </UserProvider>
  </AuthProvider>
</ThemeProvider>

3. Lazy Route Loading

All page components are lazy-loaded to optimize bundle size:
// src/Routes/appRoutes.tsx:5
const CreateTicketPage = lazy(() => import('../pages/CreateTicketPage'));
const WorkOrdersPage = lazy(() => import('../pages/WorkOrdersPage'));
// ...

4. Row-Level Security (RLS)

Database security is enforced at the PostgreSQL level using RLS policies. All tables have RLS enabled and policies that check user permissions via public.me_has_permission(code).
Never trust client-side permission checks alone. All security boundaries are enforced in the database through RLS policies.

5. Modular SQL Architecture

The database schema is organized into composable modules:
  • core_cmms: Foundation (RBAC, tickets, users, notifications)
  • assets: Asset management and preventive maintenance
  • inventory: Inventory, parts, warehouses, stock movements
Modules follow a strict execution order (00-16 for core_cmms) to ensure proper dependency resolution.

Environment Configuration

Frontend Environment Variables

# Required
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key

# Optional
VITE_WEB_PUSH_PUBLIC_KEY=your-vapid-public-key
VITE_APP_ENV=development|qa|production
VITE_ENABLE_REMOTE_REPORT_LAYOUT=true|false
Never commit .env files or expose SUPABASE_SERVICE_ROLE_KEY in frontend code. Only the anon key should be used client-side.

Build Modes

CommandModeUse Case
npm run devDevelopmentLocal development with HMR
npm run buildDevelopmentStandard build
npm run build:qaQAQA environment build
npm run build:prodProductionProduction-optimized build

Progressive Web App (PWA)

The application includes PWA capabilities:
  • Service Worker: Registered in production mode (src/main.tsx:106-123)
  • Install Prompt: Captured and deferred for custom install UI
  • Offline Support: Service worker caching for static assets
  • Push Notifications: Web Push API integration with VAPID keys

Service Worker Registration

// src/main.tsx:106
if (import.meta.env.PROD && 'serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    const swUrl = `/sw.js?v=${encodeURIComponent(__APP_VERSION__)}`;
    navigator.serviceWorker
      .register(swUrl, { updateViaCache: 'none' })
      .then(() => {
        // Handle controller changes for updates
      });
  });
}

Security Architecture

1

Authentication

JWT-based authentication via Supabase Auth with persistent sessions and automatic token refresh.
2

Authorization

Permission-based access control enforced through:
  • Frontend route guards (ProtectedRoute + RequirePerm)
  • Backend RLS policies checking public.me_has_permission(code)
3

Row-Level Security

All tables have RLS enabled with policies that verify user permissions before allowing data access.
4

Secure Headers

Security headers configured in public/_headers for Cloudflare deployment:
  • CSP, X-Frame-Options, X-Content-Type-Options, etc.

Real-time Features

The system uses Supabase Realtime for live updates:
  • Notification Deliveries: Real-time notification badge updates
  • Ticket Comments: Live comment streams on ticket detail pages
  • Change Tracking: Automatic UI updates when data changes

Realtime Configuration

Tables enabled for realtime in sql/modules/core_cmms/13_realtime.sql:
  • notification_deliveries (REPLICA IDENTITY FULL)
  • ticket_comments (REPLICA IDENTITY FULL)

Notification System

Multi-channel notification system with:
  1. In-app Notifications: Notification center with delivery tracking
  2. Web Push: Browser push notifications via Edge Function
  3. Outbox Pattern: Reliable message delivery with retry logic
  4. Deduplication: Prevents duplicate notifications within 5-minute windows

Architecture

Notification Trigger → notification_outbox → Edge Function → Push API → Browser

                    notification_deliveries → UI Badge Update
See sql/modules/core_cmms/16_notifications.sql for implementation details.

Data Invalidation Strategy

The frontend uses a custom invalidation system (src/lib/dataInvalidation.ts) to coordinate cache refreshes across:
  • Context providers
  • Service layer caches (5-minute TTL)
  • Component-level state
Domains for invalidation include: permissions, users, tickets, assignees, settings, etc.

Build & Bundle Configuration

Vite Configuration

// vite.config.ts:7
export default defineConfig({
  plugins: [react(), tailwindcss()],
  define: {
    __APP_VERSION__: JSON.stringify(pkg.version),
  },
})

TypeScript Configuration

  • Target: ES2020
  • Module: ESNext with bundler resolution
  • Strict Mode: Enabled
  • JSX: react-jsx (automatic runtime)
  • Linting: noUnusedLocals, noUnusedParameters, noFallthroughCasesInSwitch
See tsconfig.app.json for full configuration.

Performance Considerations

The current build reports large chunks. Optimization strategies:
  • Lazy loading for all route components
  • Scoped imports to reduce bundle size
  • Service-level caching (5-minute TTL) to reduce API calls
  • Debounced event handlers for input normalization

Input Normalization

Global event listeners handle numeric input normalization:
  • On Input: Remove leading zeros from integers
  • On Blur: Normalize comma to decimal, validate numeric values
See src/main.tsx:48-78 for implementation.

Deployment Architecture

SPA Routing

SPA routing depends on public/_redirects:
/* /index.html 200
This ensures all routes are handled by the React router.

Multi-Environment Support

Environment-specific builds via Vite modes:
  • Development: Full logging, source maps
  • QA: Production-like with QA-specific configs
  • Production: Optimized bundles, console suppression (except in dev)
// src/main.tsx:95
if (process.env.NODE_ENV !== 'development') {
  console.log = function () {};
  console.warn = function () {};
  // ...
}

Next Steps

Database Schema

Explore the database structure and table relationships

RBAC System

Learn about the permission-based access control system

Frontend Services

Browse the available services and functions

Installation Guide

Get started with local development