Skip to main content

System Architecture & Overview

HRS is built with modern web technologies following a client-server architecture with RESTful API communication. This page explores the system’s technical design and structure.

Architecture Overview

High-Level Architecture

Frontend (Client)

React 18 Single Page Application
  • TypeScript for type safety
  • Vite for fast builds
  • TailwindCSS for styling
  • Radix UI components

Backend (API)

RESTful API Server
  • Basic Authentication
  • JSON data format
  • CORS enabled
  • Validation layer

State Management

Hybrid approach
  • TanStack Query for server state
  • React Context for auth state
  • Session storage for credentials

Data Layer

Relational Database
  • Students, Instructors, Horses
  • Classes with relationships
  • User accounts

Technology Stack

Frontend Technologies

From package.json:1:
{
  "name": "vite_react_shadcn_ts",
  "type": "module",
  "dependencies": {
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router-dom": "^6.30.1",
    "@tanstack/react-query": "^5.83.0",
    "typescript": "^5.8.3"
  }
}
React 18.3.1
  • Modern React with Hooks
  • Concurrent rendering
  • Automatic batching
  • Suspense support
TypeScript 5.8.3
  • Strong typing throughout
  • Interface definitions for all entities
  • Type-safe API calls
  • Enhanced IDE support

Key Libraries

From package.json:45:
{
  "date-fns": "^3.6.0",
  "exceljs": "^4.4.0",
  "file-saver": "^2.0.5",
  "recharts": "^2.15.4",
  "react-hook-form": "^7.61.1",
  "zod": "^3.25.76"
}

date-fns

Modern date utility library
  • Date formatting and parsing
  • Time calculations
  • Locale support
  • Lightweight and modular

ExcelJS

Professional Excel generation
  • Advanced formatting
  • Cell styling and colors
  • Comments and formulas
  • A4 print optimization

Recharts

Data visualization
  • Bar charts for distributions
  • Line charts for trends
  • Pie charts for percentages
  • Responsive and customizable

Zod

Schema validation
  • Runtime type checking
  • Form validation
  • API response validation
  • TypeScript integration

Application Structure

Project Organization

src/
├── components/          # React components
│   ├── auth/           # Authentication components
│   ├── calendar/       # Calendar views
│   ├── cards/          # Card components
│   ├── forms/          # Form components
│   └── ui/             # UI primitives (shadcn)
├── contexts/           # React contexts
│   └── AuthProvider    # Authentication context
├── hooks/              # Custom React hooks
│   ├── useCalendar     # Calendar logic
│   ├── useReportes     # Report generation
│   └── useValidar...   # Validation hooks
├── lib/                # Utilities and libraries
│   └── api.ts          # API client
├── pages/              # Route pages
│   ├── Index           # Dashboard
│   ├── Alumnos         # Students
│   ├── Instructores    # Instructors
│   ├── Caballos        # Horses
│   ├── Clases          # Classes
│   ├── Calendario      # Calendar
│   ├── Reportes        # Reports
│   └── Finanzas        # Finances
├── services/           # External services
│   └── authService     # Auth service
├── types/              # TypeScript types
│   └── enums.ts        # Enums and types
└── utils/              # Utility functions

Routing Architecture

From src/App.tsx:30:
const App = () => (
  <QueryClientProvider client={queryClient}>
    <AuthProvider>
      <TooltipProvider>
        <Toaster />
        <Sonner />
        <BrowserRouter>
          <IdleHandler />
          <Routes>
            <Route path="/login" element={<Login />} />
            <Route path="/register" element={<Register />} />
            <Route
              path="/"
              element={
                <ProtectedRoute>
                  <Index />
                </ProtectedRoute>
              }
            />
            {/* ... more protected routes */}
          </Routes>
        </BrowserRouter>
      </TooltipProvider>
    </AuthProvider>
  </QueryClientProvider>
);
Key Features:
  • Protected route wrapper for authentication
  • Nested provider architecture
  • Global notification systems (Toaster, Sonner)
  • Idle timeout handler
  • 404 catch-all route

API Architecture

RESTful API Design

From src/lib/api.ts:9:
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;

async function apiFetch(endpoint: string, options: RequestInit = {}) {
  const credentials = sessionStorage.getItem("authCredentials");
  
  const headers: Record<string, string> = {
    "Content-Type": "application/json",
    ...(options.headers as Record<string, string>),
  };
  
  if (credentials) {
    headers["Authorization"] = `Basic ${credentials}`;
  }
  
  return fetch(`${API_BASE_URL}${endpoint}`, {
    ...options,
    headers,
  });
}

API Endpoints

Error Handling

