Skip to main content

Architecture Overview

upLegal is built as a modern full-stack web application with a client-server architecture:
┌─────────────────────────────────────────────────────────────┐
│                    Client (Browser)                         │
│  ┌───────────────────────────────────────────────────────┐  │
│  │   React SPA (Vite)                                    │  │
│  │   - Component-based UI                                │  │
│  │   - Client-side routing (React Router)                │  │
│  │   - State management (React Query, Context API)       │  │
│  └───────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘

                            │ HTTPS

┌─────────────────────────────────────────────────────────────┐
│                    Backend Services                          │
│  ┌────────────────────┐  ┌───────────────────────────────┐  │
│  │  Express Server    │  │  Supabase                     │  │
│  │  (server.mjs)      │  │  - PostgreSQL Database        │  │
│  │  - API Routes      │  │  - Authentication             │  │
│  │  - Webhooks        │  │  - Real-time Subscriptions    │  │
│  │  - Payment Logic   │  │  - Storage (S3-compatible)    │  │
│  └────────────────────┘  │  - Row Level Security (RLS)   │  │
│                          └───────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘

                            │ External APIs

┌─────────────────────────────────────────────────────────────┐
│                  Third-Party Services                        │
│  ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│  │ MercadoPago  │ │ Google Meet  │ │ Resend (Email)       │ │
│  │ - Payments   │ │ - Video Call │ │ - Transactional      │ │
│  │ - Webhooks   │ │ - Calendar   │ │ - Notifications      │ │
│  └──────────────┘ └──────────────┘ └──────────────────────┘ │
│  ┌──────────────────────────────────────────────────────┐   │
│  │ PJUD (Poder Judicial)                                │   │
│  │ - Lawyer Verification via RUT                        │   │
│  └──────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

Core Components

Frontend Layer (React SPA)

The frontend is a single-page application built with React and Vite:

UI Framework

  • React 18: Component-based architecture with hooks
  • TypeScript: Type-safe development
  • Vite: Fast development server and optimized builds
  • React Router: Client-side routing with protected routes

State Management

  • React Query: Server state caching and synchronization
  • Context API: Auth, messages, notifications
  • Local State: Component-level state with hooks

UI Components

  • shadcn/ui: Radix UI primitives with Tailwind styling
  • Tailwind CSS: Utility-first styling
  • Framer Motion: Animations and transitions
  • Recharts: Data visualization

Forms & Validation

  • React Hook Form: Form state management
  • Zod: Schema validation
  • @hookform/resolvers: Validation integration

Backend Layer (Express + Supabase)

The Express server (server.mjs) handles:
  • Payment Processing: MercadoPago preference creation and webhooks
  • Lawyer Verification: PJUD RUT validation and scraping
  • Booking Management: Appointment creation and confirmation
  • Email Notifications: Resend integration for transactional emails
  • File Uploads: Avatar and document handling
Key Routes:
  • POST /create-payment - Create MercadoPago payment preference
  • POST /api/mercadopago/webhook - Payment confirmation webhook
  • POST /verify-lawyer - PJUD lawyer verification
  • POST /api/bookings/create - Create booking with payment

Database Architecture

The database uses PostgreSQL with Supabase, organized into key tables:
  • profiles: User accounts (clients and lawyers)
  • appointments: Scheduled consultations
  • bookings: Payment-linked appointment records
  • consultations: Service requests and cases
  • messages: Real-time chat messages
  • conversations: Message threads
  • notifications: In-app notification queue
  • reviews: Client reviews and ratings
  • payments: Payment transaction records
  • lawyer_services: Lawyer-offered legal services
See Database Schema for detailed table structures.

Design Patterns

Authentication Flow

// Client authenticates via Supabase Auth
const { data, error } = await supabase.auth.signInWithPassword({
  email,
  password
})

// Session stored in localStorage
// RLS policies enforce data access based on auth.uid()
All database queries use Row Level Security (RLS) policies. The client uses the anonymous key, which only grants access to data the authenticated user owns or is authorized to view.

Real-time Subscriptions

upLegal uses Supabase real-time channels for live updates:
// Subscribe to new messages in a conversation
supabase
  .channel(`conversation:${conversationId}`)
  .on(
    'postgres_changes',
    {
      event: 'INSERT',
      schema: 'public',
      table: 'messages',
      filter: `conversation_id=eq.${conversationId}`
    },
    (payload) => {
      // Handle new message
      addMessage(payload.new)
    }
  )
  .subscribe()

Payment Flow

  1. Client selects lawyer and time slot
  2. Frontend calls POST /create-payment on Express server
  3. Server creates MercadoPago preference with 10% platform fee
  4. Client redirected to MercadoPago checkout
  5. MercadoPago sends webhook to POST /api/mercadopago/webhook
  6. Server confirms booking and sends email notifications
  7. Appointment record created in database

Deployment Architecture

Frontend Deployment

Netlify
  • Static site hosting
  • Automatic deployments from Git
  • CDN distribution
  • Serverless redirects

Backend Deployment

Render
  • Express server hosting
  • Environment variables
  • Health check endpoint
  • Auto-scaling

Security Measures

Every database table has RLS policies that restrict access:
  • Users can only read/write their own profile
  • Lawyers can only see their own appointments
  • Messages are visible only to conversation participants
  • Admin operations require service role key
  • Supabase JWT tokens for authenticated requests
  • Service role key for server-side operations
  • CORS whitelist for allowed origins
  • Request validation and sanitization
  • MercadoPago handles all sensitive payment data
  • No credit card information stored in database
  • Webhook signature verification
  • Payment reconciliation for failed webhooks
  • User emails and phone numbers are private
  • File uploads scoped to authenticated users
  • Message encryption in transit (TLS)
  • GDPR-compliant data handling

Performance Optimizations

  • Code Splitting: React lazy loading for routes
  • Image Optimization: Supabase Storage CDN
  • Database Indexing: Indexed foreign keys and search fields
  • Query Optimization: React Query caching reduces API calls
  • Infinite Scroll: Virtual scrolling for large lists
  • Debouncing: Search input debouncing (300ms)

Monitoring & Logging

  • Google Analytics: User behavior tracking
  • Payment Logging: Custom payment event logger
  • Error Logging: Error boundary for React crashes
  • Server Logs: Express logging for API requests
  • Health Checks: /health endpoint for uptime monitoring

Next Steps

Tech Stack Details

Explore the complete technology stack

Database Schema

Detailed database table structures

Local Setup

Set up upLegal for local development

Deployment Guide

Deploy upLegal to production

Build docs developers (and LLMs) love