Bluewoo HRMS

Frontend Architecture

Next.js architecture principles and patterns

Frontend Architecture

Goal

Build a modern, performant Next.js 15 frontend with React 19 that prioritizes Server Components and minimal client-side state.

Technology Stack

  • Next.js 15 with App Router
  • React 19 with Server Components
  • Tailwind CSS 3.4 for styling
  • Shadcn/ui for accessible components
  • react-hook-form + Zod 3.x for forms

Project Structure

app/
├── (auth)/              # Public routes (login, register)
├── (dashboard)/         # Protected routes
│   ├── employees/
│   ├── time-off/
│   ├── documents/
│   ├── team/
│   ├── goals/
│   └── settings/
├── layout.tsx
└── page.tsx

components/
├── ui/                  # Shadcn components
├── forms/               # Form components
└── layout/              # Layout components

lib/
├── api.ts               # API client
└── utils.ts             # Utilities

Key Principles

Server Components First

  • Default to Server Components
  • Use Client Components only when needed (interactivity, hooks)
  • Fetch data on the server, pass to client as props
  • Next.js 15 Compatibility: Ensure all route parameters (params, searchParams) are awaited before use. This is a breaking change in Next.js 15.

State Management

State TypeSolutionExample
Server dataTanStack Query + Server ComponentsEmployee list, dashboard metrics
URL stateuseSearchParamsFilters, pagination, search
Local stateuseStateModal open/close, form inputs
Global stateReact Context (minimal)Theme, user preferences

No Redux/Zustand - TanStack Query, Server Components, and URL state cover most needs.

Server State with TanStack Query

For data that lives on the server and needs client-side interactivity, use TanStack Query (React Query v5):

// lib/queries/employees.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { api } from '@/lib/api'

// Fetch employees with caching
export function useEmployees(filters?: { departmentId?: string; status?: string }) {
  return useQuery({
    queryKey: ['employees', filters],
    queryFn: () => api.employees.list(filters),
    staleTime: 5 * 60 * 1000, // 5 minutes
  })
}

// Fetch single employee
export function useEmployee(id: string) {
  return useQuery({
    queryKey: ['employees', id],
    queryFn: () => api.employees.get(id),
    enabled: !!id,
  })
}

// Create employee with cache invalidation
export function useCreateEmployee() {
  const queryClient = useQueryClient()

  return useMutation({
    mutationFn: api.employees.create,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['employees'] })
    },
  })
}

When to use TanStack Query:

  • Data that multiple components need to share
  • Data that needs to be refetched on focus/reconnect
  • Optimistic updates (update UI before server confirms)
  • Infinite scroll/pagination
  • Real-time data synchronization

When to use Server Components instead:

  • Initial page load data (SSR)
  • Data that doesn't change during session
  • Static content with infrequent updates

Data Visualization

  • React Flow - Org chart visualization
  • Recharts - Dashboard charts and graphs
  • Use Server Components for initial data, hydrate on client for interactivity

Routing Patterns

  • Route Groups: (auth) for public, (dashboard) for protected
  • Dynamic Routes: [id] for resource pages
  • Layouts: Shared UI (nav, sidebar) persists across pages
  • Loading States: loading.tsx for suspense boundaries
  • Error Handling: error.tsx for error boundaries

Forms

  • Use react-hook-form for form state
  • Use Zod schemas for validation
  • Validate on submit (not on change)
  • Handle errors at field level

Pages to Build

PagePurpose
DashboardOverview metrics, pulse score, activity
EmployeesList, profiles, org chart
Time-OffRequests, calendar, balances
DocumentsUpload, search, access control
Team FeedPosts, comments, likes, AI summaries
GoalsPersonal, team, company goals
SettingsProfile, tenant configuration
AI ChatAssistant for policy questions

Component Guidelines

Shadcn/ui Components

  • Install as needed: npx shadcn-ui@latest add button
  • Components are copied to project (fully customizable)
  • Built on Radix UI primitives (accessible)

Component Organization

  • components/ui/ - Base Shadcn components
  • components/forms/ - Form-specific components
  • components/layout/ - Navigation, sidebar, etc.

Performance

  • Use Server Components for data fetching
  • Lazy load heavy components
  • Optimize images with Next.js Image
  • Use Suspense for loading states

Accessibility

  • Use semantic HTML
  • Include ARIA labels
  • Support keyboard navigation
  • Test with screen readers

Implementation details to be defined during development