Skip to content

Latest commit

 

History

History
796 lines (714 loc) · 66.7 KB

File metadata and controls

796 lines (714 loc) · 66.7 KB

Nzila Gym Manager - System Architecture

EN: Comprehensive technical architecture documentation for the Nzila multi-tenant gym management system.

PT: Documentação abrangente de arquitetura técnica para o sistema de gestão de ginásios multi-tenant Nzila.

Version: 2.3.0 | Last Updated: March 11, 2026


Table of Contents | Índice

  1. Executive Summary
  2. System Overview
  3. Frontend Architecture
  4. Backend Architecture
  5. Data Architecture
  6. Security Architecture
  7. Module Architecture
  8. Integration Patterns
  9. Performance Considerations
  10. Deployment Architecture

Executive Summary

Nzila is a production-grade, multi-tenant SaaS platform for gym management. Built with React 19, TypeScript, and Supabase, it provides 21 core modules serving gym owners, staff, trainers, and members.

Key Metrics

Metric Value
Frontend Framework React 19 + TypeScript 5.9
Backend Supabase (PostgreSQL 15)
Database Tables 67
RLS Policies 100% coverage
Feature Modules 21
UI Components 50+ (shadcn/ui)
TanStack Query Hooks 19
i18n Coverage 95% (EN/PT)
Security Score 7.8/10

System Overview

High-Level Architecture Diagram

┌──────────────────────────────────────────────────────────────────────────────────┐
│                                   CLIENT LAYER                                    │
│                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │                         React 19 Application                                 │ │
│  │                                                                              │ │
│  │  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐    │ │
│  │  │   Landing    │  │   Auth       │  │   Dashboard  │  │   Member     │    │ │
│  │  │   Page       │  │   Module     │  │   Layouts    │  │   Portal     │    │ │
│  │  └──────────────┘  └──────────────┘  └──────────────┘  └──────────────┘    │ │
│  │                                                                              │ │
│  │  ┌──────────────────────────────────────────────────────────────────────┐   │ │
│  │  │                      21 Feature Modules (Lazy Loaded)                 │   │ │
│  │  │  Members │ Calendar │ Training │ Payments │ Invoices │ Leads │ ...   │   │ │
│  │  └──────────────────────────────────────────────────────────────────────┘   │ │
│  │                                                                              │ │
│  │  ┌─────────────────────────────────────────────────────────────────────┐    │ │
│  │  │                         Shared Layer                                 │    │ │
│  │  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌────────────┐  │    │ │
│  │  │  │ shadcn/ui   │  │ TanStack    │  │ React       │  │ i18n       │  │    │ │
│  │  │  │ Components  │  │ Query       │  │ Context     │  │ (EN/PT)    │  │    │ │
│  │  │  │ (50+)       │  │ (19 hooks)  │  │ (Auth/Gym)  │  │            │  │    │ │
│  │  │  └─────────────┘  └─────────────┘  └─────────────┘  └────────────┘  │    │ │
│  │  └─────────────────────────────────────────────────────────────────────┘    │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────────┘
                                         │
                                         │ HTTPS / WebSocket
                                         ▼
┌──────────────────────────────────────────────────────────────────────────────────┐
│                                   API LAYER                                       │
│                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │                         Supabase Edge Functions (Deno)                       │ │
│  │                                                                              │ │
│  │  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐    │ │
│  │  │ auth-with-   │  │ send-email   │  │ create-user- │  │ gdpr-export  │    │ │
│  │  │ rate-limit   │  │ (6 templates)│  │ account      │  │ gdpr-delete  │    │ │
│  │  └──────────────┘  └──────────────┘  └──────────────┘  └──────────────┘    │ │
│  │                                                                              │ │
│  │  ┌──────────────────────────────────────────────────────────────────────┐   │ │
│  │  │                        Shared Utilities                               │   │ │
│  │  │             cors.ts │ sanitize.ts │ validation.ts                     │   │ │
│  │  └──────────────────────────────────────────────────────────────────────┘   │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────────┘
                                         │
                                         │ PostgreSQL Wire Protocol
                                         ▼
