Skip to main content

Frontend Architecture Overview

BonardaHR frontend follows a Domain-Driven Feature Module Architecture. Each business domain (such as Employees, Time Off, Attendance, Workflows) is self-contained with its own models, API services, query hooks, and UI components.


Architectural Principles

  1. Unidirectional Data Flow: UI components trigger mutations or queries; responses flow back through TanStack Query caches into reactive hooks.
  2. Separation of Concerns: Components never invoke Axios directly; they consume custom hooks which call typed service wrappers.
  3. Strict Type Safety: TypeScript is configured with verbatimModuleSyntax: true and strict: true.
  4. Co-location of Domain Logic: Types, API calls, hooks, and UI components belonging to a feature live together within src/features/<feature-name>.

Feature Module Structure

Every feature under src/features/ follows a standardized layered pattern:

src/features/<feature-name>/
├── types/
│ └── <feature>.types.ts # TypeScript interfaces, DTOs, request/response models
├── services/
│ └── <feature>Service.ts # Axios API wrappers (CRUD methods)
├── hooks/
│ └── use<Feature>.ts # TanStack Query useQuery and useMutation hooks
├── utils/ # Domain-specific helpers (date transforms, status formatters)
└── components/ # React UI components for the feature
├── ui/ # Sub-components specific to this feature
└── <Feature>Page.tsx # Top-level route component

Layer Responsibilities

┌────────────────────────────────────────┐
│ Component │ (Renders UI, collects user inputs)
└──────────────────┬─────────────────────┘
│ consumes
┌──────────────────▼─────────────────────┐
│ React Query Hook │ (Handles caching, loading, errors)
└──────────────────┬─────────────────────┘
│ calls
┌──────────────────▼─────────────────────┐
│ Service Layer │ (Formats endpoints, returns Promises)
└──────────────────┬─────────────────────┘
│ invokes
┌──────────────────▼─────────────────────┐
│ apiClient (Axios) │ (Injects Auth, Impersonation headers)
└──────────────────┬─────────────────────┘
│ HTTP
┌──────────────────▼─────────────────────┐
│ Backend API Gateway │
└────────────────────────────────────────┘

Root Application Composition (App.tsx)

The root App.tsx establishes the provider hierarchy required for global state, authentication, and routing:

// src/App.tsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { RouterProvider } from 'react-router-dom';
import { router } from './routes/AppRoutes';
import { AuthProvider } from './features/auth/providers/AuthProvider';
import { ImpersonationProvider } from './features/impersonation/providers/ImpersonationProvider';
import { Toaster } from 'sonner';

const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60 * 5, // 5 minutes default cache
retry: 1,
refetchOnWindowFocus: false,
},
},
});

export default function App() {
return (
<QueryClientProvider client={queryClient}>
<AuthProvider>
<ImpersonationProvider>
<RouterProvider router={router} />
<Toaster richColors position="top-right" />
</ImpersonationProvider>
</AuthProvider>
</QueryClientProvider>
);
}