Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Rampop01/HR-Platform/llms.txt

Use this file to discover all available pages before exploring further.

Overview

HCMatrix uses a proxy-based API architecture to avoid CORS issues and centralize backend communication. All API requests flow through Next.js API routes that proxy to the backend server.
The API proxy is implemented in /app/api/proxy/[...path]/route.ts and automatically forwards requests to the configured backend.

Architecture

Why Use a Proxy?

CORS Prevention

Eliminates cross-origin request issues

Centralized Config

Single point for API configuration

Security

Hide backend URLs from client

Request Control

Modify requests/responses as needed

Configuration

Backend URL Setup

Configure the backend API URL in .env.local:
.env.local
API_BASE_URL=https://apitest.hcmatrix.co
This is a server-side only variable. It is not exposed to the browser, keeping your backend URL private.

Default Configuration

From app/api/proxy/[...path]/route.ts:3:
const API_BASE_URL = process.env.API_BASE_URL || 'https://apitest.hcmatrix.co'
If API_BASE_URL is not set, requests default to https://apitest.hcmatrix.co.

API Proxy Implementation

The proxy route handles all HTTP methods and forwards them to the backend. From app/api/proxy/[...path]/route.ts:5-58:
route.ts
async function proxyRequest(req: NextRequest) {
  // Extract the path after /api/proxy/
  const url = new URL(req.url)
  const pathSegments = url.pathname.replace('/api/proxy/', '')
  const targetUrl = `${API_BASE_URL}/${pathSegments}${url.search}`

  const headers: HeadersInit = {
    'Accept': 'application/json',
  }

  // Forward the Authorization header if present
  const authHeader = req.headers.get('Authorization')
  if (authHeader) {
    headers['Authorization'] = authHeader
  }

  const fetchOptions: RequestInit = {
    method: req.method,
    headers,
  }

  // Forward the body for POST/PUT/PATCH requests
  if (['POST', 'PUT', 'PATCH'].includes(req.method)) {
    headers['Content-Type'] = 'application/json'
    try {
      const body = await req.json()
      fetchOptions.body = JSON.stringify(body)
    } catch {
      // No body or invalid JSON — that's fine
    }
  }

  try {
    const response = await fetch(targetUrl, fetchOptions)
    const contentType = response.headers.get('content-type')
    let data: any

    if (contentType?.includes('application/json')) {
      data = await response.json()
    } else {
      const text = await response.text()
      data = { message: text }
    }

    return NextResponse.json(data, { status: response.status })
  } catch (error) {
    console.error('Proxy error:', error)
    return NextResponse.json(
      { message: 'Failed to connect to API server' },
      { status: 502 }
    )
  }
}

Supported HTTP Methods

The proxy supports all standard HTTP methods from route.ts:60-78:
export async function GET(req: NextRequest) {
  return proxyRequest(req)
}

Using the API Client

HCMatrix provides a centralized API client in lib/api.ts for all backend communication.

API Client Setup

From lib/api.ts:1-110:
api.ts
const PROXY_BASE = '/api/proxy'

async function apiCall<T>(
  endpoint: string,
  method: 'GET' | 'POST' = 'GET',
  body?: Record<string, unknown>,
  token?: string
): Promise<T> {
  const url = `${PROXY_BASE}${endpoint}`

  const headers: HeadersInit = {
    'Accept': 'application/json',
  }

  if (token) {
    headers['Authorization'] = `Bearer ${token}`
  }

  if (body) {
    headers['Content-Type'] = 'application/json'
  }

  const response = await fetch(url, {
    method,
    headers,
    body: body ? JSON.stringify(body) : undefined,
  })

  const contentType = response.headers.get('content-type')
  let responseData: any

  if (contentType?.includes('application/json')) {
    responseData = await response.json()
  } else {
    const text = await response.text()
    throw new Error(`API returned non-JSON response: ${response.status}`)
  }

  if (!response.ok) {
    const errorMessage =
      responseData?.message ||
      responseData?.error ||
      `API error: ${response.status}`
    throw new Error(errorMessage)
  }

  return responseData as T
}

Available API Methods

Login

Authenticate a user and receive a token:
import { api } from '@/lib/api'

const response = await api.login('user@example.com', 'password123')
// Returns: { user: {...}, token: "..." }

Logout

End user session:
await api.logout(token)

Type Definitions