┌──────────────────────────────────────────────────────────────────────────────────┐
│                                 DATABASE LAYER                                    │
│                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │                         PostgreSQL 15 (Supabase)                             │ │
│  │                                                                              │ │
│  │  ┌──────────────────────────────────────────────────────────────────────┐   │ │
│  │  │                         67 Tables                                     │   │ │
│  │  │  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐        │   │ │
│  │  │  │ gyms    │ │ members │ │ classes │ │payments │ │ invoices│ ...    │   │ │
│  │  │  └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘        │   │ │
│  │  └──────────────────────────────────────────────────────────────────────┘   │ │
│  │                                                                              │ │
│  │  ┌──────────────────────────────────────────────────────────────────────┐   │ │
│  │  │                    Row-Level Security (RLS)                           │   │ │
│  │  │       100% Table Coverage │ gym_id Isolation │ Role-Based Access      │   │ │
│  │  └──────────────────────────────────────────────────────────────────────┘   │ │
│  │                                                                              │ │
│  │  ┌──────────────────────────────────────────────────────────────────────┐   │ │
│  │  │                    Database Functions & Triggers                      │   │ │
│  │  │  update_updated_at │ audit_log_trigger │ get_user_gym_id              │   │ │
│  │  └──────────────────────────────────────────────────────────────────────┘   │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                   │
│  ┌──────────────────────────┐  ┌──────────────────────────┐                      │
│  │   Supabase Auth         │  │   Supabase Storage       │                      │
│  │   - JWT Sessions        │  │   - Payment Proofs       │                      │
│  │   - Rate Limiting       │  │   - Member Photos        │                      │
│  │   - Password Policy     │  │   - Gym Logos            │                      │
│  └──────────────────────────┘  └──────────────────────────┘                      │
└──────────────────────────────────────────────────────────────────────────────────┘

Frontend Architecture

Component Hierarchy

App.tsx
├── BrowserRouter
│   ├── QueryClientProvider (TanStack Query)
│   │   ├── ThemeProvider (next-themes)
│   │   │   ├── TooltipProvider
│   │   │   │   ├── AuthProvider
│   │   │   │   │   ├── GymProvider
│   │   │   │   │   │   ├── Routes
│   │   │   │   │   │   │   ├── Public Routes
│   │   │   │   │   │   │   │   ├── "/" → Index (Landing)
│   │   │   │   │   │   │   │   ├── "/auth" → AuthPage
│   │   │   │   │   │   │   │   ├── "/privacy" → Privacy
│   │   │   │   │   │   │   │   └── "/terms" → Terms
│   │   │   │   │   │   │   │
│   │   │   │   │   │   │   └── Protected Routes (ProtectedRoute wrapper)
│   │   │   │   │   │   │       ├── DashboardLayout
│   │   │   │   │   │   │       │   ├── "/dashboard" → Dashboard
│   │   │   │   │   │   │       │   ├── "/calendar" → Calendar
│   │   │   │   │   │   │       │   ├── "/members" → Members (lazy)
│   │   │   │   │   │   │       │   ├── "/check-ins" → CheckIns
│   │   │   │   │   │   │       │   ├── "/disciplines" → Disciplines
│   │   │   │   │   │   │       │   ├── "/training" → Training (lazy)
│   │   │   │   │   │   │       │   ├── "/payments" → Payments (lazy)
│   │   │   │   │   │   │       │   ├── "/staff" → Staff (lazy)
│   │   │   │   │   │   │       │   ├── "/trainers" → Trainers (lazy)
│   │   │   │   │   │   │       │   ├── "/settings/*" → Settings (lazy)
│   │   │   │   │   │   │       │   └── "/superadmin/*" → SuperAdmin (lazy)
│   │   │   │   │   │   │       │
│   │   │   │   │   │   │       └── Member Portal
│   │   │   │   │   │   │           ├── "/member/portal" → MemberPortal
│   │   │   │   │   │   │           ├── "/member/activity" → MemberActivity
│   │   │   │   │   │   │           ├── "/member/check-in" → MemberCheckIn
│   │   │   │   │   │   │           └── "/member/finances" → MemberFinances