From src/lib/api.ts:157:
async function handleResponse<T>(response: Response): Promise<T> {
  if (response.status === 401) {
    sessionStorage.removeItem("authCredentials");
    sessionStorage.removeItem("user");
    window.location.href = "/login";
    throw new Error("Sesión no autorizada");
  }
  
  if (!response.ok) {
    const errorData: ApiErrorResponse = await response.json().catch(() => ({}));
    
    // Validation errors
    if (errorData.errores) {
      const mensajesValidacion = Object.values(errorData.errores).join(". ");
      throw new Error(mensajesValidacion);
    }
    
    // General error message
    const errorMessage =
      errorData.mensaje || errorData.error || `Error ${response.status}`;
    throw new Error(errorMessage);
  }
  
  return response.json();
}
Error Response Format:
export interface ApiErrorResponse {
  timestamp: string;
  status: number;
  error: string;
  mensaje: string;
  path: string;
  errores?: Record<string, string>;
}

Authentication System

Basic Auth Implementation

From src/services/authService.ts:54:
export const encodeCredentials = (
  username: string,
  password: string,
): string => {
  return btoa(`${username}:${password}`);
};

export const storeCredentials = (credentials: string, user: User): void => {
  sessionStorage.setItem("authCredentials", credentials);
  const { password, ...safeUser } = user;
  sessionStorage.setItem("user", JSON.stringify(safeUser));
};

User Model

From src/services/authService.ts:5:
export interface User {
  id: number;
  username: string;
  email: string;
  password: string;
  rol?: string;
  activo: boolean;
  fechaCreacion: string;
  avatarUrl?: string;
}

export type SafeUser = Omit<User, "password">;

Protected Routes

From src/components/auth/ProtectedRoute.tsx:
const ProtectedRoute = ({ children }: { children: React.ReactNode }) => {
  const credentials = sessionStorage.getItem("authCredentials");
  
  if (!credentials) {
    return <Navigate to="/login" replace />;
  }
  
  return <>{children}</>;
};

Idle Timeout

From src/components/auth/IdleHandler.tsx:
  • 15-minute inactivity timeout
  • Automatic logout
  • Activity tracking (mouse, keyboard, touch)
  • Warning before logout

State Management Strategy

Server State (TanStack Query)

const queryClient = new QueryClient();

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      {/* app */}
    </QueryClientProvider>
  );
}
Used for:
  • API data fetching
  • Caching API responses
  • Automatic refetching
  • Optimistic updates
  • Loading and error states

Client State (React Context)

From src/contexts/AuthProvider.tsx:
interface AuthContextType {
  user: SafeUser | null;
  login: (credentials: LoginCredentials) => Promise<void>;
  logout: () => Promise<void>;
  isAuthenticated: boolean;
}

const AuthContext = createContext<AuthContextType | undefined>(undefined);
Used for:
  • Authentication state
  • Current user information
  • Login/logout actions
  • Session management

Local Storage Strategy

Session Storage (temporary, cleared on tab close):
  • authCredentials - Encoded Basic Auth
  • user - Current user data (without password)
Local Storage (persistent):
  • Not used for sensitive data
  • Could be used for user preferences

Data Model & Relationships

Entity Relationship Diagram

Type Definitions

From src/types/enums.ts:
export type TipoPension = "SIN_CABALLO" | "RESERVA_ESCUELA" | "CABALLO_PROPIO";
export type CuotaPension = "ENTERA" | "MEDIA" | "TERCIO";
export type EspecialidadClase = "ADIESTRAMIENTO" | "EQUINOTERAPIA" | "EQUITACION" | "MONTA";
export type EstadoClase = "PROGRAMADA" | "INICIADA" | "COMPLETADA" | "CANCELADA" | "ACA" | "ASA";
export type TipoCaballo = "ESCUELA" | "PRIVADO";

Performance Optimizations

Code Splitting

  • Route-based code splitting
  • Lazy loading components
  • Reduced initial bundle size
  • Faster first paint

Query Caching

  • TanStack Query automatic caching
  • Stale-while-revalidate strategy
  • Background refetching
  • Reduced API calls

Build Optimization

  • Vite’s optimized builds
  • Tree shaking
  • Minification
  • Asset optimization

Responsive Design

  • Mobile-first approach
  • Responsive layouts
  • Touch-friendly interfaces
  • Adaptive components

Security Considerations

Security Measures Implemented:
  1. Authentication: Basic Auth over HTTPS
  2. Session Management: Auto-logout after 15 minutes
  3. Credentials Storage: Session storage (cleared on close)
  4. Protected Routes: Authentication required
  5. Input Validation: Client and server-side validation
  6. CORS: Proper CORS configuration
  7. No Password Storage: Passwords never stored in browser

Deployment Architecture

# Development
npm run dev          # Vite dev server with HMR

# Production Build
npm run build        # Optimized production build
npm run preview      # Preview production build locally
Build Output:
  • Minified JavaScript bundles
  • Optimized CSS
  • Asset hashing for cache busting
  • Source maps for debugging

This architecture provides a solid foundation for a scalable, maintainable equestrian school management system with modern development practices and excellent user experience.

Build docs developers (and LLMs) love