The API client includes comprehensive TypeScript types for type safety.

Authentication Types

lib/api.ts
export interface LoginRequest {
  email: string
  password: string
}

export interface LoginResponse {
  user: {
    id: number
    name: string
    email: string
    [key: string]: any
  }
  token: string
}

Employee Types

lib/api.ts
export interface Employee {
  id: number
  name: string
  email: string
  job_title: string
  department: string
  location: string
  employment_type: string
  status: string
  start_date: string
  avatar?: string
}

export interface EmployeeDetail extends Employee {
  phone: string
  date_of_birth: string
  address: string
  salary: number
  manager: string
  manager_id: number
  next_of_kin_name: string
  next_of_kin_relationship: string
  next_of_kin_phone: string
  tenure_years: number
  tenure_months: number
  spouse: string | null
}

Authentication

Session Management

Authentication is handled via lib/auth.ts:1-41 using localStorage:
auth.ts
export interface AuthSession {
  token: string
  user: {
    id: number
    name: string
    email: string
  }
}

const SESSION_KEY = 'hcmatrix_session'

export const auth = {
  saveSession(session: AuthSession): void {
    if (typeof window !== 'undefined') {
      localStorage.setItem(SESSION_KEY, JSON.stringify(session))
    }
  },

  getSession(): AuthSession | null {
    if (typeof window !== 'undefined') {
      const session = localStorage.getItem(SESSION_KEY)
      return session ? JSON.parse(session) : null
    }
    return null
  },

  clearSession(): void {
    if (typeof window !== 'undefined') {
      localStorage.removeItem(SESSION_KEY)
    }
  },

  isAuthenticated(): boolean {
    return this.getSession() !== null
  },

  getToken(): string | null {
    return this.getSession()?.token || null
  },
}

Authentication Flow

1

User Login

Call api.login() with credentials:
const response = await api.login(email, password)
2

Save Session

Store the session in localStorage:
auth.saveSession({
  token: response.token,
  user: response.user
})
3

Use Token

Include token in subsequent API calls:
const token = auth.getToken()
const data = await api.getDashboard(token)
4

Logout

Clear session on logout:
await api.logout(token)
auth.clearSession()

Protected Routes

Protect pages by checking authentication status:
page.tsx
'use client'

import { useRouter } from 'next/navigation'
import { useEffect } from 'react'
import { auth } from '@/lib/auth'

export default function ProtectedPage() {
  const router = useRouter()

  useEffect(() => {
    if (!auth.getToken()) {
      router.push('/auth/login')
    }
  }, [router])

  // Page content...
}

Error Handling

The API client includes comprehensive error handling:

Connection Errors

When the backend is unreachable:
{
  "message": "Failed to connect to API server",
  "status": 502
}

API Errors

When the API returns an error:
try {
  await api.login(email, password)
} catch (error) {
  // Error message from API or generic error
  console.error(error.message)
}

Non-JSON Responses

If the API returns non-JSON content:
throw new Error(`API returned non-JSON response: ${response.status}`)

Best Practices

Always Use Types

Leverage TypeScript interfaces for type safety and autocomplete

Handle Errors

Wrap API calls in try/catch blocks and provide user feedback

Check Authentication

Verify token exists before making authenticated requests

Normalize Data

Use mapper functions to normalize API responses

Testing API Integration

Local Testing

Test the proxy with curl:
curl http://localhost:3000/api/proxy/api/auth/login \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"email":"test@example.com","password":"password"}'

Using Different Backends

Switch between environments:
API_BASE_URL=https://apitest.hcmatrix.co

Troubleshooting

Cause: Backend server is unreachableSolutions:
  • Verify API_BASE_URL is correct
  • Check backend server is running
  • Test backend URL directly in browser
Cause: Invalid or expired tokenSolutions:
  • Check token is being sent in Authorization header
  • Verify token hasn’t expired
  • Re-authenticate user
Cause: Bypassing the proxySolutions:
  • Always use /api/proxy/ prefix
  • Never call backend URL directly from frontend
  • Use the api client from lib/api.ts
Cause: API response doesn’t match TypeScript interfaceSolutions:
  • Check API documentation
  • Update type definitions
  • Use mapper functions to normalize data

Next Steps

Environment Setup

Complete environment configuration guide

Settings

Configure platform settings and preferences

Build docs developers (and LLMs) love