Directory Structure

src/
├── components/            # React components
│   ├── ui/               # shadcn/ui base (50+ components)
│   ├── layout/           # DashboardLayout, navigation
│   ├── common/           # Shared (ErrorBoundary, PageHeader)
│   ├── auth/             # Auth components
│   ├── dashboard/        # Dashboard widgets
│   ├── calendar/         # Calendar, RecurringClassForm
│   ├── member/           # Member management, elite portal
│   ├── payments/         # Payment components
│   ├── training/         # Training hub components
│   ├── settings/         # Settings panels
│   ├── notifications/    # Alert components
│   └── landing/          # Landing page components
├── contexts/             # React Context providers
│   ├── AuthContext.tsx
│   └── GymContext.tsx
├── hooks/                # Custom hooks
│   ├── useMembersData.tanstack.tsx
│   ├── usePaymentsData.tanstack.tsx
│   ├── useCalendarData.tanstack.tsx
│   ├── useCheckInsData.tanstack.tsx
│   ├── useDisciplinesData.tanstack.tsx
│   ├── useWorkoutsData.tanstack.tsx
│   ├── useInvoicesData.tanstack.tsx
│   ├── useFinancialData.tanstack.tsx
│   ├── useMemberProgressData.tanstack.tsx
│   ├── useExercisesData.tanstack.tsx
│   ├── useWorkoutBlocksData.tanstack.tsx
│   ├── useRBAC.ts
│   ├── useRealtimeUpdates.ts
│   ├── useFormWithZod.ts
│   ├── usePWA.ts
│   └── use-mobile.tsx
├── modules/              # Feature modules (21)
│   ├── auth/             # Authentication
│   ├── members/          # Member management
│   ├── payments/         # Payments & reconciliation
│   ├── calendar/         # Calendar & scheduling
│   ├── booking/          # Class booking
│   ├── invoices/         # Invoice management
│   ├── leads/            # CRM leads
│   ├── pos/              # Point of sale
│   ├── inventory/        # Inventory management
│   ├── trainers/         # Trainer management
│   ├── staff/            # Staff management
│   ├── training/         # Training hub
│   ├── checkins/         # Check-in system
│   ├── kiosk/            # Kiosk mode
│   ├── gdpr/             # GDPR compliance
│   ├── reporting/        # Financial reporting
│   ├── notifications/    # Email services
│   ├── events/           # Event bus
│   ├── onboarding/       # Setup wizard
│   ├── superadmin/       # Super admin
│   ├── saas-admin/       # SaaS administration
│   └── settings/         # Settings module
├── pages/                # Route pages
├── lib/                  # Utilities
├── types/                # TypeScript types
├── integrations/         # External integrations
│   └── supabase/
├── i18n/                 # Internationalization
│   ├── index.ts
│   └── locales/
│       ├── en/           # English translations
│       └── pt-pt/        # Portuguese translations
└── utils/                # Utility functions

State Management Architecture

┌──────────────────────────────────────────────────────────────────────────────────┐
│                            STATE MANAGEMENT LAYERS                                │
└──────────────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────────────┐
│                           LAYER 1: SERVER STATE                                   │
│                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │                         TanStack Query (19 Hooks)                            │ │
│  │                                                                              │ │
│  │  Data Fetching Hooks:                                                        │ │
│  │  ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐           │ │
│  │  │ useMembersData   │  │ usePaymentsData  │  │ useCalendarData  │           │ │
│  │  │ - useQuery       │  │ - useQuery       │  │ - useQuery       │           │ │
│  │  │ - useMutation    │  │ - useMutation    │  │ - useMutation    │           │ │
│  │  │ - Optimistic     │  │ - Optimistic     │  │ - Optimistic     │           │ │
│  │  └──────────────────┘  └──────────────────┘  └──────────────────┘           │ │
│  │                                                                              │ │
│  │  ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐           │ │
│  │  │ useCheckInsData  │  │ useDisciplines   │  │ useWorkoutsData  │           │ │
│  │  │                  │  │ Data             │  │                  │           │ │
│  │  └──────────────────┘  └──────────────────┘  └──────────────────┘           │ │
│  │                                                                              │ │
│  │  Cache Strategy:                                                             │ │
│  │  - staleTime: 5 minutes (configurable)                                       │ │
│  │  - gcTime: 30 minutes                                                        │ │
│  │  - refetchOnWindowFocus: true                                                │ │
│  │  - Automatic cache invalidation on mutations                                 │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────────────┐
│                           LAYER 2: CLIENT STATE                                   │
│                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │                         React Context Providers                              │ │
│  │                                                                              │ │
│  │  ┌──────────────────────────────────────────────────────────────────────┐   │ │
│  │  │                         AuthContext                                   │   │ │
│  │  │  State:                    Actions:                                   │   │ │
│  │  │  - user: User | null       - login(email, password)                   │   │ │
│  │  │  - session: Session        - logout()                                 │   │ │
│  │  │  - isLoading: boolean      - signUp(email, password, metadata)        │   │ │
│  │  │  - role: UserRole          - resetPassword(email)                     │   │ │
│  │  │  - profile: Profile        - updateProfile(data)                      │   │ │
│  │  └──────────────────────────────────────────────────────────────────────┘   │ │
│  │                                                                              │ │
│  │  ┌──────────────────────────────────────────────────────────────────────┐   │ │
│  │  │                         GymContext                                    │   │ │
│  │  │  State:                    Actions:                                   │   │ │
│  │  │  - gym: Gym | null         - setCurrentGym(gymId)                     │   │ │
│  │  │  - gymId: string           - refreshGymData()                         │   │ │
│  │  │  - settings: GymSettings   - updateGymSettings(data)                  │   │ │
│  │  │  - locations: Location[]                                              │   │ │
│  │  └──────────────────────────────────────────────────────────────────────┘   │ │
│  │                                                                              │ │
│  │  ┌──────────────────────────────────────────────────────────────────────┐   │ │
│  │  │                      SecureAuthContext                                │   │ │
│  │  │  Enhanced security features:                                          │   │ │
│  │  │  - Session timeout warnings                                           │   │ │
│  │  │  - Automatic session refresh                                          │   │ │
│  │  │  - Inactivity detection                                               │   │ │
│  │  │  - Force logout on security events                                    │   │ │
│  │  └──────────────────────────────────────────────────────────────────────┘   │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────────────┐
│                           LAYER 3: UI STATE                                       │
│                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │                         Component-Local State                                │ │
│  │  - useState for form inputs                                                  │ │
│  │  - useReducer for complex forms                                              │ │
│  │  - React Hook Form for form management                                       │ │
│  │  - URL state (React Router) for filters/pagination                          │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────────┘

Backend Architecture

Edge Function Architecture

┌──────────────────────────────────────────────────────────────────────────────────┐
│                           EDGE FUNCTION LAYER                                     │
└──────────────────────────────────────────────────────────────────────────────────┘

                              ┌───────────────────┐
                              │   HTTP Request    │
                              └─────────┬─────────┘
                                        │
                                        ▼
┌──────────────────────────────────────────────────────────────────────────────────┐
│                           SHARED MIDDLEWARE                                       │
│                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │                            cors.ts                                           │ │
│  │  - Origin validation against whitelist                                       │ │
│  │  - CORS headers generation                                                   │ │
│  │  - Preflight request handling                                                │ │
│  │                                                                              │ │
│  │  const ALLOWED_ORIGINS = [                                                   │ │
│  │    /^https:\/\/.*\.lovable\.app$/,                                          │ │
│  │    /^https:\/\/.*\.supabase\.co$/,                                          │ │
│  │    "https://nzila.app",                                                      │ │
│  │    "http://localhost:5173"                                                   │ │
│  │  ];                                                                          │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │                          sanitize.ts                                         │ │
│  │  - encodeHTMLEntities(): XSS prevention                                      │ │
│  │  - sanitizeURL(): URL validation and sanitization                           │ │
│  │  - stripHTML(): Remove HTML tags                                             │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │                         validation.ts                                        │ │
│  │  - Email format validation                                                   │ │
│  │  - Input length limits                                                       │ │
│  │  - Type checking utilities                                                   │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────────┘
                                        │
                                        ▼
┌──────────────────────────────────────────────────────────────────────────────────┐
│                          EDGE FUNCTIONS                                           │
│                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │                      auth-with-rate-limit                                    │ │
│  │  Purpose: Rate-limited authentication                                        │ │
│  │  Rate Limit: 5 attempts per 15 minutes per IP                               │ │
│  │  Lockout: 30 minutes after limit exceeded                                    │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │                          send-email                                          │ │
│  │  Purpose: Transactional email via Resend API                                 │ │
│  │  Auth: JWT required for custom emails                                        │ │
│  │  Templates: welcome_self_signup, welcome_admin_created, password_reset       │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │                      create-user-account                                     │ │
│  │  Purpose: Admin creates user accounts                                        │ │
│  │  Auth: Admin JWT required                                                    │ │
│  │  Creates: auth.users entry + profiles entry + member entry                   │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │                    pre-register-gym-owner                                    │ │
│  │  Purpose: Super admin pre-registers gym owners                               │ │
│  │  Auth: Super admin JWT required                                              │ │
│  │  Creates: gym_owner_invitations entry                                        │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────────┘

Data Architecture

Three-Tier Module Separation

┌─────────────────────────────────────────────────────────────────────────────┐
│                          TIER 1: DISCIPLINES MODULE                          │
│                                                                              │
│  Purpose: Activity Catalog & Taxonomy | Propósito: Catálogo de Atividades   │
│                                                                              │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐              │
│  │ Activity Types  │  │ Rank Systems    │  │ Category        │              │
│  │ - BJJ           │  │ - Belt Levels   │  │ Taxonomy        │              │
│  │ - Yoga          │  │ - Stripe System │  │ - Combat        │              │
│  │ - CrossFit      │  │ - Criteria      │  │ - Wellness      │              │
│  │ - Pilates       │  │ - Requirements  │  │ - Strength      │              │
│  │ - Boxing        │  │ - Colors        │  │ - Cardio        │              │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘              │
│                                                                              │
│  Tables: disciplines, discipline_ranks                                       │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      │ FK: discipline_id
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                          TIER 2: CALENDAR MODULE                             │
│                                                                              │
│  Purpose: Scheduling Engine | Propósito: Motor de Agendamento               │
│                                                                              │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐              │
│  │ Class Schedule  │  │ Recurring       │  │ Booking System  │              │
│  │ - Visual Cal    │  │ Series          │  │ - Reservations  │              │
│  │ - Time Slots    │  │ - RRULE Engine  │  │ - Waitlist FIFO │              │
│  │ - Coach Assign  │  │ - Exceptions    │  │ - Cancellations │              │
│  │ - Capacity      │  │ - Auto-generate │  │ - Promotions    │              │
│  │ - Locations     │  │ - End Dates     │  │ - Check-ins     │              │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘              │
│                                                                              │
│  Tables: classes, class_series, class_bookings, class_types, locations       │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      │ FK: workout_template_id
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                          TIER 3: TRAINING MODULE                             │
│                                                                              │
│  Purpose: Member Programming | Propósito: Programação de Membros            │
│                                                                              │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐              │
│  │ Exercise        │  │ Workout         │  │ Progress        │              │
│  │ Library         │  │ Templates       │  │ Tracking        │              │
│  │ - 14 Categories │  │ - Block Builder │  │ - Performance   │              │
│  │ - Equipment     │  │ - Polymorphic   │  │ - Promotions    │              │
│  │ - Muscle Groups │  │ - WOD Types     │  │ - Rank History  │              │
│  │ - Difficulty    │  │ - Assignments   │  │ - Achievements  │              │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘              │
│                                                                              │
│  Tables: gym_exercises, workout_templates, workout_blocks, exercise_instances│
│          member_ranks, performance_records                                   │
└─────────────────────────────────────────────────────────────────────────────┘

Entity Relationship Overview

┌──────────────────────────────────────────────────────────────────────────────────┐
│                            CORE ENTITIES                                          │
└──────────────────────────────────────────────────────────────────────────────────┘

    ┌─────────────┐                   ┌─────────────┐
    │    gyms     │ ◄────────────────►│   profiles  │
    │             │     1:N           │             │
    │  - id (PK)  │                   │  - id (PK)  │
    │  - name     │                   │  - user_id  │
    │  - slug     │                   │  - gym_id   │
    │  - settings │                   │  - role     │
    └──────┬──────┘                   └─────────────┘
           │
           │ 1:N (gym_id FK on all tables)
           │
    ┌──────┴────────────────────────────────────────────────────────────────┐
    │                                                                        │
    ▼                    ▼                    ▼                    ▼        │
┌─────────┐        ┌─────────┐        ┌─────────┐        ┌─────────┐       │
│ members │        │ classes │        │disciplines│       │ payments│       │
│         │◄──────►│         │◄──────►│          │        │         │       │
│         │  N:M   │         │  1:N   │          │        │         │       │
└────┬────┘        └────┬────┘        └────┬─────┘        └────┬────┘       │
     │                  │                  │                   │            │
     ▼                  ▼                  ▼                   ▼            │
┌──────────┐      ┌──────────┐      ┌──────────┐        ┌──────────┐       │
│ check_ins│      │class_    │      │discipline│        │ invoices │       │
│          │      │bookings  │      │_ranks    │        │          │       │
└──────────┘      └──────────┘      └──────────┘        └──────────┘       │
└───────────────────────────────────────────────────────────────────────────┘

Table Categories (67 Tables)

Category Tables Description
Core 8 gyms, profiles, members, locations, settings
Scheduling 6 classes, class_series, class_bookings, class_types
Training 8 disciplines, discipline_ranks, gym_exercises, workout_templates
Finance 6 payments, invoices, invoice_items, discounts, bank_reconciliations
Operations 8 check_ins, leads, lead_tasks, trainers, staff, assets
Auth & Security 10 auth_events, auth_rate_limits, audit_logs, gdpr_consents
Platform 8 gym_subscriptions, platform_plans, feature_flags, support_tickets
Communication 4 email_notifications, whatsapp_messages
GDPR 3 gdpr_consents, data_export_requests, deletion_requests

Security Architecture

Security Layers

┌─────────────────────────────────────────────────────────────────────────────┐
│                         LAYER 1: FRONTEND SECURITY                           │
│                                                                              │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐              │
│  │ Input           │  │ Output          │  │ Route           │              │
│  │ Validation      │  │ Sanitization    │  │ Protection      │              │
│  │ - Zod schemas   │  │ - HTML encoding │  │ - ProtectedRoute│              │
│  │ - Type guards   │  │ - XSS prevention│  │ - RequirePermit │              │
│  │ - Length limits │  │ - URL sanitize  │  │ - RBAC hooks    │              │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘              │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
┌─────────────────────────────────────────────────────────────────────────────┐
│                         LAYER 2: API SECURITY                                │
│                                                                              │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐              │
│  │ Authentication  │  │ Rate Limiting   │  │ CORS            │              │
│  │ - JWT tokens    │  │ - Per IP/user   │  │ - Origin check  │              │
│  │ - Session mgmt  │  │ - Exponential   │  │ - Whitelist     │              │
│  │ - Timeout warn  │  │   backoff       │  │ - Credentials   │              │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘              │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
┌─────────────────────────────────────────────────────────────────────────────┐
│                         LAYER 3: DATABASE SECURITY                           │
│                                                                              │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐              │
│  │ Row-Level       │  │ Multi-Tenant    │  │ Sensitive Data  │              │
│  │ Security        │  │ Isolation       │  │ Protection      │              │
│  │ - 67 tables     │  │ - gym_id FK     │  │ - member_       │              │
│  │ - CRUD policies │  │ - Context funcs │  │   sensitive_data│              │
│  │ - Role checks   │  │ - No cross-read │  │ - Encryption    │              │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘              │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
┌─────────────────────────────────────────────────────────────────────────────┐
│                         LAYER 4: AUDIT & MONITORING                          │
│                                                                              │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐              │
│  │ Audit Logs      │  │ Auth Events     │  │ Error Tracking  │              │
│  │ - Immutable     │  │ - Login/logout  │  │ - correlationId │              │
│  │ - Trigger-based │  │ - Failed auth   │  │ - Safe payloads │              │
│  │ - Entity track  │  │ - Session mgmt  │  │ - Stack hidden  │              │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘              │
└─────────────────────────────────────────────────────────────────────────────┘

Multi-Tenant Isolation

  Gym A Tenant                                    Gym B Tenant
  ────────────                                    ────────────
       │                                               │
       ▼                                               ▼
┌─────────────┐                                 ┌─────────────┐
│ gym_id: A   │                                 │ gym_id: B   │
│             │                                 │             │
│ ┌─────────┐ │         ISOLATION               │ ┌─────────┐ │
│ │ members │ │ ◄─────────────────────────────► │ │ members │ │
│ └─────────┘ │         (No cross-read)         │ └─────────┘ │
│ ┌─────────┐ │                                 │ ┌─────────┐ │
│ │ classes │ │                                 │ │ classes │ │
│ └─────────┘ │                                 │ └─────────┘ │
│ ┌─────────┐ │                                 │ ┌─────────┐ │
│ │payments │ │                                 │ │payments │ │
│ └─────────┘ │                                 │ └─────────┘ │
└─────────────┘                                 └─────────────┘

RLS POLICY PATTERN:

CREATE POLICY "Users can only view their gym data"
ON public.members
FOR SELECT
USING (
  gym_id = (
    SELECT gym_id FROM public.profiles
    WHERE user_id = auth.uid()
  )
);

Role-Based Access Control (RBAC)

┌─────────────────┬───────────┬───────┬─────────┬───────┬────────┐
│ Permission      │Super Admin│ Owner │ Manager │ Admin │ Member │
├─────────────────┼───────────┼───────┼─────────┼───────┼────────┤
│ members:read    │     ✓     │   ✓   │    ✓    │   ✓   │   Own  │
│ members:write   │     ✓     │   ✓   │    ✓    │   ✓   │   Own  │
│ payments:read   │     ✓     │   ✓   │    ✓    │   ✓   │   Own  │
│ payments:write  │     ✓     │   ✓   │    ✓    │   ─   │   ─    │
│ settings:read   │     ✓     │   ✓   │    ─    │   ─   │   ─    │
│ settings:write  │     ✓     │   ✓   │    ─    │   ─   │   ─    │
│ platform:manage │     ✓     │   ─   │    ─    │   ─   │   ─    │
└─────────────────┴───────────┴───────┴─────────┴───────┴────────┘

Module Architecture

Module Communication Patterns

1. Event Bus (Loose Coupling)
─────────────────────────────
// src/modules/events/eventBus.ts
const eventBus = new EventEmitter();

// Publishing
eventBus.emit('booking:created', { bookingId, memberId, classId });

// Subscribing
eventBus.on('booking:created', async (event) => {
  await sendBookingConfirmation(event);
  await updateMemberStats(event);
});

2. TanStack Query Invalidation (Data Sync)
──────────────────────────────────────────
// After creating a payment
useMutation({
  mutationFn: createPayment,
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ['payments'] });
    queryClient.invalidateQueries({ queryKey: ['invoices'] });
    queryClient.invalidateQueries({ queryKey: ['member', memberId] });
  }
});

3. Database Triggers (Backend Sync)
───────────────────────────────────
-- Automatic audit logging
CREATE TRIGGER audit_members_changes
AFTER INSERT OR UPDATE OR DELETE ON members
FOR EACH ROW EXECUTE FUNCTION log_audit_event();

-- Automatic timestamp updates
CREATE TRIGGER update_members_timestamp
BEFORE UPDATE ON members
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

Integration Patterns

External Service Integration

┌─────────────────────────────────────────────────────────────────┐
│                         RESEND (Email)                          │
│  Integration Point: supabase/functions/send-email              │
│  Auth: RESEND_API_KEY environment variable                     │
│  Flow: App → Edge Function → Resend API → Recipient            │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                    SUPABASE STORAGE (Files)                     │
│  Integration Point: Direct Supabase client                     │
│  Buckets: payment-proofs, member-photos, gym-logos, documents  │
│  Security: RLS on storage.objects table                        │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                 SUPABASE REALTIME (Live Updates)                │
│  Integration Point: Supabase client subscriptions              │
│  Enabled Tables: check_ins, class_bookings, notifications      │
│  Hook: useRealtimeUpdates()                                    │
└─────────────────────────────────────────────────────────────────┘

Performance Considerations

Caching Strategy

Layer 1: TanStack Query (Client-side)
─────────────────────────────────────
- staleTime: 5 minutes (user-specific data)
- staleTime: 30 minutes (reference data like disciplines)
- gcTime: 30 minutes
- Automatic background refetching
- Optimistic updates for mutations

Layer 2: Code Splitting
───────────────────────
- Route-based lazy loading for all 21 modules
- Critical path: main + vendor (~450KB)
- Module chunks loaded on navigation
- Prefetch common modules after initial load

Bundle Analysis

┌────────────────────────────────────────────────────────────────┐
│ main.js           │ ~150KB │ Core React, Router, Context      │
├────────────────────────────────────────────────────────────────┤
│ vendor.js         │ ~300KB │ TanStack Query, Supabase, UI     │
├────────────────────────────────────────────────────────────────┤
│ members.chunk.js  │ ~50KB  │ Members module (lazy)            │
│ payments.chunk.js │ ~40KB  │ Payments module (lazy)           │
│ calendar.chunk.js │ ~60KB  │ Calendar module (lazy)           │
│ training.chunk.js │ ~45KB  │ Training module (lazy)           │
│ ...               │        │ Other modules (lazy)             │
└────────────────────────────────────────────────────────────────┘

Deployment Architecture

Environment Overview

┌─────────────────────────────────────────────────────────────────┐
│                       LOVABLE CLOUD                             │
│                                                                 │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │                    Frontend (Vite)                        │  │
│  │  Build: npm run build / bun run build                    │  │
│  │  Output: dist/                                            │  │
│  │  CDN: Global edge distribution                           │  │
│  │  URL: https://project.lovable.app                        │  │
│  └──────────────────────────────────────────────────────────┘  │
│                                                                 │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │                  Supabase Project                         │  │
│  │  Database: PostgreSQL 15                                  │  │
│  │  Auth: Supabase Auth (JWT)                               │  │
│  │  Storage: Supabase Storage                               │  │
│  │  Edge Functions: Deno runtime                            │  │
│  │  Realtime: WebSocket subscriptions                       │  │
│  └──────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘

Environment Variables:
VITE_SUPABASE_URL=https://project.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=eyJ...
VITE_SUPABASE_PROJECT_ID=project-id

# Edge function secrets (managed in Lovable Cloud)
RESEND_API_KEY=re_...
FROM_EMAIL=noreply@gym.com
SITE_URL=https://project.lovable.app
WEBHOOK_SECRET=whsec_...

Related Documentation


Version: 1.0.5 | Last Updated: February 8, 2026